def test_set_sub(self): t = TSet(INT) s1 = Bag((0, 1)) s2 = Bag((1, 0)) e = EEq(EBinOp(EVar("s1").with_type(t), "-", EVar("s2").with_type(t)), EEmptyList().with_type(t)) assert retypecheck(e) assert eval(e, {"s1": s1, "s2": s2}) is True
def test_heap_equality(self): t = TMinHeap(BOOL, INT) env = { "h1": Bag(((False, 7), (False, 13), (False, 13))), "h2": Bag(((False, 13), (False, 13), (False, 7))), } assert eval(EEq(EVar("h1").with_type(t), EVar("h2").with_type(t)), env)
def random_value(t): """ Construct a stream of values in type t """ if isinstance(t, TBag): yield Bag() for v in random_value(t.elem_type): yield Bag((v, )) for v1 in random_value(t.elem_type): for v2 in random_value(t.elem_type): yield Bag((v1, v2)) elif isinstance(t, TInt): yield random.randint(0, 100) yield 0 elif isinstance(t, TNative): yield (t.name, 0) elif isinstance(t, TFloat): yield random.randint(0, 100) / 100.0 yield 0.0 elif isinstance(t, TBool): yield True yield False elif isinstance(t, TString): yield ''.join(random.choice(string.ascii_letters) for _ in range(8)) elif isinstance(t, TRecord): iterables = [random_value(ty) for _, ty in t.fields] for vs in product(*iterables): yield FrozenDict({field[0]: v for v, field in zip(vs, t.fields)}) else: raise Exception( "Unknown type for random value construction: {}".format(t))
def test_distinct_order(self): env = { "xs": Bag([0, 1, 0]), } e = EUnaryOp(UOp.Distinct, EVar("xs").with_type(INT_BAG)).with_type(INT_BAG) self.assertEqual(eval(e, env), Bag([0, 1]))
def test_heap_enumeration(self): xs = EVar("xs").with_type(INT_BAG) context = RootCtx(state_vars=[xs]) cost_model = CostModel() def not_min_or_max(e, *args, **kwargs): # forbid min/max to ensure that heap operations get cached if isinstance(e, EArgMin) or isinstance(e, EArgMax): return False return True enumerator = Enumerator(examples=[{ "xs": Bag(()) }, { "xs": Bag((1, 2)) }, { "xs": Bag((1, 1)) }], cost_model=cost_model, check_wf=not_min_or_max) with save_property(accelerate, "value"): accelerate.value = False print("-" * 20 + " Looking for xs...") found_xs = False for e in enumerator.enumerate(context, 0, STATE_POOL): print(pprint(e)) if e == xs: assert retypecheck(deep_copy(e)) found_xs = True print("^^^ FOUND") assert found_xs print("-" * 20 + " Looking for heap construction...") found_make_heap = False for e in enumerator.enumerate(context, 1, STATE_POOL): print(pprint(e)) if isinstance(e, EMakeMinHeap) or isinstance(e, EMakeMaxHeap): assert retypecheck(deep_copy(e)) found_make_heap = True print("^^^ FOUND") assert found_make_heap print("-" * 20 + " Looking for heap usage...") found_heap_peek = False for e in enumerator.enumerate(context, 2, RUNTIME_POOL): print(pprint(e)) if isinstance(e, EHeapPeek) or isinstance(e, EHeapPeek2): assert retypecheck(deep_copy(e)) found_heap_peek = True print("^^^ FOUND") assert found_heap_peek
def test_deep_eq(self): t = THandle("H", INT) h1 = Handle(address=0, value=0) h2 = Handle(address=0, value=1) assert h1 != h2 assert values_equal(t, h1, h2) h3 = Handle(address=1, value=0) b1 = Bag((h1, h3, h3)) b2 = Bag((h3, h2, h3)) assert b1 != b2 assert values_equal(TBag(t), b1, b2)
def unaryop_distinct(stk): v = stk.pop() res = [] for x in v: if not any(values_equal(elem_type, x, y) for y in res): res.append(x) stk.append(Bag(res))
def test_fingerprint_subset(self): inp = {"x": Bag([1])} e1 = EVar("x").with_type(INT_BAG) e2 = EEmptyList().with_type(e1.type) fp1 = Fingerprint.of(e1, [inp]) fp2 = Fingerprint.of(e2, [inp]) self.assertNotEqual(fp1, fp2) assert not fp1.subset_of(fp2) assert fp2.subset_of(fp1)
def binaryop_sub_bags(stk): v2 = stk.pop() v1 = stk.pop() elems = list(v1) for x in v2: for i in range(len(elems)): if values_equal(elem_type, x, elems[i]): del elems[i] break stk.append(Bag(elems))
def test_state_pool_boundary(self): """ When enumerating expressions, we shouldn't ever enumerate state expressions in a context where some binders are runtime variables. """ class TestEnumerator(Enumerator): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.state_enumerations = 0 def _enumerate_core(self, context, size, pool): print("_enumerate_core({}, {}, {})".format( context, size, pool)) if pool == STATE_POOL: self.state_enumerations += 1 return super()._enumerate_core(context, size, pool) state_bag = EVar("state").with_type(INT_BAG) context = RootCtx(state_vars=[state_bag], args=[EVar("arg").with_type(INT)]) enumerator = TestEnumerator(examples=[{ "state": Bag([10]), "arg": 10 }, { "state": Bag([20]), "arg": 30 }], cost_model=CostModel()) for e in enumerator.enumerate(context, 1, RUNTIME_POOL): pass for e in enumerator.enumerate( UnderBinder(context, EVar("x").with_type(INT), EStateVar(state_bag).with_type(state_bag.type), RUNTIME_POOL), 1, RUNTIME_POOL): pass assert enumerator.state_enumerations == 1
def do_concat(stk): v = stk.pop() stk.append(Bag(elem for bag in v for elem in bag))
def binaryop_add_sets(stk): v2 = stk.pop() v1 = stk.pop() stk.append(Bag(unique(itertools.chain(v1, v2))))
def binaryop_add_collections(stk): v2 = stk.pop() v1 = stk.pop() stk.append(Bag(itertools.chain(v1, v2)))
def read_map_keys(stk): stk.append(Bag(stk.pop().keys()))
def iterable_to_bag(stk): stk.append(Bag(stk.pop()))
def make_singleton_bag(stk): stk.append(Bag((stk.pop(),)))
def list_index(default): def _list_index(stk): i = stk.pop() l = stk.pop() stk.append( l[i] if i >= 0 and i < len(l) else default) return _list_index def list_slice(stk): end = max(stk.pop(), 0) start = max(stk.pop(), 0) l = stk.pop() stk.append(l[start:end]) _EMPTY_BAG = Bag() def _compile(e, env : {str:int}, out): if isinstance(e, EVar): i = env[e.id] if isinstance(i, int): def load_var(stk): stk.append(stk[i]) out.append(load_var) else: def load_bound(stk): stk.append(i()) out.append(load_bound) elif isinstance(e, EBool): out.append(push_true if e.val else push_false) elif isinstance(e, ENum): s = e.val
def test_bag_equality(self): b1 = Bag(((False, 10), (False, 12), (False, 6))) b2 = Bag(((False, 6), (False, 12), (False, 10))) assert b1 != b2
def test_bag_equality_with_tuple(self): assert (0, 1, 2) == Bag((0, 1, 2)) assert Bag((0, 1, 2)) == (0, 1, 2)