Line data Source code
1 : #define BOOST_TEST_DYN_LINK
2 : #define BOOST_TEST_MODULE (WorkflowIntegration test)
3 :
4 : #include <boost/test/unit_test.hpp>
5 :
6 : #include <cstdlib>
7 : #include <ctime>
8 : #include <iostream>
9 : #include <memory>
10 : #include <string>
11 : #include <vector>
12 :
13 : #include "../DatabaseConfigurationInterface.h"
14 :
15 : using namespace ots;
16 :
17 : struct WorkflowIntegrationTestData {
18 2 : WorkflowIntegrationTestData() {
19 2 : srand(time(nullptr));
20 2 : baseVersion = rand() % 99999 + 100000;
21 2 : std::cout << "=== WORKFLOW INTEGRATION TEST SUITE ===\n";
22 2 : std::cout << "Base version: " << baseVersion << "\n\n";
23 2 : }
24 :
25 2 : ~WorkflowIntegrationTestData() { std::cout << "\n=== TEST SUITE COMPLETE ===\n"; }
26 :
27 : int baseVersion;
28 : };
29 :
30 : WorkflowIntegrationTestData fixture;
31 :
32 : BOOST_AUTO_TEST_SUITE(workflow_integration_test)
33 :
34 4 : BOOST_AUTO_TEST_CASE(complete_crud_lifecycle) {
35 2 : std::cout << "\n=== TEST 1: Complete CRUD lifecycle ===\n";
36 :
37 2 : auto ifc = DatabaseConfigurationInterface();
38 2 : int version1 = fixture.baseVersion;
39 2 : int version2 = fixture.baseVersion + 1;
40 :
41 2 : std::shared_ptr<ConfigurationBase> cfg = std::make_shared<TestConfiguration001>();
42 2 : cfg->getView().version = version1;
43 4 : cfg->getView().fillFromJSON("{\"stage\": \"created\"}");
44 2 : auto createResult = ifc.saveActiveVersion(cfg.get());
45 2 : BOOST_REQUIRE_EQUAL(createResult, 0);
46 2 : std::cout << "Step 1 (CREATE): Saved version " << version1 << "\n";
47 :
48 2 : std::shared_ptr<ConfigurationBase> readCfg = std::make_shared<TestConfiguration001>();
49 2 : auto readResult = ifc.fill(readCfg.get(), version1);
50 2 : BOOST_REQUIRE_EQUAL(readResult, 0);
51 2 : bool hasCreated = (readCfg->getView()._json.find("created") != std::string::npos);
52 2 : BOOST_CHECK(hasCreated);
53 2 : std::cout << "Step 2 (READ): Loaded version " << version1 << ", has 'created': " << (hasCreated ? "yes" : "no") << "\n";
54 :
55 2 : cfg->getView().version = version2;
56 4 : cfg->getView().fillFromJSON("{\"stage\": \"updated\"}");
57 2 : auto updateResult = ifc.saveActiveVersion(cfg.get());
58 2 : BOOST_REQUIRE_EQUAL(updateResult, 0);
59 2 : std::cout << "Step 3 (UPDATE): Saved version " << version2 << "\n";
60 :
61 2 : auto versions = ifc.getVersions(cfg.get());
62 2 : bool hasV1 = (versions.find(version1) != versions.end());
63 2 : bool hasV2 = (versions.find(version2) != versions.end());
64 2 : BOOST_CHECK(hasV1);
65 2 : BOOST_CHECK(hasV2);
66 2 : std::cout << "Step 4 (VERIFY): Has v1: " << (hasV1 ? "yes" : "no") << ", Has v2: " << (hasV2 ? "yes" : "no") << "\n";
67 :
68 2 : std::cout << " Verified: Complete CRUD lifecycle works\n";
69 2 : }
70 :
71 4 : BOOST_AUTO_TEST_CASE(version_promotion_workflow) {
72 2 : std::cout << "\n=== TEST 2: Version promotion workflow ===\n";
73 :
74 2 : auto ifc = DatabaseConfigurationInterface();
75 2 : int testVersion = fixture.baseVersion + 10;
76 2 : std::string suffix = "_" + std::to_string(fixture.baseVersion);
77 :
78 2 : std::shared_ptr<ConfigurationBase> cfg = std::make_shared<TestConfiguration001>();
79 2 : cfg->getView().version = testVersion;
80 4 : cfg->getView().fillFromJSON("{\"environment\": \"development\"}");
81 2 : ifc.saveActiveVersion(cfg.get());
82 2 : std::cout << "Step 1: Created development version " << testVersion << "\n";
83 :
84 2 : auto map = DatabaseConfigurationInterface::config_version_map_t{};
85 2 : map[cfg->getConfigurationName()] = testVersion;
86 2 : ifc.storeGlobalConfiguration(map, "Development" + suffix);
87 2 : std::cout << "Step 2: Created Development composition\n";
88 :
89 2 : ifc.storeGlobalConfiguration(map, "Staging" + suffix);
90 2 : std::cout << "Step 3: Promoted to Staging composition\n";
91 :
92 2 : ifc.storeGlobalConfiguration(map, "Production" + suffix);
93 2 : std::cout << "Step 4: Promoted to Production composition\n";
94 :
95 2 : auto devLoaded = ifc.loadGlobalConfiguration("Development" + suffix);
96 2 : auto stagingLoaded = ifc.loadGlobalConfiguration("Staging" + suffix);
97 2 : auto prodLoaded = ifc.loadGlobalConfiguration("Production" + suffix);
98 :
99 2 : BOOST_CHECK_EQUAL(devLoaded[cfg->getConfigurationName()], testVersion);
100 2 : BOOST_CHECK_EQUAL(stagingLoaded[cfg->getConfigurationName()], testVersion);
101 2 : BOOST_CHECK_EQUAL(prodLoaded[cfg->getConfigurationName()], testVersion);
102 :
103 2 : std::cout << "Step 5: All compositions reference version " << testVersion << "\n";
104 2 : std::cout << " Verified: Version promotion workflow works\n";
105 2 : }
106 :
107 4 : BOOST_AUTO_TEST_CASE(rollback_simulation) {
108 2 : std::cout << "\n=== TEST 3: Rollback simulation ===\n";
109 :
110 2 : auto ifc = DatabaseConfigurationInterface();
111 2 : int goodVersion = fixture.baseVersion + 20;
112 2 : int badVersion = fixture.baseVersion + 21;
113 2 : std::string compName = "RollbackTest_" + std::to_string(fixture.baseVersion);
114 :
115 2 : std::shared_ptr<ConfigurationBase> cfg = std::make_shared<TestConfiguration001>();
116 2 : cfg->getView().version = goodVersion;
117 4 : cfg->getView().fillFromJSON("{\"status\": \"good_version\"}");
118 2 : ifc.saveActiveVersion(cfg.get());
119 2 : std::cout << "Step 1: Created good version " << goodVersion << "\n";
120 :
121 2 : cfg->getView().version = badVersion;
122 4 : cfg->getView().fillFromJSON("{\"status\": \"bad_version\"}");
123 2 : ifc.saveActiveVersion(cfg.get());
124 2 : std::cout << "Step 2: Created bad version " << badVersion << "\n";
125 :
126 2 : auto map = DatabaseConfigurationInterface::config_version_map_t{};
127 2 : map[cfg->getConfigurationName()] = badVersion;
128 2 : ifc.storeGlobalConfiguration(map, compName);
129 2 : std::cout << "Step 3: Created composition pointing to bad version\n";
130 :
131 2 : auto loaded1 = ifc.loadGlobalConfiguration(compName);
132 2 : BOOST_CHECK_EQUAL(loaded1[cfg->getConfigurationName()], badVersion);
133 :
134 2 : map[cfg->getConfigurationName()] = goodVersion;
135 2 : ifc.storeGlobalConfiguration(map, compName, true);
136 2 : std::cout << "Step 4: Rolled back composition to good version\n";
137 :
138 2 : auto loaded2 = ifc.loadGlobalConfiguration(compName);
139 2 : BOOST_CHECK_EQUAL(loaded2[cfg->getConfigurationName()], goodVersion);
140 :
141 2 : std::cout << "Step 5: Verified composition now points to version " << loaded2[cfg->getConfigurationName()] << "\n";
142 2 : std::cout << " Verified: Rollback simulation works\n";
143 2 : }
144 :
145 4 : BOOST_AUTO_TEST_CASE(parallel_development_branches) {
146 2 : std::cout << "\n=== TEST 4: Parallel development branches ===\n";
147 :
148 2 : auto ifc = DatabaseConfigurationInterface();
149 2 : std::string suffix = "_" + std::to_string(fixture.baseVersion);
150 :
151 2 : std::shared_ptr<ConfigurationBase> cfg = std::make_shared<TestConfiguration001>();
152 :
153 2 : int mainVersion = fixture.baseVersion + 30;
154 2 : cfg->getView().version = mainVersion;
155 4 : cfg->getView().fillFromJSON("{\"branch\": \"main\"}");
156 2 : ifc.saveActiveVersion(cfg.get());
157 :
158 8 : for (int i = 0; i < 3; i++) {
159 6 : cfg->getView().version = fixture.baseVersion + 100 + i;
160 6 : cfg->getView().fillFromJSON("{\"branch\": \"featureA\", \"iteration\": " + std::to_string(i) + "}");
161 6 : ifc.saveActiveVersion(cfg.get());
162 : }
163 :
164 8 : for (int i = 0; i < 3; i++) {
165 6 : cfg->getView().version = fixture.baseVersion + 200 + i;
166 6 : cfg->getView().fillFromJSON("{\"branch\": \"featureB\", \"iteration\": " + std::to_string(i) + "}");
167 6 : ifc.saveActiveVersion(cfg.get());
168 : }
169 2 : std::cout << "Step 1: Created versions for main, featureA, and featureB\n";
170 :
171 8 : auto mainMap = DatabaseConfigurationInterface::config_version_map_t{{cfg->getConfigurationName(), mainVersion}};
172 8 : auto featureAMap = DatabaseConfigurationInterface::config_version_map_t{{cfg->getConfigurationName(), fixture.baseVersion + 102}};
173 8 : auto featureBMap = DatabaseConfigurationInterface::config_version_map_t{{cfg->getConfigurationName(), fixture.baseVersion + 202}};
174 :
175 2 : ifc.storeGlobalConfiguration(mainMap, "Main" + suffix);
176 2 : ifc.storeGlobalConfiguration(featureAMap, "FeatureA" + suffix);
177 2 : ifc.storeGlobalConfiguration(featureBMap, "FeatureB" + suffix);
178 2 : std::cout << "Step 2: Created compositions for each branch\n";
179 :
180 2 : auto mainLoaded = ifc.loadGlobalConfiguration("Main" + suffix);
181 2 : auto featureALoaded = ifc.loadGlobalConfiguration("FeatureA" + suffix);
182 2 : auto featureBLoaded = ifc.loadGlobalConfiguration("FeatureB" + suffix);
183 :
184 2 : BOOST_CHECK_EQUAL(mainLoaded[cfg->getConfigurationName()], mainVersion);
185 2 : BOOST_CHECK_EQUAL(featureALoaded[cfg->getConfigurationName()], fixture.baseVersion + 102);
186 2 : BOOST_CHECK_EQUAL(featureBLoaded[cfg->getConfigurationName()], fixture.baseVersion + 202);
187 :
188 4 : std::cout << "Step 3: Main=" << mainLoaded[cfg->getConfigurationName()] << ", FeatureA=" << featureALoaded[cfg->getConfigurationName()]
189 2 : << ", FeatureB=" << featureBLoaded[cfg->getConfigurationName()] << "\n";
190 2 : std::cout << " Verified: Parallel development branches work independently\n";
191 14 : }
192 :
193 4 : BOOST_AUTO_TEST_CASE(composition_evolution_history) {
194 2 : std::cout << "\n=== TEST 5: Composition evolution history ===\n";
195 :
196 2 : auto ifc = DatabaseConfigurationInterface();
197 2 : std::string compName = "Evolving_" + std::to_string(fixture.baseVersion);
198 :
199 2 : std::shared_ptr<ConfigurationBase> cfg1 = std::make_shared<TestConfiguration001>();
200 2 : std::shared_ptr<ConfigurationBase> cfg2 = std::make_shared<TestConfiguration002>();
201 :
202 2 : cfg1->getView().version = fixture.baseVersion + 40;
203 2 : cfg2->getView().version = fixture.baseVersion + 40;
204 2 : ifc.saveActiveVersion(cfg1.get());
205 2 : ifc.saveActiveVersion(cfg2.get());
206 :
207 2 : cfg1->getView().version = fixture.baseVersion + 41;
208 2 : ifc.saveActiveVersion(cfg1.get());
209 2 : std::cout << "Step 1: Created configuration versions\n";
210 :
211 2 : auto map = DatabaseConfigurationInterface::config_version_map_t{};
212 2 : map[cfg1->getConfigurationName()] = fixture.baseVersion + 40;
213 2 : ifc.storeGlobalConfiguration(map, compName);
214 :
215 2 : auto loaded1 = ifc.loadGlobalConfiguration(compName);
216 2 : std::cout << "Step 2: Initial composition has " << loaded1.size() << " member(s)\n";
217 2 : BOOST_CHECK_EQUAL(loaded1.size(), 1);
218 :
219 2 : map[cfg2->getConfigurationName()] = fixture.baseVersion + 40;
220 2 : ifc.storeGlobalConfiguration(map, compName, true);
221 :
222 2 : auto loaded2 = ifc.loadGlobalConfiguration(compName);
223 2 : std::cout << "Step 3: After adding member, has " << loaded2.size() << " member(s)\n";
224 2 : BOOST_CHECK_EQUAL(loaded2.size(), 2);
225 :
226 2 : map[cfg1->getConfigurationName()] = fixture.baseVersion + 41;
227 2 : ifc.storeGlobalConfiguration(map, compName, true);
228 :
229 2 : auto loaded3 = ifc.loadGlobalConfiguration(compName);
230 2 : std::cout << "Step 4: After version update, type1 version is " << loaded3[cfg1->getConfigurationName()] << "\n";
231 2 : BOOST_CHECK_EQUAL(loaded3[cfg1->getConfigurationName()], fixture.baseVersion + 41);
232 2 : BOOST_CHECK_EQUAL(loaded3.size(), 2);
233 :
234 2 : map.erase(cfg2->getConfigurationName());
235 2 : ifc.storeGlobalConfiguration(map, compName, true);
236 :
237 2 : auto loaded4 = ifc.loadGlobalConfiguration(compName);
238 2 : std::cout << "Step 5: After removing member, has " << loaded4.size() << " member(s)\n";
239 2 : BOOST_CHECK_EQUAL(loaded4.size(), 1);
240 2 : BOOST_CHECK_EQUAL(loaded4[cfg1->getConfigurationName()], fixture.baseVersion + 41);
241 :
242 2 : std::cout << " Verified: Composition evolution works correctly\n";
243 2 : }
244 :
245 : BOOST_AUTO_TEST_SUITE_END()
|