1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 /**
32  * Unit tests of the Initializer type.
33  */
34 
35 #include "mongo/base/init.h"
36 #include "mongo/base/initializer.h"
37 #include "mongo/base/initializer_dependency_graph.h"
38 #include "mongo/base/make_string_vector.h"
39 #include "mongo/unittest/unittest.h"
40 
41 /*
42  * Unless otherwise specified, all tests herein use the following
43  * dependency graph.
44  *
45  * 0 <-  3 <- 7
46  *  ^   / ^    ^
47  *   \ v   \     \
48  *    2     5 <-  8
49  *   / ^   /     /
50  *  v   \ v    v
51  * 1 <-  4 <- 6
52  *
53  */
54 
55 #define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
56     (GRAPH).addInitializer(                             \
57         (NAME), (FN), MONGO_MAKE_STRING_VECTOR PREREQS, MONGO_MAKE_STRING_VECTOR DEPS)
58 
59 #define ASSERT_ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
60     ASSERT_EQUALS(Status::OK(), ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS))
61 
62 
63 #define CONSTRUCT_DEPENDENCY_GRAPH(GRAPH, FN0, FN1, FN2, FN3, FN4, FN5, FN6, FN7, FN8)           \
64     do {                                                                                         \
65         InitializerDependencyGraph& _graph_ = (GRAPH);                                           \
66         ASSERT_ADD_INITIALIZER(_graph_, "n0", FN0, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS); \
67         ASSERT_ADD_INITIALIZER(_graph_, "n1", FN1, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS); \
68         ASSERT_ADD_INITIALIZER(_graph_, "n2", FN2, ("n0", "n1"), MONGO_NO_DEPENDENTS);           \
69         ASSERT_ADD_INITIALIZER(_graph_, "n3", FN3, ("n0", "n2"), MONGO_NO_DEPENDENTS);           \
70         ASSERT_ADD_INITIALIZER(_graph_, "n4", FN4, ("n2", "n1"), MONGO_NO_DEPENDENTS);           \
71         ASSERT_ADD_INITIALIZER(_graph_, "n5", FN5, ("n3", "n4"), MONGO_NO_DEPENDENTS);           \
72         ASSERT_ADD_INITIALIZER(_graph_, "n6", FN6, ("n4"), MONGO_NO_DEPENDENTS);                 \
73         ASSERT_ADD_INITIALIZER(_graph_, "n7", FN7, ("n3"), MONGO_NO_DEPENDENTS);                 \
74         ASSERT_ADD_INITIALIZER(_graph_, "n8", FN8, ("n5", "n6", "n7"), MONGO_NO_DEPENDENTS);     \
75     } while (false)
76 
77 namespace mongo {
78 namespace {
79 
80 int globalCounts[9];
81 
doNothing(InitializerContext *)82 Status doNothing(InitializerContext*) {
83     return Status::OK();
84 }
85 
set0(InitializerContext *)86 Status set0(InitializerContext*) {
87     globalCounts[0] = 1;
88     return Status::OK();
89 }
90 
set1(InitializerContext *)91 Status set1(InitializerContext*) {
92     globalCounts[1] = 1;
93     return Status::OK();
94 }
95 
set2(InitializerContext *)96 Status set2(InitializerContext*) {
97     if (!globalCounts[0] || !globalCounts[1])
98         return Status(ErrorCodes::UnknownError, "one of 0 or 1 not already set");
99     globalCounts[2] = 1;
100     return Status::OK();
101 }
102 
set3(InitializerContext *)103 Status set3(InitializerContext*) {
104     if (!globalCounts[0] || !globalCounts[2])
105         return Status(ErrorCodes::UnknownError, "one of 0 or 2 not already set");
106     globalCounts[3] = 1;
107     return Status::OK();
108 }
109 
set4(InitializerContext *)110 Status set4(InitializerContext*) {
111     if (!globalCounts[1] || !globalCounts[2])
112         return Status(ErrorCodes::UnknownError, "one of 1 or 2 not already set");
113     globalCounts[4] = 1;
114     return Status::OK();
115 }
116 
set5(InitializerContext *)117 Status set5(InitializerContext*) {
118     if (!globalCounts[3] || !globalCounts[4])
119         return Status(ErrorCodes::UnknownError, "one of 3 or 4 not already set");
120     globalCounts[5] = 1;
121     return Status::OK();
122 }
123 
set6(InitializerContext *)124 Status set6(InitializerContext*) {
125     if (!globalCounts[4])
126         return Status(ErrorCodes::UnknownError, "4 not already set");
127     globalCounts[6] = 1;
128     return Status::OK();
129 }
130 
set7(InitializerContext *)131 Status set7(InitializerContext*) {
132     if (!globalCounts[3])
133         return Status(ErrorCodes::UnknownError, "3 not already set");
134     globalCounts[7] = 1;
135     return Status::OK();
136 }
137 
set8(InitializerContext *)138 Status set8(InitializerContext*) {
139     if (!globalCounts[5] || !globalCounts[6] || !globalCounts[7])
140         return Status(ErrorCodes::UnknownError, "one of 5, 6, 7 not already set");
141     globalCounts[8] = 1;
142     return Status::OK();
143 }
144 
clearCounts()145 void clearCounts() {
146     for (size_t i = 0; i < 9; ++i)
147         globalCounts[i] = 0;
148 }
149 
TEST(InitializerTest,SuccessfulInitialization)150 TEST(InitializerTest, SuccessfulInitialization) {
151     Initializer initializer;
152     CONSTRUCT_DEPENDENCY_GRAPH(initializer.getInitializerDependencyGraph(),
153                                set0,
154                                set1,
155                                set2,
156                                set3,
157                                set4,
158                                set5,
159                                set6,
160                                set7,
161                                set8);
162     clearCounts();
163     ASSERT_OK(initializer.execute(InitializerContext::ArgumentVector(),
164                                   InitializerContext::EnvironmentMap()));
165     for (int i = 0; i < 9; ++i)
166         ASSERT_EQUALS(1, globalCounts[i]);
167 }
168 
TEST(InitializerTest,Step5Misimplemented)169 TEST(InitializerTest, Step5Misimplemented) {
170     Initializer initializer;
171     CONSTRUCT_DEPENDENCY_GRAPH(initializer.getInitializerDependencyGraph(),
172                                set0,
173                                set1,
174                                set2,
175                                set3,
176                                set4,
177                                doNothing,
178                                set6,
179                                set7,
180                                set8);
181     clearCounts();
182     ASSERT_EQUALS(ErrorCodes::UnknownError,
183                   initializer.execute(InitializerContext::ArgumentVector(),
184                                       InitializerContext::EnvironmentMap()));
185     ASSERT_EQUALS(1, globalCounts[0]);
186     ASSERT_EQUALS(1, globalCounts[1]);
187     ASSERT_EQUALS(1, globalCounts[2]);
188     ASSERT_EQUALS(1, globalCounts[3]);
189     ASSERT_EQUALS(1, globalCounts[4]);
190     ASSERT_EQUALS(0, globalCounts[8]);
191 }
192 
193 }  // namespace
194 }  // namespace mongo
195