def test_codegen_decision_only(self): base = abs_path('./specs/') sc = 'script-no-graph.py' ps = Parser(base + sc, base) ps.main(verbose=False) # compare file content with open(base + FIRST_SCRIPT, 'r') as f: actual = f.read() with open(base + sc, 'r') as f: lines = f.readlines()[7:] expected = ''.join(lines).replace('{{a}}', '1') self.assertEqual(actual, expected)
def test_codegen_graph_only(self): base = abs_path('./specs/') ps = Parser(base + 'script1-good.py', base) ps.main(verbose=False) # compare file content with open(os.path.join(base, FIRST_SCRIPT), 'r') as f: actual = f.read() with open(base + 'script1.py', 'r') as f: lines = f.read().split('\n') expected = '' for l in lines: if not l.strip().startswith('# --- '): expected += l + '\n' self.assertEqual(actual.strip(), expected.strip())
def test_adg(self): base = abs_path('./specs/') ps = Parser(base + 'script4-1.py', base) ps.adg.create(ps.code_parser.blocks) self.assertSetEqual(ps.adg.nodes, {'b', 'C', 'B', 'A'}) expected = {'B': {'b', 'C'}, 'A': {'B'}} self.assertDictEqual(self._edge_to_set(ps.adg.edges), expected)
def test_condition_syntax(self): """ Does the condition code contain python syntax error? """ base = abs_path('./specs/') ps = Parser(base + 'script3-1.py', base) spec = {'constraints': [{'block': 'A', 'condition': 'B=b1'}]} with self.assertRaises(ParseError): read_wrapper(spec, ps) spec = {'constraints': [{'block': 'A', 'condition': 'B b1'}]} with self.assertRaises(ParseError): read_wrapper(spec, ps) spec = {'constraints': [{'block': 'A', 'condition': 'B == 2.5'}]} read_wrapper(spec, ps)
def test_code_gen(self): base = abs_path('../example/simple/') ps = Parser(base + 'template.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 6)
def test_spec_cyclic_graph(self, stdout): base = abs_path('./specs/') with self.assertRaises(SystemExit): Parser(base + 'script1-cyclic-graph.py') self.assertRegex(stdout.getvalue(), 'Cannot find any starting node')
def test_spec_bad_graph(self, stdout): base = abs_path('./specs/') with self.assertRaises(SystemExit): Parser(base + 'script1-bad-graph.py') self.assertRegex(stdout.getvalue(), 'Cannot find a target node')
def test_script_3(self, stdout): with self.assertRaises(SystemExit): Parser(abs_path('./specs/') + 'script2-syntax.py') self.assertRegex(stdout.getvalue(), r'Cannot find "\("')
def test_link(self): base = abs_path('./specs/') ps = Parser(base + 'script3-7.py') cp = ConstraintParser(ps.spec) cs = cp.read_constraints(ps.code_parser, ps.dec_parser) self.assertEqual(len(cs), 10)
def test_script_6(self): base = abs_path('./specs/') ps = Parser(base + 'script2-block-param.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 9)
def test_script_4(self, stdout): with self.assertRaises(SystemExit): Parser(abs_path('./specs/') + 'script2-dup.py') self.assertRegex(stdout.getvalue(), '(?i)duplicated')
def test_constraint_inline(self): """ Inline constraints """ base = abs_path('./specs/') ps = Parser(base + 'script-inline-constraints.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 2)
def test_constraint_7(self): """ Linked decisions """ base = abs_path('./specs/') ps = Parser(base + 'script3-7.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 10)
def test_constraint_5(self): """ Skip a block """ # first, skip a normal block base = abs_path('./specs/') ps = Parser(base + 'script3-5.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 8) # then, skip a decision block ps = Parser(base + 'script3-5.py', base) ps.spec['constraints'] = [{ "block": "B", "skippable": True, "condition": "a == if" }] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 6)
def test_constraint_4(self): """ Variable depends on variable """ base = abs_path('./specs/') ps = Parser(base + 'script3-4.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4) # then, test index ps = Parser(base + 'script3-4.py', base) ps.spec['constraints'] = [{ "variable": "b", "index": 1, "condition": "a.index == 0" }, { "variable": "b", "index": 0, "condition": "a == else" }] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4)
def test_constraint_3(self): """ Normal block depends on block parameter """ base = abs_path('./specs/') ps = Parser(base + 'script3-3.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 8)
def test_constraint_1(self): """ Block options depend on block parameter """ base = abs_path('./specs/') ps = Parser(base + 'script3-1.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 6)
def test_codegen_reading(self): base = abs_path('../example/reading/python/') Parser(base + 'template.py', base).main(verbose=False)
def test_r(self): base = abs_path('../example/fertility_r/') ps = Parser(base + 'template.R', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 120)
def test_codegen_missing_decision(self, stdout): base = abs_path('./specs/') sc = 'script-no-graph-empty.py' with self.assertRaises(SystemExit): Parser(base + sc, base) self.assertRegex(stdout.getvalue(), 'Cannot find matching variable')
def test_adg_link(self): base = abs_path('./specs/') ps = Parser(base + 'script4-3.py', base) ps.adg.create(ps.code_parser.blocks) self.assertSetEqual(ps.adg.nodes, {'a', 'B'}) self.assertDictEqual(ps.adg.edges, {'a': ['B']})
def test_script_5(self, stdout): with self.assertRaises(SystemExit): Parser(abs_path('./specs/') + 'script2-dup-var.py') self.assertRegex(stdout.getvalue(), '(?i)name')
def test_parse_blocks(self): base = abs_path('../example/simple/') ps = Parser(base + 'template.py') self.assertSetEqual(set(ps.code_parser.blocks.keys()), {'_start', 'A:std', 'A:iqr', 'B'}) self.assertListEqual(['_start', 'A', 'B'], ps.code_parser.order)
def test_spec_good(self): base = abs_path('../example/simple/') ps = Parser(base + 'template.py') expected = [['_start', 'A:std', 'B'], ['_start', 'A:iqr', 'B']] expected = set([','.join(p) for p in expected]) self.assertSetEqual(set([','.join(p) for p in ps.paths]), expected)
def test_json_syntax(self): """ Test various possibilities to specify constraints in JSON """ base = abs_path('./specs/') ps = Parser(base + 'script3-1.py', base) # empty - should parse spec = {} read_wrapper(spec, ps) # empty array - should parse spec = {'constraints': []} read_wrapper(spec, ps) # empty element - should fail spec = {'constraints': [{}]} with self.assertRaises(ParseError): read_wrapper(spec, ps) # no matching block - should fail spec = {'constraints': [{'block': 'a'}]} with self.assertRaises(ParseError): read_wrapper(spec, ps) # no matching variable - should fail spec = {'constraints': [{'variable': 'c'}]} with self.assertRaises(ParseError): read_wrapper(spec, ps) # loner option - should fail spec = {'constraints': [{'option': 'a1'}]} with self.assertRaises(ParseError): read_wrapper(spec, ps) # loner block - should parse spec = {'constraints': [{'block': 'A', 'condition': 'B==b1'}]} read_wrapper(spec, ps) # block and option - should parse spec = { 'constraints': [{ 'block': 'A', 'option': 'a1', 'condition': 'B==b1' }] } read_wrapper(spec, ps) # variable and option - should parse spec = { 'constraints': [{ 'variable': 'a', 'option': '2.5', 'condition': 'B==b1' }] } read_wrapper(spec, ps) # weird option - should parse # fixme: {'option': '[1,2]'} will fail spec = { 'constraints': [{ 'variable': 'c', 'option': '[1, 2]', 'condition': 'B==b1' }] } read_wrapper(spec, ps) # variables in condition do not match - should fail spec = {'constraints': [{'block': 'A', 'condition': 'H==b1'}]} with self.assertRaises(ParseError): read_wrapper(spec, ps) # variables in condition do not match - should fail spec = {'constraints': [{'block': 'A', 'condition': 'H.index==1'}]} with self.assertRaises(ParseError): read_wrapper(spec, ps)
def test_spec_empty(self): base = abs_path('./specs/') ps = Parser(base + 'script1.py') self.assertListEqual(ps.paths, [['A', 'B', 'C']])
def test_eval(self): """ Evaluation of various conditions """ # expr and expr base = abs_path('./specs/') ps = Parser(base + 'script3-6.py', base) ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 2) # expr or expr ps.spec['constraints'] = [{ "block": "D", "condition": "a == if or B == b1" }] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 6) # expr and (expr or expr) ps.spec['constraints'] = [{ "block": "D", "condition": "a == if and (B == b1 or B == b2)" }] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4) # testing != ps.spec['constraints'] = [{"block": "D", "condition": "a != if"}] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4) # testing >= ps.spec['constraints'] = [{"block": "D", "condition": "a.index >= 1"}] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4) # testing index ps.spec['constraints'] = [{"block": "D", "condition": "b.index == 1"}] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4) # testing option with integer type ps.spec['constraints'] = [{"block": "D", "condition": "b == 0"}] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4) # testing option with float type ps.spec['constraints'] = [{"block": "D", "condition": "b == 1.5"}] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 4) # testing unmade decision ps.spec['constraints'] = [{"block": "A", "condition": "b.index == 0"}] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 0) # testing if the decision is made when the block depends on a variable # inside the block ps.spec['constraints'] = [{"block": "B", "condition": "b.index == 0"}] ps._parse_constraints() ps.main(verbose=False) self.assertEqual(ps.wrangler.counter, 0)
def test_script_2(self): ps = Parser(abs_path('./specs/') + 'script2.py') self.assertListEqual([*ps.code_parser.blocks], ['_start', 'A', 'B', 'C'])