def test_hack_code_gen(self) -> None: ClingoContext.number_of_nodes = 12 ClingoContext.min_depth = 3 ClingoContext.min_classes = 3 ClingoContext.min_interfaces = 4 ClingoContext.lower_bound = 1 ClingoContext.higher_bound = 5 ClingoContext.avg_width = 0 exp = """\ <?hh class S9 {} class S10 {} class S11 {} interface S0 {} interface S1 {} interface S2 {} interface S3 {} interface S4 extends S0 {} interface S5 {} interface S6 {} interface S7 {} interface S8 extends S4 {} """ hack_codegen = hackGenerator.HackCodeGenerator() hh_codesynthesis.do_reasoning( additional_programs=hh_codesynthesis.generate_logic_rules(), generator=hack_codegen, ) self.assertEqual(str(hack_codegen), exp)
def test_extends_dependency_with_rule_extraction(self) -> None: exp = [ 'add_method("A","foo")', 'add_method("B","foo")', 'class("B")', 'class("I")', 'extends("A","T")', 'extends("B","I")', 'implements("B","A")', 'interface("A")', 'interface("T")', ] deps = """\ Extends A -> Type B Extends I -> Type B Extends T -> Type A Method A::foo -> Type B Type A -> Type B Type I -> Type B Type T -> Type A, Type B """ raw_codegen = hh_codesynthesis.CodeGenerator() additional_programs = hh_codesynthesis.extract_logic_rules(deps.split("\n")) hh_codesynthesis.do_reasoning( additional_programs=additional_programs, generator=raw_codegen ) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_type_dependency(self) -> None: # This one covered the 'has_method_with_parameter'. exp = ['class("B")', 'has_method_with_parameter("C","B")', 'interface("C")'] rules = ['type("B", "C").' 'symbols("B"; "C").'] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_clingo_exception(self) -> None: deps = ["rule_without_period(symbol1, symbol2)"] raw_codegen = hh_codesynthesis.CodeGenerator() with self.assertRaises(expected_exception=RuntimeError, msg="parsing failed"): hh_codesynthesis.do_reasoning( additional_programs=deps, generator=raw_codegen )
def extract_run_and_compare( self, deps: str, exp: str, generator: hh_codesynthesis.CodeGenerator ) -> None: additional_programs = hh_codesynthesis.extract_logic_rules(deps.split("\n")) hh_codesynthesis.do_reasoning( additional_programs=additional_programs, generator=generator ) self.assertEqual(str(generator), exp)
def test_fun_type_dependencies(self) -> None: # This one covered the 'invokes_function' with 'Type'. exp = [ 'class("A")', 'funcs("Fn")', 'interface("B")', 'invokes_function("A","Fn")', ] rules = ['invoked_by("Fn", "A").' 'symbols("A"; "B").' 'funcs("Fn").'] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_smethod_dependency_exception(self) -> None: # This one covered the unsatifiable part, that we can't find an answer. # Here we are forcing symbol("B") to get interface("B"). rules = [ 'static_method("A", "foo", "B").', 'interface("B").' 'symbols("A"; "B").', ] raw_codegen = hh_codesynthesis.CodeGenerator() with self.assertRaises(expected_exception=RuntimeError, msg="Unsatisfiable."): hh_codesynthesis.do_reasoning( additional_programs=rules, generator=raw_codegen )
def test_unsatisfiable_parameters(self) -> None: # Given 5 nodes, but asking for 3 classes + 4 interfaces with ClingoContext.number_of_nodes = 5 ClingoContext.min_classes = 3 ClingoContext.min_interfaces = 4 hack_codegen = hackGenerator.HackCodeGenerator() with self.assertRaises(expected_exception=RuntimeError, msg="Unsatisfiable."): hh_codesynthesis.do_reasoning( additional_programs=hh_codesynthesis.generate_logic_rules(), generator=hack_codegen, )
def test_smethod_fun_dependencies(self) -> None: # This one covered the 'invokes_static_method' with 'Fun', and we don't need to # pass the object as parameter, so that we directly invoke the static method. exp = [ 'add_static_method("B","foo")', 'class("B")', 'funcs("C")', 'interface("A")', 'invokes_static_method("C","B","foo")', ] rules = ['static_method("B", "foo", "C").' 'symbols("A"; "B").' 'funcs("C").'] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_method_dependency(self) -> None: # This one covered the 'invokes_in_method', as well as the # 'has_method_with_parameter', since we need to pass the object as parameter, # then invoke its method. exp = [ 'add_method("B","foo")', 'class("C")', 'has_method_with_parameter("C","B")', 'interface("B")', 'invokes_in_method("C","B","foo")', ] rules = ['method("B", "foo", "C").' 'symbols("B"; "C").'] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_extends_dependency_hack_codegen(self) -> None: exp = """\ <?hh class B extends I implements A {} class I {} interface A extends T {} interface T {} """ rules = [ 'extends_to("A", "B").', 'extends_to("I", "B").', 'extends_to("T", "A").', 'symbols("A";"B";"I";"T").', ] hack_codegen = hackGenerator.HackCodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=hack_codegen) self.assertEqual(str(hack_codegen), exp)
def test_hack_code_gen_with_partial_dependency_graph_given_by_user(self) -> None: ClingoContext.number_of_nodes = 12 ClingoContext.min_depth = 3 ClingoContext.min_classes = 3 ClingoContext.min_interfaces = 4 ClingoContext.lower_bound = 1 ClingoContext.higher_bound = 5 ClingoContext.avg_width = 0 deps = """\ Extends A -> Type B Extends I -> Type B Extends T -> Type A Type A -> Type B Type I -> Type B Type T -> Type A, Type B""" exp = """\ <?hh class S9 {} class S10 {} class S11 {} interface A extends T {} interface B extends A,I {} interface I {} interface T {} interface S0 {} interface S1 {} interface S2 {} interface S3 {} interface S4 extends S0 {} interface S5 {} interface S6 {} interface S7 {} interface S8 extends S4 {} """ hack_codegen = hackGenerator.HackCodeGenerator() combined_rules = ( hh_codesynthesis.generate_logic_rules() + hh_codesynthesis.extract_logic_rules(deps.split("\n")) ) hh_codesynthesis.do_reasoning( additional_programs=combined_rules, generator=hack_codegen, ) self.assertEqual(str(hack_codegen), exp)
def test_interface_type_fun_dependency(self) -> None: # This one covered the 'has_parameter_and_argument' with <'Type', 'Fun'>. exp = [ 'class("B")', 'funcs("Fn")', 'has_parameter_and_argument("Fn","A","B")', 'implements("B","A")', 'interface("A")', ] rules = [ 'type("A", "Fn").' 'symbols("A"; "B").' 'funcs("Fn").' 'extends_to("A","B").' ] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_method_type_extends_dependencies(self) -> None: # This one covered the 'override' in the "Extend" and "Method" edge. exp = [ 'add_method("B","foo")', 'add_method("C","foo")', 'class("C")', 'implements("C","B")', 'interface("B")', ] rules = [ 'extends_to("B", "C").', 'method("B", "foo", "C").', 'type("B", "C").', 'symbols("B"; "C").', ] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_extends_dependency(self) -> None: exp = [ 'class("B")', 'class("I")', 'extends("A","T")', 'extends("B","I")', 'implements("B","A")', 'interface("A")', 'interface("T")', ] rules = [ 'extends_to("A", "B").', 'extends_to("I", "B").', 'extends_to("T", "A").', 'symbols("A";"B";"I";"T").', ] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_class_method_fun_dependency(self) -> None: # This one covered the 'creates_in_body' with <'Method', 'Fun'>. exp = [ 'add_method("B","foo")', 'class("B")', 'creates_in_body("Fn","B")', 'funcs("Fn")', 'implements("B","A")', 'interface("A")', 'invokes_in_body("Fn","B","foo")', ] rules = [ 'method("B", "foo", "Fn").' 'symbols("A"; "B").' 'funcs("Fn").' 'extends_to("A","B").' ] raw_codegen = hh_codesynthesis.CodeGenerator() hh_codesynthesis.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)