|
4 | 4 |
|
5 | 5 | import ROOT |
6 | 6 |
|
| 7 | +# Helper function to assert that the elements of an array object and a std::vector proxy are equal |
| 8 | +def assertVec(vec, arr): |
| 9 | + # cppyy automatically casts random integers to unicode characters, |
| 10 | + # so do the same in python so the validation doesn't fail |
| 11 | + if isinstance(arr, array.array) and arr.typecode in ("b", "B"): |
| 12 | + arr = [chr(b) for b in arr] |
| 13 | + |
| 14 | + tc = unittest.TestCase() |
| 15 | + # first check lengths match |
| 16 | + tc.assertEqual(len(vec), len(arr), f"Length mismatch: std::vector is {len(vec)}, array is {len(arr)}") |
| 17 | + |
| 18 | + tc.assertSequenceEqual(vec, arr, msg="std::vector and array differ, iadd failed") |
| 19 | + |
7 | 20 |
|
8 | 21 | class STL_vector(unittest.TestCase): |
9 | 22 | """ |
@@ -45,6 +58,77 @@ def test_stl_vector_boolean(self): |
45 | 58 | self.assertFalse(vector.empty()) |
46 | 59 | self.assertTrue(bool(vector)) |
47 | 60 |
|
| 61 | + def test_stl_vector_iadd(self): |
| 62 | + import array |
| 63 | + import random |
| 64 | + """ |
| 65 | + Test that the __iadd__ pythonization of std::vector works as expected. |
| 66 | + This call dispatches to std::insert |
| 67 | + https://github.com/root-project/root/issues/18768 |
| 68 | + """ |
| 69 | + |
| 70 | + # we go over all possible numeric PODs |
| 71 | + # https://docs.python.org/3/library/array.html |
| 72 | + entry_type = [ |
| 73 | + "char", |
| 74 | + "unsigned char", |
| 75 | + "short", |
| 76 | + "unsigned short", |
| 77 | + "int", |
| 78 | + "unsigned int", |
| 79 | + "long", |
| 80 | + "unsigned long", |
| 81 | + "long long", |
| 82 | + "float", |
| 83 | + "double", |
| 84 | + ] |
| 85 | + array_type = ["b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d"] |
| 86 | + |
| 87 | + typemap = zip(entry_type, array_type) |
| 88 | + n = 5 |
| 89 | + for dtype in typemap: |
| 90 | + vec = ROOT.std.vector[dtype[0]]() |
| 91 | + self.assertTrue(vec.empty()) |
| 92 | + li = [random.randint(1, 100) for _ in range(n)] |
| 93 | + arr = array.array(dtype[1], li) |
| 94 | + vec += arr |
| 95 | + self.assertFalse(vec.empty()) |
| 96 | + assertVec(vec, arr) |
| 97 | + vec.pop_back() |
| 98 | + arr = arr[:-1] |
| 99 | + assertVec(vec, arr) |
| 100 | + |
| 101 | + def test_stl_vector_iadd_2D(self): |
| 102 | + """ |
| 103 | + Test that the __iadd__ pythonization of std::vector works as expected in 2D |
| 104 | + """ |
| 105 | + initial = [ |
| 106 | + [1, 2, 3], |
| 107 | + [4, 5, 6], |
| 108 | + [7, 8, 9], |
| 109 | + ] |
| 110 | + |
| 111 | + vec2d = ROOT.std.vector[ROOT.std.vector[int]](initial) |
| 112 | + self.assertEqual( |
| 113 | + len(vec2d), len(initial), f"Initial 2D vector row count wrong ({len(vec2d)} vs {len(initial)})" |
| 114 | + ) |
| 115 | + |
| 116 | + # verify rows before iadd |
| 117 | + for idx, (subvec, sublist) in enumerate(zip(vec2d, initial)): |
| 118 | + with self.subTest(row=idx, phase="before"): |
| 119 | + assertVec(subvec, sublist) |
| 120 | + |
| 121 | + vec2d += initial |
| 122 | + expected = initial + initial |
| 123 | + |
| 124 | + self.assertEqual( |
| 125 | + len(vec2d), len(expected), f"2D vector row count after iadd wrong ({len(vec2d)} vs {len(expected)})" |
| 126 | + ) |
| 127 | + |
| 128 | + for idx, (subvec, sublist) in enumerate(zip(vec2d, expected)): |
| 129 | + with self.subTest(row=idx, phase="after"): |
| 130 | + assertVec(subvec, sublist) |
| 131 | + |
48 | 132 | def test_tree_with_containers(self): |
49 | 133 | """ |
50 | 134 | Test that the boolean conversion of a std::vector works as expected inside a TTree. |
|
0 commit comments