def test_assign_value__magicmethod__(self): """tests the behavior of assign and value""" with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) step1 = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name["v"].name self.assertIsNone(step1.value[v]) step1 += (v, yes) self.assertEqual(yes, step1.value[v]) step1 += (v, no) self.assertEqual(no, step1.value[v])
def test_iter(self): """tests the behavior of assign and value""" with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) step1 = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name['v'].name self.assertEqual([], list(step1)) step1 += v, yes self.assertEqual([(v, yes)], list(step1)) # += really ASSIGNS a value, not append step1 += v, no self.assertEqual([(v, no)], list(step1))
def test_is_loopback_when_frozen(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) step1 = trace.steps[1] step2 = trace.append_step() yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name['v'].name step1 += (v, yes) step2 += (v, no) trace.freeze() step1.force_loopback() self.assertTrue(step1.is_loopback) self.assertFalse(step2.is_loopback) step2.force_loopback() self.assertTrue(step1.is_loopback) # last step is never a loopback self.assertFalse(step2.is_loopback) trace.thaw() self.assertFalse(step1.is_loopback) self.assertFalse(step2.is_loopback)
def test_iter(self): """tests the behavior of assign and value""" with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) step1 = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name["v"].name self.assertEqual([], list(step1)) step1 += v, yes self.assertEqual([(v, yes)], list(step1)) # += really ASSIGNS a value, not append step1 += v, no self.assertEqual([(v, no)], list(step1))
def test_verify_exactly(self): theta = Node.from_ptr(parse_simple_expression("TRUE")) theta = bmcutils.make_nnf_boolean_wff(theta) sigma_12= Node.from_ptr(parse_ltl_spec("TRUE")) sigma_12= bmcutils.make_nnf_boolean_wff(sigma_12).to_node() obs_names = ["mouse"] obs_vars = diagnosability.mk_observable_vars(obs_names) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = inactive")) for i in range(5): res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), i, theta, sigma_12, sigma_12) self.assertEqual("No Violation", res) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = highlight")) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 0, theta, sigma_12, sigma_12) self.assertEqual("No Violation", res) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 1, theta, sigma_12, sigma_12) self.assertTrue(res.startswith("############### DIAGNOSABILITY VIOLATION")) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 2, theta, sigma_12, sigma_12) self.assertTrue(res.startswith("############### DIAGNOSABILITY VIOLATION")) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 3, theta, sigma_12, sigma_12) self.assertTrue(res.startswith("############### DIAGNOSABILITY VIOLATION"))
def test_generate_sat_problem(self): theta = Node.from_ptr(parse_simple_expression("TRUE")) theta = bmcutils.make_nnf_boolean_wff(theta) sigma_12= Node.from_ptr(parse_ltl_spec("TRUE")) sigma_12= bmcutils.make_nnf_boolean_wff(sigma_12).to_node() observable = diagnosability.mk_observable_vars(["mouse"]) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = inactive")) for i in range(5): problem = diagnosability.generate_sat_problem(observable, (f1, f2), i, theta, sigma_12, sigma_12) solver = SatSolverFactory.create() cnf = problem.to_cnf() solver += cnf solver.polarity(cnf, Polarity.POSITIVE) self.assertEqual(SatSolverResult.UNSATISFIABLE, solver.solve()) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = highlight")) for i in range(1, 4): # length zero has no input => only an initial state and the # diagnosability condition is not checked problem = diagnosability.generate_sat_problem(observable, (f1, f2), i, theta, sigma_12, sigma_12) solver = SatSolverFactory.create() cnf = problem.to_cnf() solver += cnf solver.polarity(cnf, Polarity.POSITIVE) self.assertEqual(SatSolverResult.SATISFIABLE, solver.solve())
def test_generate_sat_problem(self): theta = Node.from_ptr(parse_simple_expression("TRUE")) theta = bmcutils.make_nnf_boolean_wff(theta) sigma_12 = Node.from_ptr(parse_ltl_spec("TRUE")) sigma_12 = bmcutils.make_nnf_boolean_wff(sigma_12).to_node() observable = diagnosability.mk_observable_vars(["mouse"]) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = inactive")) for i in range(5): problem = diagnosability.generate_sat_problem( observable, (f1, f2), i, theta, sigma_12, sigma_12) solver = SatSolverFactory.create() cnf = problem.to_cnf() solver += cnf solver.polarity(cnf, Polarity.POSITIVE) self.assertEqual(SatSolverResult.UNSATISFIABLE, solver.solve()) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = highlight")) for i in range(1, 4): # length zero has no input => only an initial state and the # diagnosability condition is not checked problem = diagnosability.generate_sat_problem( observable, (f1, f2), i, theta, sigma_12, sigma_12) solver = SatSolverFactory.create() cnf = problem.to_cnf() solver += cnf solver.polarity(cnf, Polarity.POSITIVE) self.assertEqual(SatSolverResult.SATISFIABLE, solver.solve())
def test_language_contains(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) v = be_fsm.encoding.by_name["v"] w = be_fsm.encoding.by_name["w"] f = be_fsm.encoding.by_name["f"] i = be_fsm.encoding.by_name["i"] self.assertTrue(v.name in trace) self.assertTrue(w.name in trace) self.assertTrue(f.name in trace) self.assertTrue(i.name in trace) x = parse_simple_expression("x") self.assertFalse(Node.from_ptr(x) in trace)
def test_copy(self): """Tests the copy behavior""" h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h[a] = a h2= h.copy() self.assertTrue(a in h2)
def test_clear(self): """Verifies that clear works as expected""" h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h[a] = a h.clear() self.assertFalse(a in h)
def test_copy(self): """Tests the copy behavior""" h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h[a] = a h2 = h.copy() self.assertTrue(a in h2)
def test_constraint_context_theta(self): enc = master_be_fsm().encoding cond = Wff(parse_simple_expression("mouse = down")).to_boolean_wff() theta = diagnosability.constraint_context_theta_initial(cond, 0, 1) manual= enc.shift_to_time(cond.to_be(enc), 0) \ & enc.shift_to_time(cond.to_be(enc), 1) \ self.assertEqual(theta, manual)
def test_empty(self): """Tests the empty factory""" a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h = Assoc.empty(freeit=True) self.assertFalse(a in h) hh = Assoc.empty(initial_capa=1, freeit=True) hh[a] = a self.assertTrue(a in hh)
def test_verify_exactly(self): theta = Node.from_ptr(parse_simple_expression("TRUE")) theta = bmcutils.make_nnf_boolean_wff(theta) sigma_12 = Node.from_ptr(parse_ltl_spec("TRUE")) sigma_12 = bmcutils.make_nnf_boolean_wff(sigma_12).to_node() obs_names = ["mouse"] obs_vars = diagnosability.mk_observable_vars(obs_names) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = inactive")) for i in range(5): res = diagnosability.verify_for_size_exactly_k( obs_names, obs_vars, (f1, f2), i, theta, sigma_12, sigma_12) self.assertEqual("No Violation", res) f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = highlight")) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 0, theta, sigma_12, sigma_12) self.assertEqual("No Violation", res) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 1, theta, sigma_12, sigma_12) self.assertTrue( res.startswith("############### DIAGNOSABILITY VIOLATION")) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 2, theta, sigma_12, sigma_12) self.assertTrue( res.startswith("############### DIAGNOSABILITY VIOLATION")) res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 3, theta, sigma_12, sigma_12) self.assertTrue( res.startswith("############### DIAGNOSABILITY VIOLATION"))
def test_associative_array(self): """ This function tests the basic functions of the associative array proto """ h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) b = Node.from_ptr(parse_simple_expression("b.car = 3"), freeit=False) # __contains__ self.assertFalse(a in h) # __setitem__ h[a] = a self.assertTrue(a in h) # __getitem__ self.assertEqual(h[a], a) with self.assertRaises(KeyError): h[b] # __delitem__ del h[a] self.assertFalse(a in h)
def test_get_mod_instance_type(self): glob.load_from_file("tests/pynusmv/models/counters.smv") glob.compute_model() sexp = parse_simple_expression("c1") self.assertIsNotNone(sexp) st = glob.symb_table() tp = nssymb_table.SymbTable_get_type_checker(st._ptr) expr_type = nstype_checking.TypeChecker_get_expression_type( tp, sexp, None) self.assertTrue(nssymb_table.SymbType_is_error(expr_type))
def test_eventually_critical_pair(self): enc = master_be_fsm().encoding f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = highlight")) constraint = diagnosability.constraint_eventually_critical_pair( (f1, f2), 0, 5, 5) nnf1 = bmcutils.make_nnf_boolean_wff(f1).to_be(enc) nnf2 = bmcutils.make_nnf_boolean_wff(f2).to_be(enc) manual = Be.false(enc.manager) for i in range(6): # again, from 0 to 5 manual |= (enc.shift_to_time(nnf1, i) & enc.shift_to_time(nnf2, 5 + i)) # observing the clauses generated in both cases, one observes that # the generated clauses are the same except that the number of the cnf # literals do not match, example: # [-59, -24, 58] # [-65, -24, 64] # This is due to the fact that some 'fresh' cnf literals are used in the # generation of the epxression. Therefore, a comparison (even on the # canonical form of the CNF) is not feasible. # # Satisfiability is just an indication but at least that is .. something solver_c = SatSolverFactory.create() cnf = constraint.to_cnf() solver_c += cnf solver_c.polarity(cnf, Polarity.POSITIVE) result_c = solver_c.solve() solver_m = SatSolverFactory.create() cnf = manual.to_cnf() solver_m += cnf solver_m.polarity(cnf, Polarity.POSITIVE) result_m = solver_m.solve() self.assertEqual(result_c, result_m)
def test_eventually_critical_pair(self): enc= master_be_fsm().encoding f1 = Node.from_ptr(parse_simple_expression("status = active")) f2 = Node.from_ptr(parse_simple_expression("status = highlight")) constraint = diagnosability.constraint_eventually_critical_pair((f1, f2), 0, 5, 5) nnf1 = bmcutils.make_nnf_boolean_wff(f1).to_be(enc) nnf2 = bmcutils.make_nnf_boolean_wff(f2).to_be(enc) manual = Be.false(enc.manager) for i in range(6): # again, from 0 to 5 manual |= ( enc.shift_to_time(nnf1 , i) & enc.shift_to_time(nnf2 , 5+i)) # observing the clauses generated in both cases, one observes that # the generated clauses are the same except that the number of the cnf # literals do not match, example: # [-59, -24, 58] # [-65, -24, 64] # This is due to the fact that some 'fresh' cnf literals are used in the # generation of the epxression. Therefore, a comparison (even on the # canonical form of the CNF) is not feasible. # # Satisfiability is just an indication but at least that is .. something solver_c = SatSolverFactory.create() cnf = constraint.to_cnf() solver_c+= cnf solver_c.polarity(cnf, Polarity.POSITIVE) result_c = solver_c.solve() solver_m = SatSolverFactory.create() cnf = manual.to_cnf() solver_m+= cnf solver_m.polarity(cnf, Polarity.POSITIVE) result_m = solver_m.solve() self.assertEqual(result_c, result_m)
def test_is_loopback_when_frozen(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) step1 = trace.steps[1] step2 = trace.append_step() yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name["v"].name step1 += (v, yes) step2 += (v, no) trace.freeze() step1.force_loopback() self.assertTrue(step1.is_loopback) self.assertFalse(step2.is_loopback) step2.force_loopback() self.assertTrue(step1.is_loopback) # last step is never a loopback self.assertFalse(step2.is_loopback) trace.thaw() self.assertFalse(step1.is_loopback) self.assertFalse(step2.is_loopback)
def test_assign_value__magicmethod__(self): """tests the behavior of assign and value""" with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) step1 = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name['v'].name self.assertIsNone(step1.value[v]) step1 += (v, yes) self.assertEqual(yes, step1.value[v]) step1 += (v, no) self.assertEqual(no, step1.value[v])
def test_associative_array(self): """ This function tests the basic functions of the associative array proto """ h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) # __contains__ self.assertFalse(a in h) # __setitem__ h[a] = a self.assertTrue(a in h) # __getitem__ self.assertEqual(h[a], a) # __delitem__ del h[a] self.assertFalse(a in h)
def _booleanize(self): """ Returns a boolean expression (Be) corresponding to this simple boolean expression (text). .. note:: Albeit feasible, working directly with variables as offered by the encoding is a little bit limiting as it de facto rejects any symbol which is not a variable. As a consequence, the DEFINES, or arithmetic expressions are not usable. The use of this function palliates that limitation and makes the use of any simple boolean expression possible. :return: a be expression (Be) corresponding to `self` """ if not self._booleanized: befsm = master_be_fsm() node = parse_simple_expression(self.id) self._booleanized = Wff(node).to_boolean_wff().to_be(befsm.encoding) return self._booleanized
def _booleanize(self): """ Returns a boolean expression (Be) corresponding to this simple boolean expression (text). .. note:: Albeit feasible, working directly with variables as offered by the encoding is a little bit limiting as it de facto rejects any symbol which is not a variable. As a consequence, the DEFINES, or arithmetic expressions are not usable. The use of this function palliates that limitation and makes the use of any simple boolean expression possible. :return: a be expression (Be) corresponding to `self` """ if not self._booleanized: befsm = master_be_fsm() node = parse_simple_expression(self.id) self._booleanized = Wff(node).to_boolean_wff().to_be( befsm.encoding) return self._booleanized
def test_is_complete(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) # vacuously true self.assertTrue(trace.is_complete(NodeList.from_list([]))) v = be_fsm.encoding.by_name['v'].name self.assertFalse(trace.is_complete(NodeList.from_list([v]))) step = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) step += (v, yes) self.assertTrue(trace.is_complete(NodeList.from_list([v])))
def test_language_contains(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) v = be_fsm.encoding.by_name['v'] w = be_fsm.encoding.by_name['w'] f = be_fsm.encoding.by_name['f'] i = be_fsm.encoding.by_name['i'] self.assertTrue(v.name in trace) self.assertTrue(w.name in trace) self.assertTrue(f.name in trace) self.assertTrue(i.name in trace) x = parse_simple_expression("x") self.assertFalse(Node.from_ptr(x) in trace)
def check(args, condition_text, observable): """ Performs the verification of the diagnosability of the condition represented by `condition_text` and print its result to stdout. :param args: the arguments that were given on the command line :param condition_text: a string representing the diagnosability condition to be verified in the format 'c1 ; c2'. :param observable: the set of symbols considered observable in the context of this diagnosability test """ try: observable_vars = mk_observable_vars(observable) diagnosability_condition = mk_specs_nodes(condition_text) theta = Node.from_ptr(parse_simple_expression(args.initial_condition)) theta = make_nnf_boolean_wff(theta) sigma1= Node.from_ptr(parse_ltl_spec(args.sigma1)) sigma1= make_nnf_boolean_wff(sigma1).to_node() sigma2= Node.from_ptr(parse_ltl_spec(args.sigma2)) sigma2= make_nnf_boolean_wff(sigma2).to_node() for k in range(args.bound+1): result = verify_for_size_exactly_k(observable, observable_vars, diagnosability_condition, k, theta, sigma1, sigma2) if "No Violation" != str(result): print("-- {} is *NOT* diagnosable for length {}".format(diagnosability_condition, k)) print(result) return else: print("-- No counter example at length {}".format(k)) print("-- No counter example found for executions of length <= {}".format(args.bound)) except Exception as e: print("The specified condition contains a syntax error") print(e)
def check(args, condition_text, observable): """ Performs the verification of the diagnosability of the condition represented by `condition_text` and print its result to stdout. :param args: the arguments that were given on the command line :param condition_text: a string representing the diagnosability condition to be verified in the format 'c1 ; c2'. :param observable: the set of symbols considered observable in the context of this diagnosability test """ try: observable_vars = mk_observable_vars(observable) diagnosability_condition = mk_specs_nodes(condition_text) theta = Node.from_ptr(parse_simple_expression(args.initial_condition)) theta = make_nnf_boolean_wff(theta) sigma1 = Node.from_ptr(parse_ltl_spec(args.sigma1)) sigma1 = make_nnf_boolean_wff(sigma1).to_node() sigma2 = Node.from_ptr(parse_ltl_spec(args.sigma2)) sigma2 = make_nnf_boolean_wff(sigma2).to_node() for k in range(args.bound + 1): result = verify_for_size_exactly_k( observable, observable_vars, diagnosability_condition, k, theta, sigma1, sigma2 ) if "No Violation" != str(result): print("-- {} is *NOT* diagnosable for length {}".format(diagnosability_condition, k)) print(result) return print("-- No counter example found for executions of length <= {}".format(k)) except Exception as e: print("The specified condition contains a syntax error") print(e)
def test_is_complete(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) # vacuously true self.assertTrue(trace.is_complete(NodeList.from_list([]))) v = be_fsm.encoding.by_name["v"].name self.assertFalse(trace.is_complete(NodeList.from_list([v]))) step = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) step += (v, yes) self.assertTrue(trace.is_complete(NodeList.from_list([v])))
def mk_specs_nodes(spec): """ Creates the Nodes(:see:`pynusmv.node.Node`), that represent the diagnosability condition to be verified. .. note:: The diagnosability condition *must* be expressed as a pair of boolean expression (propositional formulas) that are separated by a semicolon. Example:: status = active ; status = highlighted :param spec: the diagnosability condition to be evaluated. :return: a tuple representing the diagnosability condition to be verified. (This tuple is composed of two Nodes, which stand for the NuSMV way of representing formulas) """ splitted = spec.split(";") if len(splitted) < 2: raise ValueError("The two parts of the diagnosability condition need to be separated with a semicolon") to_node = lambda x: Node.from_ptr(parse_simple_expression(x)) return tuple(map(to_node, splitted))
def mk_specs_nodes(spec): """ Creates the Nodes(:see:`pynusmv.node.Node`), that represent the diagnosability condition to be verified. .. note:: The diagnosability condition *must* be expressed as a pair of boolean expression (propositional formulas) that are separated by a semicolon. Example:: status = active ; status = highlighted :param spec: the diagnosability condition to be evaluated. :return: a tuple representing the diagnosability condition to be verified. (This tuple is composed of two Nodes, which stand for the NuSMV way of representing formulas) """ splitted = spec.split(';') if len(splitted) < 2: raise ValueError("The two parts of the diagnosability condition need to be separated with a semicolon") to_node = lambda x: Node.from_ptr(parse_simple_expression(x)) return tuple(map(to_node, splitted))
def node_from_expr(self, expr): return Node.from_ptr(parse_simple_expression(expr))
def test_from_dict(self): """Tests the from_dict factory""" a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) d = {a: a} h = Assoc.from_dict(d) self.assertTrue(a in h)
def test_empty(self): """Tests the empty factory""" a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h = Assoc.empty(freeit=True) self.assertFalse(a in h)