def process_hook(state: State) -> None: # We can't remove because the globally applied hooks are stored in # the Manticore class, not State self.assertFalse(state.remove_hook(0x400610, process_hook, after=True)) # We can remove this one because it was applied specifically to this # State (or its parent) self.assertTrue(state.remove_hook(None, do_nothing, after=True)) state.add_hook(None, do_nothing, after=False) state.add_hook(None, do_nothing, after=True) state.add_hook(0x400647, fin, after=True) state.add_hook(0x400647, fin, after=False)
def testContextSerialization(self): import pickle as pickle initial_file = "" new_file = "" new_new_file = "" constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) initial_state.context["step"] = 10 initial_file = pickle_dumps(initial_state) with initial_state as new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 10) new_state.context["step"] = 20 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) new_file = pickle_dumps(new_state) with new_state as new_new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 20) new_new_state.context["step"] += 10 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) new_new_file = pickle_dumps(new_new_state) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(initial_state.context["step"], 10) del initial_state del new_state del new_new_state initial_state = pickle.loads(initial_file) self.assertEqual(initial_state.context["step"], 10) new_state = pickle.loads(new_file) self.assertEqual(new_state.context["step"], 20) new_new_state = pickle.loads(new_new_file) self.assertEqual(new_new_state.context["step"], 30)
class ModelTest(unittest.TestCase): dirname = os.path.dirname(__file__) l = linux.SLinux(os.path.join(dirname, "binaries", "basic_linux_amd64")) state = State(ConstraintSet(), l) stack_top = state.cpu.RSP def _clear_constraints(self): self.state.context["migration_map"] = None self.state._constraints = ConstraintSet() def tearDown(self): self._clear_constraints() self.state.cpu.RSP = self.stack_top def _push_string(self, s): cpu = self.state.cpu cpu.RSP -= len(s) cpu.write_bytes(cpu.RSP, s) return cpu.RSP def _push_string_space(self, l): cpu = self.state.cpu cpu.RSP -= l return cpu.RSP def _pop_string_space(self, l): cpu = self.state.cpu cpu.RSP += l return cpu.RSP def assertItemsEqual(self, a, b): # Required for Python3 compatibility self.assertEqual(sorted(a), sorted(b))
def setUp(self): # if not hasattr(self, 'manager'): # self.manager = SyncManager() # self.manager.start(lambda: signal.signal(signal.SIGINT, signal.SIG_IGN)) dirname = os.path.dirname(__file__) l = linux.Linux(os.path.join(dirname, "binaries", "basic_linux_amd64")) self.state = State(ConstraintSet(), l)
def get_state(cls): if cls.cpu is None: constraints = ConstraintSet() dirname = os.path.dirname(__file__) platform = linux.SLinux( os.path.join(dirname, 'binaries', 'basic_linux_amd64')) cls.state = State(constraints, platform) cls.cpu = platform._mk_proc('armv7') return (cls.cpu, cls.state)
def setUp(self): if not hasattr(self, 'manager'): self.manager = SyncManager() self.manager.start( lambda: signal.signal(signal.SIGINT, signal.SIG_IGN)) dirname = os.path.dirname(__file__) l = linux.Linux(os.path.join(dirname, 'binaries', 'basic_linux_amd64')) self.state = State(ConstraintSet(), l) self.lock = self.manager.Condition()
def test_state(self): constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) arr = initial_state.symbolicate_buffer("+" * 100, label="SYMBA") initial_state.constrain(arr[0] > 0x41) self.assertTrue(len(initial_state.constraints.declarations) == 1) with initial_state as new_state: self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) arrb = new_state.symbolicate_buffer("+" * 100, label="SYMBB") self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) new_state.constrain(arrb[0] > 0x42) self.assertTrue(len(new_state.constraints.declarations) == 2) self.assertTrue(len(initial_state.constraints.declarations) == 1)
def process_hook(state: State) -> None: # We can't remove because the globally applied hooks are stored in # the Manticore class, not State self.assertFalse( state.remove_hook(12, process_hook, after=True, syscall=True)) # We can remove this one because it was applied specifically to this # State (or its parent) self.assertTrue( state.remove_hook(None, do_nothing, after=True, syscall=True)) state.add_hook(None, do_nothing, after=False, syscall=True) state.add_hook(None, do_nothing, after=True, syscall=True) # Should execute directly after sys_brk invocation state.add_hook("sys_brk", fin, after=True, syscall=True)
def test_state_hook(self): initial_state = State(ConstraintSet(), FakePlatform()) def fake_hook(_: StateBase) -> None: return None self.assertTrue(len(initial_state._hooks) == 0) self.assertTrue(len(initial_state._after_hooks) == 0) # This hook should be propagated to child state initial_state.add_hook(0x4000, fake_hook, after=False) self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 0) with initial_state as new_state: # Child state has parent's hook self.assertTrue(len(new_state._hooks) == 1) self.assertTrue(len(new_state._after_hooks) == 0) # Try adding the same hook new_state.add_hook(0x4000, fake_hook, after=False) # Should not add again self.assertTrue(len(new_state._hooks) == 1) # Add two hooks for after and before instruction new_state.add_hook(0x4001, fake_hook, after=True) new_state.add_hook(0x4001, fake_hook, after=False) # A new hook added to both lists self.assertTrue(len(new_state._hooks) == 2) self.assertTrue(len(new_state._after_hooks) == 1) # Ensure parent state was not affected self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 0) # Remove one of the hooks we added new_state.remove_hook(0x4000, fake_hook, after=False) # Try to remove a non-existent hook self.assertFalse( new_state.remove_hook(0x4000, fake_hook, after=True)) # Ensure removal self.assertTrue(len(new_state._hooks) == 1) self.assertTrue(len(new_state._after_hooks) == 1) # Ensure parent state wasn't affected self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 0) # Add hook to all PC in our parent state initial_state.add_hook(None, fake_hook, after=True) # Ensure only the hooks we added are still here self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 1)
def setUp(self): dirname = os.path.dirname(__file__) l = linux.Linux(os.path.join(dirname, "binaries", "basic_linux_amd64")) self.state = State(ConstraintSet(), l)
class StateTest(unittest.TestCase): _multiprocess_can_split_ = True def setUp(self): dirname = os.path.dirname(__file__) l = linux.Linux(os.path.join(dirname, "binaries", "basic_linux_amd64")) self.state = State(ConstraintSet(), l) def test_solve_one(self): val = 42 expr = BitVecVariable(32, "tmp") self.state.constrain(expr == val) solved = self.state.solve_one(expr) self.assertEqual(solved, val) def test_solve_n(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 4) self.state.constrain(expr < 7) solved = sorted(self.state.solve_n(expr, 2)) self.assertEqual(solved, [5, 6]) def test_solve_n2(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 4) self.state.constrain(expr < 100) solved = self.state.solve_n(expr, 5) self.assertEqual(len(solved), 5) def test_solve_min_max(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 4) self.state.constrain(expr < 7) self.assertEqual(self.state.solve_min(expr), 5) self.assertEqual(self.state.solve_max(expr), 6) self.assertEqual(self.state.solve_minmax(expr), (5, 6)) def test_policy_one(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 0) self.state.constrain(expr < 100) solved = self.state.concretize(expr, "ONE") self.assertEqual(len(solved), 1) self.assertIn(solved[0], range(100)) def test_state(self): constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) arr = initial_state.symbolicate_buffer("+" * 100, label="SYMBA") initial_state.constrain(arr[0] > 0x41) self.assertTrue(len(initial_state.constraints.declarations) == 1) with initial_state as new_state: self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) arrb = new_state.symbolicate_buffer("+" * 100, label="SYMBB") self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) new_state.constrain(arrb[0] > 0x42) self.assertTrue(len(new_state.constraints.declarations) == 2) self.assertTrue(len(initial_state.constraints.declarations) == 1) def test_new_symbolic_buffer(self): length = 64 expr = self.state.new_symbolic_buffer(length) self.assertEqual(len(expr), length) def test_new_symbolic_value(self): length = 64 expr = self.state.new_symbolic_value(length) self.assertEqual(expr.size, length) def test_new_bad_symbolic_value(self): length = 62 with self.assertRaises(Exception): expr = self.state.new_symbolic_value(length) def test_tainted_symbolic_buffer(self): taint = ("TEST_TAINT",) expr = self.state.new_symbolic_buffer(64, taint=taint) self.assertEqual(expr.taint, frozenset(taint)) def test_tainted_symbolic_value(self): taint = ("TEST_TAINT",) expr = self.state.new_symbolic_value(64, taint=taint) self.assertEqual(expr.taint, frozenset(taint)) def testContextSerialization(self): import pickle as pickle initial_file = "" new_file = "" new_new_file = "" constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) initial_state.context["step"] = 10 initial_file = pickle_dumps(initial_state) with initial_state as new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 10) new_state.context["step"] = 20 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) new_file = pickle_dumps(new_state) with new_state as new_new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 20) new_new_state.context["step"] += 10 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) new_new_file = pickle_dumps(new_new_state) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(initial_state.context["step"], 10) del initial_state del new_state del new_new_state initial_state = pickle.loads(initial_file) self.assertEqual(initial_state.context["step"], 10) new_state = pickle.loads(new_file) self.assertEqual(new_state.context["step"], 20) new_new_state = pickle.loads(new_new_file) self.assertEqual(new_new_state.context["step"], 30) def testContextSerialization(self): import pickle as pickle initial_file = "" new_file = "" new_new_file = "" constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) initial_state.context["step"] = 10 initial_file = pickle_dumps(initial_state) with initial_state as new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 10) new_state.context["step"] = 20 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) new_file = pickle_dumps(new_state) with new_state as new_new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 20) new_new_state.context["step"] += 10 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) new_new_file = pickle_dumps(new_new_state) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(initial_state.context["step"], 10) del initial_state del new_state del new_new_state initial_state = pickle.loads(initial_file) self.assertEqual(initial_state.context["step"], 10) new_state = pickle.loads(new_file) self.assertEqual(new_state.context["step"], 20) new_new_state = pickle.loads(new_new_file) self.assertEqual(new_new_state.context["step"], 30)
class StateTest(unittest.TestCase): _multiprocess_can_split_ = True def setUp(self): dirname = os.path.dirname(__file__) l = linux.Linux(os.path.join(dirname, 'binaries', 'basic_linux_amd64')) self.state = State(ConstraintSet(), l) def test_solve_one(self): val = 42 expr = BitVecVariable(32, 'tmp') self.state.constrain(expr == val) solved = self.state.solve_one(expr) self.assertEqual(solved, val) def test_solve_n(self): expr = BitVecVariable(32, 'tmp') self.state.constrain(expr > 4) self.state.constrain(expr < 7) solved = self.state.solve_n(expr, 2) self.assertEqual(solved, [5, 6]) def test_solve_n2(self): expr = BitVecVariable(32, 'tmp') self.state.constrain(expr > 4) self.state.constrain(expr < 100) solved = self.state.solve_n(expr, 5) self.assertEqual(len(solved), 5) def test_solve_min_max(self): expr = BitVecVariable(32, 'tmp') self.state.constrain(expr > 4) self.state.constrain(expr < 7) self.assertEqual(self.state.solve_min(expr), 5) self.assertEqual(self.state.solve_max(expr), 6) self.assertEqual(self.state.solve_minmax(expr), (5, 6)) def test_policy_one(self): expr = BitVecVariable(32, 'tmp') self.state.constrain(expr > 0) self.state.constrain(expr < 100) solved = self.state.concretize(expr, 'ONE') self.assertEqual(len(solved), 1) self.assertIn(solved[0], range(100)) def test_state(self): constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) arr = initial_state.symbolicate_buffer('+' * 100, label='SYMBA') initial_state.constrain(arr[0] > 0x41) self.assertTrue(len(initial_state.constraints.declarations) == 1) with initial_state as new_state: self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) arrb = new_state.symbolicate_buffer('+' * 100, label='SYMBB') self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) new_state.constrain(arrb[0] > 0x42) self.assertTrue(len(new_state.constraints.declarations) == 2) self.assertTrue(len(initial_state.constraints.declarations) == 1) def test_new_symbolic_buffer(self): length = 64 expr = self.state.new_symbolic_buffer(length) self.assertEqual(len(expr), length) def test_new_symbolic_value(self): length = 64 expr = self.state.new_symbolic_value(length) self.assertEqual(expr.size, length) def test_new_bad_symbolic_value(self): length = 62 with self.assertRaises(Exception): expr = self.state.new_symbolic_value(length) def test_tainted_symbolic_buffer(self): taint = ('TEST_TAINT', ) expr = self.state.new_symbolic_buffer(64, taint=taint) self.assertEqual(expr.taint, frozenset(taint)) def test_tainted_symbolic_value(self): taint = ('TEST_TAINT', ) expr = self.state.new_symbolic_value(64, taint=taint) self.assertEqual(expr.taint, frozenset(taint)) def testContextSerialization(self): import pickle as pickle initial_file = '' new_file = '' new_new_file = '' constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) initial_state.context['step'] = 10 initial_file = pickle.dumps(initial_state) with initial_state as new_state: self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 10) new_state.context['step'] = 20 self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) new_file = pickle.dumps(new_state) with new_state as new_new_state: self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(new_new_state.context['step'], 20) new_new_state.context['step'] += 10 self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(new_new_state.context['step'], 30) new_new_file = pickle.dumps(new_new_state) self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(new_new_state.context['step'], 30) self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(initial_state.context['step'], 10) del initial_state del new_state del new_new_state initial_state = pickle.loads(initial_file) self.assertEqual(initial_state.context['step'], 10) new_state = pickle.loads(new_file) self.assertEqual(new_state.context['step'], 20) new_new_state = pickle.loads(new_new_file) self.assertEqual(new_new_state.context['step'], 30) def _test_state_gen_helper(self, name, msg): self.assertEqual(name, 'statename') self.assertEqual(msg, 'statemsg') raise _CallbackExecuted def testContextSerialization(self): import pickle as pickle initial_file = '' new_file = '' new_new_file = '' constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) initial_state.context['step'] = 10 initial_file = pickle.dumps(initial_state) with initial_state as new_state: self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 10) new_state.context['step'] = 20 self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) new_file = pickle.dumps(new_state) with new_state as new_new_state: self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(new_new_state.context['step'], 20) new_new_state.context['step'] += 10 self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(new_new_state.context['step'], 30) new_new_file = pickle.dumps(new_new_state) self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(new_new_state.context['step'], 30) self.assertEqual(initial_state.context['step'], 10) self.assertEqual(new_state.context['step'], 20) self.assertEqual(initial_state.context['step'], 10) del initial_state del new_state del new_new_state initial_state = pickle.loads(initial_file) self.assertEqual(initial_state.context['step'], 10) new_state = pickle.loads(new_file) self.assertEqual(new_state.context['step'], 20) new_new_state = pickle.loads(new_new_file) self.assertEqual(new_new_state.context['step'], 30) def test_state_gen(self): self.state.subscribe('will_generate_testcase', self._test_state_gen_helper) with self.assertRaises(_CallbackExecuted): self.state.generate_testcase('statename', 'statemsg')
class StateTest(unittest.TestCase): _multiprocess_can_split_ = True def setUp(self): dirname = os.path.dirname(__file__) l = linux.Linux(os.path.join(dirname, "binaries", "basic_linux_amd64")) self.state = State(ConstraintSet(), l) def test_solve_one(self): val = 42 expr = BitVecVariable(32, "tmp") self.state.constrain(expr == val) solved = self.state.solve_one(expr) self.assertEqual(solved, val) def test_solve_n(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 4) self.state.constrain(expr < 7) solved = sorted(self.state.solve_n(expr, 2)) self.assertEqual(solved, [5, 6]) def test_solve_n2(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 4) self.state.constrain(expr < 100) solved = self.state.solve_n(expr, 5) self.assertEqual(len(solved), 5) def test_solve_min_max(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 4) self.state.constrain(expr < 7) self.assertEqual(self.state.solve_min(expr), 5) self.assertEqual(self.state.solve_max(expr), 6) self.assertEqual(self.state.solve_minmax(expr), (5, 6)) def test_policy_one(self): expr = BitVecVariable(32, "tmp") self.state.constrain(expr > 0) self.state.constrain(expr < 100) solved = self.state.concretize(expr, "ONE") self.assertEqual(len(solved), 1) self.assertIn(solved[0], range(100)) def test_state(self): constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) arr = initial_state.symbolicate_buffer("+" * 100, label="SYMBA") initial_state.constrain(arr[0] > 0x41) self.assertTrue(len(initial_state.constraints.declarations) == 1) with initial_state as new_state: self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) arrb = new_state.symbolicate_buffer("+" * 100, label="SYMBB") self.assertTrue(len(initial_state.constraints.declarations) == 1) self.assertTrue(len(new_state.constraints.declarations) == 1) new_state.constrain(arrb[0] > 0x42) self.assertTrue(len(new_state.constraints.declarations) == 2) self.assertTrue(len(initial_state.constraints.declarations) == 1) def test_new_symbolic_buffer(self): length = 64 expr = self.state.new_symbolic_buffer(length) self.assertEqual(len(expr), length) def test_new_symbolic_value(self): length = 64 expr = self.state.new_symbolic_value(length) self.assertEqual(expr.size, length) def test_new_bad_symbolic_value(self): length = 62 with self.assertRaises(Exception): expr = self.state.new_symbolic_value(length) def test_tainted_symbolic_buffer(self): taint = ("TEST_TAINT", ) expr = self.state.new_symbolic_buffer(64, taint=taint) self.assertEqual(expr.taint, frozenset(taint)) def test_tainted_symbolic_value(self): taint = ("TEST_TAINT", ) expr = self.state.new_symbolic_value(64, taint=taint) self.assertEqual(expr.taint, frozenset(taint)) def test_state_hook(self): initial_state = State(ConstraintSet(), FakePlatform()) def fake_hook(_: StateBase) -> None: return None self.assertTrue(len(initial_state._hooks) == 0) self.assertTrue(len(initial_state._after_hooks) == 0) # This hook should be propagated to child state initial_state.add_hook(0x4000, fake_hook, after=False) self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 0) with initial_state as new_state: # Child state has parent's hook self.assertTrue(len(new_state._hooks) == 1) self.assertTrue(len(new_state._after_hooks) == 0) # Try adding the same hook new_state.add_hook(0x4000, fake_hook, after=False) # Should not add again self.assertTrue(len(new_state._hooks) == 1) # Add two hooks for after and before instruction new_state.add_hook(0x4001, fake_hook, after=True) new_state.add_hook(0x4001, fake_hook, after=False) # A new hook added to both lists self.assertTrue(len(new_state._hooks) == 2) self.assertTrue(len(new_state._after_hooks) == 1) # Ensure parent state was not affected self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 0) # Remove one of the hooks we added new_state.remove_hook(0x4000, fake_hook, after=False) # Try to remove a non-existent hook self.assertFalse( new_state.remove_hook(0x4000, fake_hook, after=True)) # Ensure removal self.assertTrue(len(new_state._hooks) == 1) self.assertTrue(len(new_state._after_hooks) == 1) # Ensure parent state wasn't affected self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 0) # Add hook to all PC in our parent state initial_state.add_hook(None, fake_hook, after=True) # Ensure only the hooks we added are still here self.assertTrue(len(initial_state._hooks) == 1) self.assertTrue(len(initial_state._after_hooks) == 1) def testContextSerialization(self): import pickle as pickle initial_file = "" new_file = "" new_new_file = "" constraints = ConstraintSet() initial_state = State(constraints, FakePlatform()) initial_state.context["step"] = 10 initial_file = pickle_dumps(initial_state) with initial_state as new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 10) new_state.context["step"] = 20 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) new_file = pickle_dumps(new_state) with new_state as new_new_state: self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 20) new_new_state.context["step"] += 10 self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) new_new_file = pickle_dumps(new_new_state) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(new_new_state.context["step"], 30) self.assertEqual(initial_state.context["step"], 10) self.assertEqual(new_state.context["step"], 20) self.assertEqual(initial_state.context["step"], 10) del initial_state del new_state del new_new_state initial_state = pickle.loads(initial_file) self.assertEqual(initial_state.context["step"], 10) new_state = pickle.loads(new_file) self.assertEqual(new_state.context["step"], 20) new_new_state = pickle.loads(new_new_file) self.assertEqual(new_new_state.context["step"], 30)