def test_clingo_exception(self) -> None: deps = ["rule_without_period(symbol1, symbol2)"] raw_codegen = agentGenerator.CodeGenerator() with self.assertRaises(expected_exception=RuntimeError, msg="parsing failed"): agentGenerator.do_reasoning(additional_programs=deps, generator=raw_codegen)
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 = agentGenerator.CodeGenerator() additional_programs = agentGenerator.extract_logic_rules( deps.split("\n")) agentGenerator.do_reasoning(additional_programs=additional_programs, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def create_agent(agents: List[Agent], agent_numbers: List[int], profiles: List[Dict[str, Any]]): for index, agent_number in enumerate(agent_numbers): # The number of agents may greater than the number of profiles # So, we are round robin through each profile for the agent here. profile = profiles[index % len(profiles)] solving_context = ClingoContext( number_of_nodes=profile["number_of_nodes"], min_depth=profile["min_depth"], min_classes=profile["min_classes"], min_interfaces=profile["min_interfaces"], lower_bound=profile["lower_bound"], higher_bound=profile["higher_bound"], min_stub_classes=profile["min_stub_classes"], min_stub_interfaces=profile["min_stub_interfaces"], degree_distribution=profile["degree_distribution"], ) generator = HackCodeGenerator(solving_context) # To avoid two agents using same profile to produce the same output, # we are using model_count to enumerate the next solution with this profile. generator.model_count = index // len(profiles) combined_rules = agentGenerator.generate_logic_rules( solving_context, f"A{agent_number}") agents[agent_number] = Agent(generator, solving_context) agentGenerator.do_reasoning(combined_rules, generator)
def extract_run_and_compare( self, deps: str, exp: str, generator: agentGenerator.CodeGenerator) -> None: additional_programs = agentGenerator.extract_logic_rules( deps.split("\n")) agentGenerator.do_reasoning(additional_programs=additional_programs, generator=generator) self.assertEqual(str(generator), 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 = agentGenerator.CodeGenerator() agentGenerator.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 = agentGenerator.CodeGenerator() with self.assertRaises(expected_exception=RuntimeError, msg="Unsatisfiable."): agentGenerator.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 solving_context = ClingoContext(number_of_nodes=5, min_classes=3, min_interfaces=4) hack_codegen = hackGenerator.HackCodeGenerator(solving_context) with self.assertRaises(expected_exception=RuntimeError, msg="Unsatisfiable."): agentGenerator.do_reasoning( additional_programs=agentGenerator.generate_logic_rules( solving_context), generator=hack_codegen, )
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 = agentGenerator.CodeGenerator() agentGenerator.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_smethod_type_dependencies(self) -> None: # This one covered the 'invokes_static_method' with 'Type', 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")', 'class("C")', 'interface("A")', 'invokes_static_method("C","B","foo")', ] rules = ['static_method("B", "foo", "C").', 'symbols("A"; "B"; "C").'] raw_codegen = agentGenerator.CodeGenerator() agentGenerator.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 = agentGenerator.CodeGenerator() agentGenerator.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() agentGenerator.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: solving_context = ClingoContext( number_of_nodes=12, min_depth=3, min_classes=3, min_interfaces=4, lower_bound=1, higher_bound=5, ) 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(solving_context) combined_rules = agentGenerator.generate_logic_rules( solving_context) + agentGenerator.extract_logic_rules( deps.split("\n")) agentGenerator.do_reasoning(additional_programs=combined_rules, generator=hack_codegen) self.assertEqual(str(hack_codegen), 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 = agentGenerator.CodeGenerator() agentGenerator.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), 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 = agentGenerator.CodeGenerator() agentGenerator.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)
def test_hack_code_gen(self) -> None: solving_context = ClingoContext( number_of_nodes=12, min_depth=3, min_classes=3, min_interfaces=4, lower_bound=1, higher_bound=5, min_stub_classes=4, min_stub_interfaces=1, degree_distribution=[1, 3, 5], ) hack_codegen = hackGenerator.HackCodeGenerator(solving_context) agentGenerator.do_reasoning( additional_programs=agentGenerator.generate_logic_rules( solving_context), generator=hack_codegen, ) self.assertTrue(hack_codegen.validate())
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 = agentGenerator.CodeGenerator() agentGenerator.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 = agentGenerator.CodeGenerator() agentGenerator.do_reasoning(additional_programs=rules, generator=raw_codegen) self.assertListEqual(sorted(str(raw_codegen).split()), exp)