Line data Source code
1 : #define BOOST_TEST_DYN_LINK
2 : #define BOOST_TEST_MODULE (CaseSensitivity test)
3 :
4 : #include <boost/test/unit_test.hpp>
5 :
6 : #include <algorithm>
7 : #include <iostream>
8 : #include <memory>
9 : #include <set>
10 : #include <string>
11 :
12 : #include "../DatabaseConfigurationInterface.h"
13 :
14 : using namespace ots;
15 :
16 : struct CaseSensitivityTestData {
17 2 : CaseSensitivityTestData() {
18 2 : srand(time(nullptr));
19 2 : baseVersion = rand() % 99999 + 100000;
20 2 : std::cout << "=== CASE SENSITIVITY VERIFICATION TEST SUITE ===\n";
21 2 : std::cout << "Base version: " << baseVersion << "\n\n";
22 2 : }
23 :
24 2 : ~CaseSensitivityTestData() { std::cout << "\n=== TEST SUITE COMPLETE ===\n"; }
25 :
26 : int baseVersion;
27 : };
28 :
29 : CaseSensitivityTestData fixture;
30 :
31 : BOOST_AUTO_TEST_SUITE(case_sensitivity_test)
32 :
33 4 : BOOST_AUTO_TEST_CASE(different_cases_create_different_compositions) {
34 2 : std::cout << "\n=== TEST 1: Different cases create different compositions ===\n";
35 :
36 2 : auto ifc = DatabaseConfigurationInterface();
37 :
38 2 : int version1 = fixture.baseVersion;
39 :
40 2 : std::shared_ptr<ConfigurationBase> cfg1 = std::make_shared<TestConfiguration001>();
41 2 : cfg1->getView().version = version1;
42 2 : auto result1 = ifc.saveActiveVersion(cfg1.get());
43 2 : BOOST_CHECK_EQUAL(result1, 0);
44 :
45 2 : std::cout << "Created configuration version: " << version1 << "\n";
46 :
47 2 : auto compositionMap = DatabaseConfigurationInterface::config_version_map_t{};
48 2 : compositionMap[cfg1->getConfigurationName()] = version1;
49 :
50 4 : std::string name1 = "RunConfig";
51 4 : std::string name2 = "runconfig";
52 2 : std::string name3 = "RUNCONFIG";
53 :
54 2 : std::cout << "Creating compositions with different cases:\n";
55 2 : std::cout << " 1. '" << name1 << "'\n";
56 2 : std::cout << " 2. '" << name2 << "'\n";
57 2 : std::cout << " 3. '" << name3 << "'\n";
58 :
59 2 : ifc.storeGlobalConfiguration(compositionMap, name1);
60 2 : ifc.storeGlobalConfiguration(compositionMap, name2);
61 2 : ifc.storeGlobalConfiguration(compositionMap, name3);
62 :
63 2 : auto allCompositions = ifc.findAllGlobalConfigurations();
64 :
65 2 : bool found1 = (allCompositions.find(name1) != allCompositions.end());
66 2 : bool found2 = (allCompositions.find(name2) != allCompositions.end());
67 2 : bool found3 = (allCompositions.find(name3) != allCompositions.end());
68 :
69 2 : std::cout << "Results:\n";
70 2 : std::cout << " '" << name1 << "' found: " << (found1 ? "YES" : "NO") << "\n";
71 2 : std::cout << " '" << name2 << "' found: " << (found2 ? "YES" : "NO") << "\n";
72 2 : std::cout << " '" << name3 << "' found: " << (found3 ? "YES" : "NO") << "\n";
73 :
74 2 : BOOST_CHECK_EQUAL(found1, true);
75 2 : BOOST_CHECK_EQUAL(found2, true);
76 2 : BOOST_CHECK_EQUAL(found3, true);
77 :
78 2 : std::cout << " Verified: All three compositions exist independently\n";
79 2 : }
80 :
81 4 : BOOST_AUTO_TEST_CASE(case_sensitive_lookup) {
82 2 : std::cout << "\n=== TEST 2: Case-sensitive lookup ===\n";
83 :
84 2 : auto ifc = DatabaseConfigurationInterface();
85 :
86 2 : int version1 = fixture.baseVersion + 10;
87 :
88 2 : std::shared_ptr<ConfigurationBase> cfg1 = std::make_shared<TestConfiguration001>();
89 2 : cfg1->getView().version = version1;
90 2 : ifc.saveActiveVersion(cfg1.get());
91 :
92 2 : auto compositionMap = DatabaseConfigurationInterface::config_version_map_t{};
93 2 : compositionMap[cfg1->getConfigurationName()] = version1;
94 :
95 2 : std::string exactName = "TestComp_Case";
96 2 : ifc.storeGlobalConfiguration(compositionMap, exactName);
97 :
98 2 : std::cout << "Created composition: '" << exactName << "'\n";
99 :
100 2 : std::cout << "Loading with exact case: '" << exactName << "'...\n";
101 : try {
102 2 : auto loadedMap = ifc.loadGlobalConfiguration(exactName);
103 2 : BOOST_CHECK_EQUAL(loadedMap.size(), 1);
104 2 : std::cout << " SUCCESS: Loaded composition with exact case\n";
105 2 : } catch (std::exception const& e) {
106 0 : BOOST_FAIL("Failed to load with exact case: " << e.what());
107 0 : }
108 :
109 2 : std::string wrongCase = "testcomp_case";
110 2 : std::cout << "Loading with different case: '" << wrongCase << "'...\n";
111 :
112 2 : bool loadedWithWrongCase = true;
113 : try {
114 2 : auto loadedMap = ifc.loadGlobalConfiguration(wrongCase);
115 0 : loadedWithWrongCase = true;
116 0 : std::cout << " UNEXPECTED: Loaded with different case (case-insensitive!)\n";
117 2 : } catch (std::exception const& e) {
118 2 : loadedWithWrongCase = false;
119 2 : std::cout << " EXPECTED: Failed to load with different case (case-sensitive)\n";
120 2 : }
121 :
122 2 : BOOST_CHECK_EQUAL(loadedWithWrongCase, false);
123 2 : }
124 :
125 4 : BOOST_AUTO_TEST_CASE(case_sensitive_search) {
126 2 : std::cout << "\n=== TEST 3: Case-sensitive search ===\n";
127 :
128 2 : auto ifc = DatabaseConfigurationInterface();
129 :
130 2 : int version1 = fixture.baseVersion + 20;
131 :
132 2 : std::shared_ptr<ConfigurationBase> cfg1 = std::make_shared<TestConfiguration001>();
133 2 : cfg1->getView().version = version1;
134 2 : ifc.saveActiveVersion(cfg1.get());
135 :
136 2 : auto compositionMap = DatabaseConfigurationInterface::config_version_map_t{};
137 2 : compositionMap[cfg1->getConfigurationName()] = version1;
138 :
139 4 : std::string name1 = "SearchTest_ABC";
140 2 : std::string name2 = "SearchTest_abc";
141 :
142 2 : ifc.storeGlobalConfiguration(compositionMap, name1);
143 2 : ifc.storeGlobalConfiguration(compositionMap, name2);
144 :
145 2 : std::cout << "Created compositions:\n";
146 2 : std::cout << " 1. '" << name1 << "'\n";
147 2 : std::cout << " 2. '" << name2 << "'\n";
148 :
149 2 : std::cout << "Searching for exact match: '" << name1 << "'\n";
150 2 : auto results1 = ifc.findAllGlobalConfigurations(name1);
151 :
152 2 : std::cout << "Found " << results1.size() << " result(s)\n";
153 :
154 2 : if (results1.size() == 1) {
155 2 : std::cout << " CASE-SENSITIVE: Found only exact match\n";
156 2 : BOOST_CHECK_EQUAL(results1.size(), 1);
157 0 : } else if (results1.size() == 2) {
158 0 : std::cout << " CASE-INSENSITIVE: Found both variations (potential bug)\n";
159 0 : BOOST_WARN_MESSAGE(false, "Search appears to be case-insensitive");
160 : }
161 :
162 2 : bool foundExact = (results1.find(name1) != results1.end());
163 2 : BOOST_CHECK_EQUAL(foundExact, true);
164 2 : }
165 :
166 4 : BOOST_AUTO_TEST_CASE(case_preservation_in_storage) {
167 2 : std::cout << "\n=== TEST 4: Case preservation in storage ===\n";
168 :
169 2 : auto ifc = DatabaseConfigurationInterface();
170 :
171 2 : int version1 = fixture.baseVersion + 30;
172 :
173 2 : std::shared_ptr<ConfigurationBase> cfg1 = std::make_shared<TestConfiguration001>();
174 2 : cfg1->getView().version = version1;
175 2 : ifc.saveActiveVersion(cfg1.get());
176 :
177 2 : auto compositionMap = DatabaseConfigurationInterface::config_version_map_t{};
178 2 : compositionMap[cfg1->getConfigurationName()] = version1;
179 :
180 2 : std::string originalName = "MixedCase_TeStNaMe_123";
181 2 : ifc.storeGlobalConfiguration(compositionMap, originalName);
182 :
183 2 : std::cout << "Stored composition with name: '" << originalName << "'\n";
184 :
185 2 : auto allCompositions = ifc.findAllGlobalConfigurations();
186 :
187 2 : bool foundWithOriginalCase = (allCompositions.find(originalName) != allCompositions.end());
188 :
189 2 : std::cout << "Searching for composition in returned list...\n";
190 2 : std::cout << " Original case '" << originalName << "' found: " << (foundWithOriginalCase ? "YES" : "NO") << "\n";
191 :
192 2 : BOOST_CHECK_EQUAL(foundWithOriginalCase, true);
193 :
194 2 : auto loadedMap = ifc.loadGlobalConfiguration(originalName);
195 2 : BOOST_CHECK_EQUAL(loadedMap.size(), 1);
196 :
197 2 : std::cout << " Verified: Case is preserved in storage and retrieval\n";
198 2 : }
199 :
200 4 : BOOST_AUTO_TEST_CASE(configuration_type_names_case_sensitive) {
201 2 : std::cout << "\n=== TEST 5: Configuration type names case-sensitive ===\n";
202 :
203 2 : auto ifc = DatabaseConfigurationInterface();
204 :
205 2 : std::shared_ptr<ConfigurationBase> cfg1 = std::make_shared<TestConfiguration001>();
206 2 : std::string actualTypeName = cfg1->getConfigurationName();
207 :
208 2 : std::cout << "Actual configuration type name: '" << actualTypeName << "'\n";
209 :
210 2 : int version1 = fixture.baseVersion + 40;
211 2 : cfg1->getView().version = version1;
212 2 : ifc.saveActiveVersion(cfg1.get());
213 :
214 2 : auto compositionMap = DatabaseConfigurationInterface::config_version_map_t{};
215 2 : compositionMap[actualTypeName] = version1;
216 :
217 2 : std::string compName = "TypeNameTest_" + std::to_string(fixture.baseVersion);
218 2 : ifc.storeGlobalConfiguration(compositionMap, compName);
219 :
220 2 : std::cout << "Created composition with type: '" << actualTypeName << "'\n";
221 :
222 2 : auto loadedMap = ifc.loadGlobalConfiguration(compName);
223 :
224 2 : bool foundExactType = (loadedMap.find(actualTypeName) != loadedMap.end());
225 :
226 2 : std::cout << "Loaded composition, checking for exact type name...\n";
227 2 : std::cout << " Found '" << actualTypeName << "': " << (foundExactType ? "YES" : "NO") << "\n";
228 :
229 2 : BOOST_CHECK_EQUAL(foundExactType, true);
230 2 : BOOST_CHECK_EQUAL(loadedMap.size(), 1);
231 :
232 2 : std::cout << " All configuration types in composition:\n";
233 4 : for (auto const& entry : loadedMap) {
234 2 : std::cout << " - '" << entry.first << "' -> version " << entry.second << "\n";
235 : }
236 :
237 2 : std::cout << " Verified: Configuration type names are case-sensitive\n";
238 2 : }
239 :
240 4 : BOOST_AUTO_TEST_CASE(case_sensitive_reverse_lookup) {
241 2 : std::cout << "\n=== TEST 6: Case-sensitive reverse lookup ===\n";
242 :
243 2 : auto ifc = DatabaseConfigurationInterface();
244 :
245 2 : int version1 = fixture.baseVersion + 50;
246 :
247 2 : std::shared_ptr<ConfigurationBase> cfg1 = std::make_shared<TestConfiguration001>();
248 2 : cfg1->getView().version = version1;
249 2 : ifc.saveActiveVersion(cfg1.get());
250 :
251 2 : std::string configTypeName = cfg1->getConfigurationName();
252 :
253 2 : auto compositionMap = DatabaseConfigurationInterface::config_version_map_t{};
254 2 : compositionMap[configTypeName] = version1;
255 :
256 4 : std::string comp1Name = "ReverseTest_ABC";
257 2 : std::string comp2Name = "ReverseTest_abc";
258 :
259 2 : ifc.storeGlobalConfiguration(compositionMap, comp1Name);
260 2 : ifc.storeGlobalConfiguration(compositionMap, comp2Name);
261 :
262 2 : std::cout << "Created compositions:\n";
263 2 : std::cout << " 1. '" << comp1Name << "'\n";
264 2 : std::cout << " 2. '" << comp2Name << "'\n";
265 :
266 2 : auto foundCompositions = ifc.findCompositionsContaining(configTypeName, std::to_string(version1));
267 :
268 2 : std::cout << "Reverse lookup for version " << version1 << " found " << foundCompositions.size() << " compositions\n";
269 :
270 2 : BOOST_CHECK_EQUAL(foundCompositions.size(), 2);
271 :
272 2 : bool found1 = (foundCompositions.find(comp1Name) != foundCompositions.end());
273 2 : bool found2 = (foundCompositions.find(comp2Name) != foundCompositions.end());
274 :
275 2 : std::cout << " Found '" << comp1Name << "': " << (found1 ? "YES" : "NO") << "\n";
276 2 : std::cout << " Found '" << comp2Name << "': " << (found2 ? "YES" : "NO") << "\n";
277 :
278 2 : BOOST_CHECK_EQUAL(found1, true);
279 2 : BOOST_CHECK_EQUAL(found2, true);
280 :
281 6 : for (auto const& compName : foundCompositions) {
282 4 : std::cout << " - '" << compName << "'\n";
283 :
284 4 : if (compName == comp1Name) {
285 2 : std::cout << " Matches '" << comp1Name << "' exactly (case preserved)\n";
286 2 : } else if (compName == comp2Name) {
287 2 : std::cout << " Matches '" << comp2Name << "' exactly (case preserved)\n";
288 : }
289 : }
290 :
291 2 : std::cout << " Verified: Reverse lookup preserves case in composition names\n";
292 2 : }
293 :
294 : BOOST_AUTO_TEST_SUITE_END()
|