|
13 | 13 | // for std::accumulate |
14 | 14 | #include <numeric> |
15 | 15 |
|
16 | | -// for std::sort, std::is_sorted |
| 16 | +// for std::sort, std::is_sorted, std::find_if, std::transform, std::copy_if |
17 | 17 | #include <algorithm> |
18 | 18 |
|
| 19 | +// for std::back_inserter |
| 20 | +#include <iterator> |
| 21 | + |
| 22 | +// for std::to_string |
| 23 | +#include <string> |
| 24 | + |
19 | 25 | #include "cunit.h" |
| 26 | +#include "xobject.h" |
20 | 27 |
|
21 | 28 | using namespace std; |
22 | 29 |
|
@@ -55,10 +62,262 @@ void TestArraySort() { |
55 | 62 | Assert(std::is_sorted(v.begin(), v.end())); |
56 | 63 | } |
57 | 64 |
|
| 65 | +void TestArrayFind() { |
| 66 | + // Demonstrate finding elements in an xarray |
| 67 | + xarray v; |
| 68 | + v.push_back(xnode::value_of(10)); |
| 69 | + v.push_back(xnode::value_of(20)); |
| 70 | + v.push_back(xnode::value_of(30)); |
| 71 | + v.push_back(xnode::value_of(40)); |
| 72 | + v.push_back(xnode::value_of("test string")); |
| 73 | + v.push_back(xnode::value_of(true)); |
| 74 | + |
| 75 | + // Find using find_if with a lambda - finding a specific int value |
| 76 | + auto it = std::find_if(v.begin(), v.end(), [](const xnode& n) { |
| 77 | + return n.is<int>() && n.get_as<int>() == 30; |
| 78 | + }); |
| 79 | + Assert(it != v.end(), "Failed to find element with value 30"); |
| 80 | + Assert(it->get_as<int>() == 30, "Found element has incorrect value"); |
| 81 | + |
| 82 | + // Find using find_if with a lambda - finding a string |
| 83 | + auto strIt = std::find_if(v.begin(), v.end(), [](const xnode& n) { |
| 84 | + return n.is<std::string>() && n.get_as<std::string>() == "test string"; |
| 85 | + }); |
| 86 | + Assert(strIt != v.end(), "Failed to find element with string value"); |
| 87 | + Assert(strIt->get_as<std::string>() == "test string", "Found string element has incorrect value"); |
| 88 | + |
| 89 | + // Count elements of a specific type |
| 90 | + int intCount = std::count_if(v.begin(), v.end(), [](const xnode& n) { return n.is<int>(); }); |
| 91 | + Assert(intCount == 4, "Incorrect count of int elements"); |
| 92 | +} |
| 93 | + |
| 94 | +void TestArrayTransform() { |
| 95 | + // Demonstrate transforming an xarray |
| 96 | + xarray source; |
| 97 | + source.push_back(xnode::value_of(1)); |
| 98 | + source.push_back(xnode::value_of(2)); |
| 99 | + source.push_back(xnode::value_of(3)); |
| 100 | + source.push_back(xnode::value_of(4)); |
| 101 | + source.push_back(xnode::value_of(5)); |
| 102 | + |
| 103 | + // Transform to a new array with doubled values |
| 104 | + xarray result; |
| 105 | + result.reserve(source.size()); |
| 106 | + |
| 107 | + std::transform(source.begin(), source.end(), std::back_inserter(result), |
| 108 | + [](const xnode& n) { return xnode::value_of(n.get_as<int>() * 2); }); |
| 109 | + |
| 110 | + // Verify transformation |
| 111 | + Assert(result.size() == source.size(), "Result size should match source size"); |
| 112 | + for (size_t i = 0; i < source.size(); ++i) { |
| 113 | + Assert(result[i].get_as<int>() == source[i].get_as<int>() * 2, |
| 114 | + "Transformed value should be double the original"); |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +void TestArrayMixedTypes() { |
| 119 | + // Demonstrate storing and processing mixed data types in an xarray |
| 120 | + xarray v; |
| 121 | + |
| 122 | + // Add different types |
| 123 | + v.push_back(xnode::value_of(42)); // int |
| 124 | + v.push_back(xnode::value_of(3.14159)); // double |
| 125 | + v.push_back(xnode::value_of("Hello, world!")); // string |
| 126 | + v.push_back(xnode::value_of(true)); // bool |
| 127 | + |
| 128 | + // Create a long value explicitly to avoid ambiguity |
| 129 | + xnode longNode; |
| 130 | + long longValue = 1000000L; |
| 131 | + longNode.set_as(longValue); |
| 132 | + v.push_back(longNode); // long |
| 133 | + |
| 134 | + // Check types and values |
| 135 | + Assert(v[0].is<int>(), "Element 0 should be an int"); |
| 136 | + Assert(v[1].is<double>(), "Element 1 should be a double"); |
| 137 | + Assert(v[2].is<std::string>(), "Element 2 should be a string"); |
| 138 | + Assert(v[3].is<bool>(), "Element 3 should be a bool"); |
| 139 | + Assert(v[4].is<long>(), "Element 4 should be a long"); |
| 140 | + |
| 141 | + // Create a string representation of each element |
| 142 | + std::vector<std::string> stringReps; |
| 143 | + for (const auto& node : v) { |
| 144 | + if (node.is<std::string>()) { |
| 145 | + stringReps.push_back(node.get_as<std::string>()); |
| 146 | + } else if (node.is<int>()) { |
| 147 | + stringReps.push_back("Int: " + std::to_string(node.get_as<int>())); |
| 148 | + } else if (node.is<double>()) { |
| 149 | + stringReps.push_back("Double: " + std::to_string(node.get_as<double>())); |
| 150 | + } else if (node.is<bool>()) { |
| 151 | + stringReps.push_back(node.get_as<bool>() ? "Bool: true" : "Bool: false"); |
| 152 | + } else if (node.is<long>()) { |
| 153 | + stringReps.push_back("Long: " + std::to_string(node.get_as<long>())); |
| 154 | + } |
| 155 | + } |
| 156 | + |
| 157 | + // Verify string representations |
| 158 | + Assert(stringReps.size() == 5, "Should have 5 string representations"); |
| 159 | + Assert(stringReps[0] == "Int: 42", "First string rep should be 'Int: 42'"); |
| 160 | + Assert(stringReps[3] == "Bool: true", "Fourth string rep should be 'Bool: true'"); |
| 161 | +} |
| 162 | + |
| 163 | +void TestArrayFilter() { |
| 164 | + // Demonstrate filtering an array |
| 165 | + xarray original; |
| 166 | + for (int i = 1; i <= 10; ++i) { |
| 167 | + original.push_back(xnode::value_of(i)); |
| 168 | + } |
| 169 | + |
| 170 | + // Create a filtered copy with only even numbers |
| 171 | + xarray evens; |
| 172 | + std::copy_if(original.begin(), original.end(), std::back_inserter(evens), |
| 173 | + [](const xnode& n) { return n.get_as<int>() % 2 == 0; }); |
| 174 | + |
| 175 | + // Verify filter results |
| 176 | + Assert(evens.size() == 5, "Filtered array should have 5 elements"); |
| 177 | + for (const auto& n : evens) { |
| 178 | + Assert(n.get_as<int>() % 2 == 0, "All elements should be even"); |
| 179 | + } |
| 180 | +} |
| 181 | + |
| 182 | +void TestArrayNestedStructures() { |
| 183 | + // Demonstrate an xarray containing other containers (objects and arrays) |
| 184 | + xarray root; |
| 185 | + |
| 186 | + // Add primitive types |
| 187 | + root.push_back(xnode::value_of(1)); |
| 188 | + root.push_back(xnode::value_of("root level string")); |
| 189 | + |
| 190 | + // Create and add an object |
| 191 | + xobject obj; |
| 192 | + obj.put("name", xnode::value_of(std::string("test object"))); |
| 193 | + obj.put("value", xnode::value_of(42)); |
| 194 | + root.push_back(xnode::value_of(obj)); |
| 195 | + |
| 196 | + // Create and add a nested array |
| 197 | + xarray nested; |
| 198 | + nested.push_back(xnode::value_of(10)); |
| 199 | + nested.push_back(xnode::value_of(20)); |
| 200 | + nested.push_back(xnode::value_of("nested string")); |
| 201 | + root.push_back(xnode::value_of(nested)); |
| 202 | + |
| 203 | + // Verify root structure |
| 204 | + Assert(root.size() == 4, "Root array should have 4 elements"); |
| 205 | + Assert(root[0].is<int>(), "First element should be int"); |
| 206 | + Assert(root[1].is<std::string>(), "Second element should be string"); |
| 207 | + Assert(root[2].is<xobject>(), "Third element should be xobject"); |
| 208 | + Assert(root[3].is<xarray>(), "Fourth element should be xarray"); |
| 209 | + |
| 210 | + // Verify object content |
| 211 | + Assert(root[2].get_ptr<xobject>()->contains("name"), "Object should contain 'name' property"); |
| 212 | + Assert(root[2].get_ptr<xobject>()->get("value").get_as<int>() == 42, "Object 'value' should be 42"); |
| 213 | + |
| 214 | + // Verify nested array content |
| 215 | + Assert(root[3].get_ptr<xarray>()->size() == 3, "Nested array should have 3 elements"); |
| 216 | + Assert(root[3].get_ptr<xarray>()->at(2).get_as<std::string>() == "nested string", |
| 217 | + "Nested array string element has wrong value"); |
| 218 | +} |
| 219 | + |
| 220 | +void TestArrayCopy() { |
| 221 | + // Demonstrate copying and comparing arrays |
| 222 | + xarray original; |
| 223 | + original.reserve(3); |
| 224 | + original.push_back(xnode::value_of(1)); |
| 225 | + original.push_back(xnode::value_of(2)); |
| 226 | + original.push_back(xnode::value_of(3)); |
| 227 | + |
| 228 | + // Test copying using vector's copy constructor |
| 229 | + xarray copy(original); |
| 230 | + |
| 231 | + // Verify the copy |
| 232 | + Assert(copy.size() == original.size(), "Copy size should match original"); |
| 233 | + for (size_t i = 0; i < original.size(); ++i) { |
| 234 | + Assert(copy[i].get_as<int>() == original[i].get_as<int>(), |
| 235 | + "Copy values should match original"); |
| 236 | + } |
| 237 | + |
| 238 | + // Modify the copy and ensure original is unchanged |
| 239 | + copy[0].set_as(100); |
| 240 | + Assert(original[0].get_as<int>() == 1, "Original should be unchanged"); |
| 241 | + Assert(copy[0].get_as<int>() == 100, "Copy should be modified"); |
| 242 | +} |
| 243 | + |
| 244 | +void TestArrayIteration() { |
| 245 | + // Demonstrate various ways to iterate through an xarray |
| 246 | + xarray v; |
| 247 | + v.push_back(xnode::value_of(10)); |
| 248 | + v.push_back(xnode::value_of(20)); |
| 249 | + v.push_back(xnode::value_of(30)); |
| 250 | + |
| 251 | + // Method 1: Index-based for loop |
| 252 | + int sum1 = 0; |
| 253 | + for (size_t i = 0; i < v.size(); ++i) { |
| 254 | + sum1 += v[i].get_as<int>(); |
| 255 | + } |
| 256 | + Assert(sum1 == 60, "Index-based sum should be 60"); |
| 257 | + |
| 258 | + // Method 2: Iterator-based for loop |
| 259 | + int sum2 = 0; |
| 260 | + for (xarray::iterator it = v.begin(); it != v.end(); ++it) { |
| 261 | + sum2 += it->get_as<int>(); |
| 262 | + } |
| 263 | + Assert(sum2 == 60, "Iterator-based sum should be 60"); |
| 264 | + |
| 265 | + // Method 3: Range-based for loop (C++11) |
| 266 | + int sum3 = 0; |
| 267 | + for (const auto& node : v) { |
| 268 | + sum3 += node.get_as<int>(); |
| 269 | + } |
| 270 | + Assert(sum3 == 60, "Range-based sum should be 60"); |
| 271 | + |
| 272 | + // Method 4: Use STL algorithm |
| 273 | + int sum4 = 0; |
| 274 | + std::for_each(v.begin(), v.end(), [&sum4](const xnode& node) { |
| 275 | + sum4 += node.get_as<int>(); |
| 276 | + }); |
| 277 | + Assert(sum4 == 60, "STL algorithm sum should be 60"); |
| 278 | +} |
| 279 | + |
| 280 | +void TestArrayManipulation() { |
| 281 | + // Demonstrate various vector manipulation operations on xarray |
| 282 | + xarray v; |
| 283 | + |
| 284 | + // Test push_back |
| 285 | + v.push_back(xnode::value_of(1)); |
| 286 | + v.push_back(xnode::value_of(2)); |
| 287 | + Assert(v.size() == 2, "Size should be 2 after push_back"); |
| 288 | + |
| 289 | + // Test insert |
| 290 | + v.insert(v.begin() + 1, xnode::value_of(3)); |
| 291 | + Assert(v.size() == 3, "Size should be 3 after insert"); |
| 292 | + Assert(v[1].get_as<int>() == 3, "Inserted value should be 3"); |
| 293 | + |
| 294 | + // Test erase |
| 295 | + v.erase(v.begin()); |
| 296 | + Assert(v.size() == 2, "Size should be 2 after erase"); |
| 297 | + Assert(v[0].get_as<int>() == 3, "First value should be 3 after erase"); |
| 298 | + |
| 299 | + // Test clear |
| 300 | + v.clear(); |
| 301 | + Assert(v.empty(), "Array should be empty after clear"); |
| 302 | + |
| 303 | + // Test resize |
| 304 | + v.resize(3, xnode::value_of(5)); |
| 305 | + Assert(v.size() == 3, "Size should be 3 after resize"); |
| 306 | + Assert(v[0].get_as<int>() == 5, "Resized element should have default value"); |
| 307 | +} |
| 308 | + |
58 | 309 | int xarray_test() { |
59 | 310 | TEST_PROLOG(); |
60 | 311 | TEST_FUNC(ArraySum); |
61 | 312 | TEST_FUNC(ArraySort); |
| 313 | + TEST_FUNC(ArrayFind); |
| 314 | + TEST_FUNC(ArrayTransform); |
| 315 | + TEST_FUNC(ArrayMixedTypes); |
| 316 | + TEST_FUNC(ArrayFilter); |
| 317 | + TEST_FUNC(ArrayNestedStructures); |
| 318 | + TEST_FUNC(ArrayCopy); |
| 319 | + TEST_FUNC(ArrayIteration); |
| 320 | + TEST_FUNC(ArrayManipulation); |
62 | 321 | TEST_EPILOG(); |
63 | 322 | } |
64 | 323 |
|
|
0 commit comments