|
14 | 14 | import unittest
|
15 | 15 |
|
16 | 16 | from constrainedrandom import RandObj
|
| 17 | +from .. import testutils |
17 | 18 |
|
18 | 19 |
|
19 | 20 | class NonPureFunction(unittest.TestCase):
|
@@ -48,3 +49,48 @@ def non_pure_constraint(a):
|
48 | 49 | # after c.var is assigned.
|
49 | 50 | c.var = 5
|
50 | 51 | r.randomize()
|
| 52 | + |
| 53 | + |
| 54 | +class RandSizeListOrder(testutils.RandObjTestBase): |
| 55 | + ''' |
| 56 | + Minimal test that hits a specific corner case involving |
| 57 | + random list length. |
| 58 | + The case requires: |
| 59 | + - more than one list depending on the same random length |
| 60 | + - a small total state space |
| 61 | + - the lists are constrained based on one another and the random length |
| 62 | + - a constraint that uses the random length to index the lists |
| 63 | + - fails with naive solver, or skips it |
| 64 | + - fails with sparsities == 1, or manually run with sparsities > 1 |
| 65 | + The symptom seen was IndexError: list index out of range |
| 66 | + when applying the constraint. |
| 67 | + ''' |
| 68 | + |
| 69 | + ITERATIONS = 100 |
| 70 | + |
| 71 | + def get_randobj(self, *args): |
| 72 | + r = RandObj(*args) |
| 73 | + r.add_rand_var('length', domain=range(1,3), order=0) |
| 74 | + r.add_rand_var('list1', domain=range(-10,11), rand_length='length', order=1) |
| 75 | + r.add_rand_var('list2', domain=range(-10,11), rand_length='length', order=2) |
| 76 | + |
| 77 | + def var_not_in_list(length, list1, list2): |
| 78 | + # Use length as an index, as this is how the bug |
| 79 | + # was found in the wild. |
| 80 | + for i in range(length): |
| 81 | + if list1[i] == list2[i]: |
| 82 | + return False |
| 83 | + return True |
| 84 | + r.add_constraint(var_not_in_list, ('length', 'list1', 'list2')) |
| 85 | + r.set_solver_mode(naive=False, sparsities=[10]) |
| 86 | + return r |
| 87 | + |
| 88 | + def check(self, results): |
| 89 | + for result in results: |
| 90 | + length = result['length'] |
| 91 | + list1 = result['list1'] |
| 92 | + list2 = result['list2'] |
| 93 | + self.assertEqual(len(list1), length, "list1 length was wrong") |
| 94 | + self.assertEqual(len(list2), length, "list2 length was wrong") |
| 95 | + for x1, x2 in zip(list1, list2): |
| 96 | + self.assertFalse(x1 == x2) |
0 commit comments