Exemple #1
0
    def test_dependency_graph(self):
        """Test that dependency graph gets updated correctly."""
        run = runtime.Runtime()
        run.debug_mode()
        g = run.global_dependency_graph

        run.create_policy('test')

        run.insert('p(x) :- q(x), nova:q(x)', target='test')
        self.assertTrue(g.edge_in('test:p', 'nova:q', False))
        self.assertTrue(g.edge_in('test:p', 'test:q', False))

        run.insert('p(x) :- s(x)', target='test')
        self.assertTrue(g.edge_in('test:p', 'nova:q', False))
        self.assertTrue(g.edge_in('test:p', 'test:q', False))
        self.assertTrue(g.edge_in('test:p', 'test:s', False))

        run.insert('q(x) :- nova:r(x)', target='test')
        self.assertTrue(g.edge_in('test:p', 'nova:q', False))
        self.assertTrue(g.edge_in('test:p', 'test:q', False))
        self.assertTrue(g.edge_in('test:p', 'test:s', False))
        self.assertTrue(g.edge_in('test:q', 'nova:r', False))

        run.delete('p(x) :- q(x), nova:q(x)', target='test')
        self.assertTrue(g.edge_in('test:p', 'test:s', False))
        self.assertTrue(g.edge_in('test:q', 'nova:r', False))

        run.update([
            runtime.Event(helper.str2form('p(x) :- q(x), nova:q(x)'),
                          target='test')
        ])
        self.assertTrue(g.edge_in('test:p', 'nova:q', False))
        self.assertTrue(g.edge_in('test:p', 'test:q', False))
        self.assertTrue(g.edge_in('test:p', 'test:s', False))
        self.assertTrue(g.edge_in('test:q', 'nova:r', False))
 def test_column_references_lowlevel(self):
     """Test column-references with low-level checks."""
     # do the first one the painful way, to ensure the parser
     #   is doing something reasonable.
     run = runtime.Runtime()
     run.create_policy('nova')
     nova_schema = compile.Schema({'q': ('id', 'name', 'status')})
     run.set_schema('nova', nova_schema, complete=True)
     code = ("p(x) :- nova:q(id=x)")
     actual = run.parse(code)
     self.assertEqual(len(actual), 1)
     rule = actual[0]
     self.assertEqual(len(rule.heads), 1)
     self.assertEqual(rule.head.table, "p")
     self.assertEqual(len(rule.head.arguments), 1)
     self.assertEqual(rule.head.arguments[0].name, 'x')
     self.assertEqual(len(rule.body), 1)
     lit = rule.body[0]
     self.assertFalse(lit.is_negated())
     self.assertEqual(lit.table, "q")
     self.assertEqual(len(lit.arguments), 3)
     self.assertEqual(lit.arguments[0].name, 'x')
     self.assertNotEqual(lit.arguments[0].name, lit.arguments[1].name)
     self.assertNotEqual(lit.arguments[0].name, lit.arguments[2].name)
     self.assertNotEqual(lit.arguments[1].name, lit.arguments[2].name)
    def test_column_references_multiple_atoms(self):
        """Test column references occurring in multiple atoms in a rule."""
        run = runtime.Runtime()
        run.create_policy('nova')
        schema = compile.Schema({
            'q': ('id', 'name', 'status'),
            'r': ('id', 'age', 'weight')
        })
        run.set_schema('nova', schema, complete=True)

        # Multiple atoms
        code = ("p(x) :- nova:q(id=x, 2=y), nova:r(id=x)")
        actual = run.parse(code)
        correct = "p(x) :- nova:q(x, x0, y), nova:r(x, y0, y1)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Multiple atoms')

        # Multiple atoms sharing column name but different variables
        code = ("p(x) :- nova:q(id=x), nova:r(id=y)")
        actual = run.parse(code)
        correct = "p(x) :- nova:q(x, x0, x1), nova:r(y, y0, y1)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Multiple atoms shared column name')

        # Multiple atoms, same table
        code = ("p(x) :- nova:q(id=x, 2=y), nova:q(id=x)")
        actual = run.parse(code)
        correct = "p(x) :- nova:q(x, x0, y), nova:q(x, y0, y1)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Multiple atoms, same table')
Exemple #4
0
 def test_policy_errors(self):
     """Test errors for multiple policies."""
     # errors
     run = runtime.Runtime()
     run.create_policy('existent')
     self.assertRaises(KeyError, run.create_policy, 'existent')
     self.assertRaises(KeyError, run.delete_policy, 'nonexistent')
     self.assertRaises(KeyError, run.policy_object, 'nonexistent')
Exemple #5
0
 def test_initialize_tables(self):
     """Test initialize_tables() functionality of Runtime."""
     run = runtime.Runtime()
     run.create_policy('test')
     run.insert('p(1) p(2)')
     run.initialize_tables(['p'], ['p(3)', 'p(4)'])
     e = helper.datalog_equal(run.select('p(x)'), 'p(3) p(4)')
     self.assertTrue(e)
Exemple #6
0
    def setUp(self):
        super(TestRuntimePerformance, self).setUp()

        self._runtime = runtime.Runtime()
        self._runtime.create_policy(NREC_THEORY,
                                    kind=base.NONRECURSIVE_POLICY_TYPE)
        self._runtime.create_policy(DB_THEORY, kind=base.DATABASE_POLICY_TYPE)
        self._runtime.debug_mode()
        self._runtime.insert('', target=NREC_THEORY)
Exemple #7
0
    def test_dump_load(self):
        """Test if dumping/loading theories works properly."""
        run = runtime.Runtime()
        run.create_policy('test')
        run.debug_mode()
        policy = ('p(4,"a","bcdef ghi", 17.1) '
                  'p(5,"a","bcdef ghi", 17.1) '
                  'p(6,"a","bcdef ghi", 17.1)')
        run.insert(policy)

        full_path = os.path.realpath(__file__)
        path = os.path.dirname(full_path)
        path = os.path.join(path, "snapshot")
        run.dump_dir(path)
        run = runtime.Runtime()
        run.load_dir(path)
        e = helper.datalog_equal(run.theory['test'].content_string(), policy,
                                 'Service theory dump/load')
        self.assertTrue(e)
Exemple #8
0
 def test_external(self):
     """Test ability to write rules that span multiple policies."""
     # External theory
     run = runtime.Runtime()
     run.create_policy('test1')
     run.insert('q(1)', target='test1')
     run.insert('q(2)', target='test1')
     run.create_policy('test2')
     run.insert('p(x) :- test1:q(x)', target='test2')
     actual = run.select('p(x)', target='test2')
     e = helper.db_equal(actual, 'p(1) p(2)')
     self.assertTrue(e, "Basic")
    def test_column_references_atom_errors(self):
        """Test invalid column references occurring in a single atom."""
        run = runtime.Runtime()
        run.create_policy('nova')
        schema = compile.Schema({
            'q': ('id', 'name', 'status'),
            'r': ('id', 'age', 'weight')
        })
        run.set_schema('nova', schema, complete=True)

        def check_err(code, errmsg, msg):
            try:
                run.parse(code)
                self.fail("Error should have been thrown but was not: " + msg)
            except compile.CongressException as e:
                emsg = "Err message '{}' should include '{}'".format(
                    str(e), errmsg)
                self.assertTrue(errmsg in str(e), msg + ": " + emsg)

        check_err('p(x) :- q(id=x, 0=y)',
                  'columns for table q have not been declared',
                  'Missing schema')

        check_err('p(x) :- nova:q(id=x, birthday=y)',
                  'column name birthday does not exist', 'Unknown column name')

        check_err('p(x) :- nova:q(id=x, status=x, id=y)',
                  'two values for column name id',
                  'Multiple values for column name')

        check_err('p(x) :- nova:q(4=y)', 'column number 4 is too large',
                  'Large column number')

        check_err('p(x) :- nova:q(4=y, id=w, 4=z)',
                  'two values for column number 4',
                  'Multiple values for column number')

        check_err('p(x) :- nova:q(id=x, 0=y)',
                  'column was given two values by reference parameters',
                  'Conflict between name and number references')

        check_err('p(x) :- nova:q(x, y, id=z)',
                  'already provided by position arguments',
                  'Conflict between name and position')

        check_err('p(x) :- nova:q(x, y, 1=z)',
                  '1 is already provided by position arguments',
                  'Conflict between name and position')

        check_err('p(x) :- nova:q(x, 1=z, y)',
                  'positional parameter after a reference parameter',
                  'Positional parameter after reference parameter')
Exemple #10
0
 def test_multipolicy_head(self):
     """Test SELECT with different policy in the head."""
     run = runtime.Runtime()
     run.debug_mode()
     run.create_policy('test1', kind='action')
     run.create_policy('test2', kind='action')
     (permitted, errors) = run.insert('test2:p+(x) :- q(x)', 'test1')
     self.assertTrue(permitted, "modals with policy names must be allowed")
     run.insert('q(1)', 'test1')
     run.insert('p(2)', 'test2')
     actual = run.select('test2:p+(x)', 'test1')
     e = helper.db_equal(actual, 'test2:p+(1)')
     self.assertTrue(e, "Policy name in the head")
Exemple #11
0
 def test_local(self):
     """Test ability to write rules that span multiple policies."""
     # Local table used
     run = runtime.Runtime()
     run.create_policy('test1')
     run.insert('q(1)', target='test1')
     run.insert('q(2)', target='test1')
     run.create_policy('test2')
     run.insert('p(x) :- test1:q(x), q(x)', target='test2')
     run.insert('q(2)', 'test2')
     actual = run.select('p(x)', target='test2')
     e = helper.db_equal(actual, 'p(2)')
     self.assertTrue(e, "Local table used")
Exemple #12
0
 def prep_runtime(self, code=None, msg=None, target=None, theories=None):
     if code is None:
         code = ""
     if target is None:
         target = self.DEFAULT_THEORY
     run = runtime.Runtime()
     run.create_policy(self.DEFAULT_THEORY)
     run.create_policy(self.ACTION_THEORY, kind='action')
     if theories:
         for theory in theories:
             run.create_policy(theory)
     run.debug_mode()
     run.insert(code, target=target)
     return run
Exemple #13
0
 def test_multi_external(self):
     """Test multiple rules that span multiple policies."""
     run = runtime.Runtime()
     run.debug_mode()
     run.create_policy('test1')
     run.create_policy('test2')
     run.create_policy('test3')
     run.insert('p(x) :- test2:p(x)', target='test1')
     run.insert('p(x) :- test3:p(x)', target='test1')
     run.insert('p(1)', target='test2')
     run.insert('p(2)', target='test3')
     actual = run.select('p(x)', target='test1')
     e = helper.db_equal(actual, 'p(1) p(2)')
     self.assertTrue(e, "Multiple external rules with multiple policies")
 def prep_runtime(self, code=None, msg=None, target=None):
     # compile source
     if msg is not None:
         LOG.debug(msg)
     if code is None:
         code = ""
     if target is None:
         target = MAT_THEORY
     run = runtime.Runtime()
     run.theory[NREC_THEORY] = runtime.NonrecursiveRuleTheory()
     run.theory[DB_THEORY] = runtime.Database()
     run.theory[MAT_THEORY] = runtime.MaterializedViewTheory()
     run.debug_mode()
     run.insert(code, target=target)
     return run
Exemple #15
0
 def test_single_policy(self):
     """Test ability to create/delete single policies."""
     # single policy
     run = runtime.Runtime()
     original = run.policy_names()
     run.create_policy('test1')
     run.insert('p(x) :- q(x)', 'test1')
     run.insert('q(1)', 'test1')
     self.assertEqual(run.select('p(x)', 'test1'), 'p(1)',
                      'Policy creation')
     self.assertEqual(run.select('p(x)', 'test1'), 'p(1)',
                      'Policy creation')
     run.delete_policy('test1')
     self.assertEqual(set(run.policy_names()), set(original),
                      'Policy deletion')
Exemple #16
0
 def prep_runtime(self, code=None, msg=None, target=None):
     # compile source
     if msg is not None:
         LOG.debug(msg)
     if code is None:
         code = ""
     if target is None:
         target = MAT_THEORY
     run = runtime.Runtime()
     run.create_policy(MAT_THEORY, kind=MATERIALIZED_POLICY_TYPE)
     run.create_policy(DB_THEORY, kind=DATABASE_POLICY_TYPE)
     # ensure inserts without target go to MAT_THEORY
     run.DEFAULT_THEORY = MAT_THEORY
     run.debug_mode()
     run.insert(code, target=target)
     return run
Exemple #17
0
 def test_multi_policy(self):
     """Test ability to create/delete multiple policies."""
     # multiple policies
     run = runtime.Runtime()
     original = run.policy_names()
     run.create_policy('test2')
     run.create_policy('test3')
     self.assertEqual(set(run.policy_names()),
                      set(original + ['test2', 'test3']),
                      'Multi policy creation')
     run.delete_policy('test2')
     run.create_policy('test4')
     self.assertEqual(set(run.policy_names()),
                      set(original + ['test3', 'test4']),
                      'Multiple policy deletion')
     run.insert('p(x) :- q(x)  q(1)', 'test4')
     self.assertEqual(run.select('p(x)', 'test4'), 'p(1)',
                      'Multipolicy deletion select')
Exemple #18
0
 def test_multiple_levels_external(self):
     """Test ability to write rules that span multiple policies."""
     # Multiple levels of external theories
     run = runtime.Runtime()
     run.debug_mode()
     run.create_policy('test1')
     run.insert('p(x) :- test2:q(x), test3:q(x)', target='test1')
     run.insert('s(3) s(1) s(2) s(4)', target='test1')
     run.create_policy('test2')
     run.insert('q(x) :- test4:r(x)', target='test2')
     run.create_policy('test3')
     run.insert('q(x) :- test1:s(x)', target='test3')
     run.create_policy('test4')
     run.insert('r(1)', target='test4')
     run.insert('r(2)', target='test4')
     run.insert('r(5)', target='test4')
     actual = run.select('p(x)', target='test1')
     e = helper.db_equal(actual, 'p(1) p(2)')
     self.assertTrue(e, "Multiple levels of external theories")
Exemple #19
0
    def test_multipolicy_normal_errors(self):
        """Test errors arising from rules in multiple policies."""
        run = runtime.Runtime()
        run.debug_mode()
        run.create_policy('test1')

        # policy in head of rule
        (permitted, errors) = run.insert('test2:p(x) :- q(x)', 'test1')
        self.assertFalse(permitted)
        self.assertTrue("should not reference any policy" in str(errors[0]))

        # policy in head of rule with update
        (permitted, errors) = run.insert('test2:p+(x) :- q(x)', 'test1')
        self.assertFalse(permitted)
        self.assertTrue("should not reference any policy" in str(errors[0]))

        # policy in head of rule with update
        (permitted, errors) = run.insert('test2:p-(x) :- q(x)', 'test1')
        self.assertFalse(permitted)
        self.assertTrue("should not reference any policy" in str(errors[0]))

        # policy in head of fact
        (permitted, errors) = run.insert('test2:p(1)', 'test1')
        self.assertFalse(permitted)
        self.assertTrue("should not reference any policy" in str(errors[0]))

        # policy in head of fact
        (permitted, errors) = run.insert('test2:p+(1)', 'test1')
        self.assertFalse(permitted)
        self.assertTrue("should not reference any policy" in str(errors[0]))

        # policy in head of fact
        (permitted, errors) = run.insert('test2:p-(1)', 'test1')
        self.assertFalse(permitted)
        self.assertTrue("should not reference any policy" in str(errors[0]))

        # recursion across policies
        run.insert('p(x) :- test2:q(x)', target='test1')
        run.create_policy('test2')
        (permit, errors) = run.insert('q(x) :- test1:p(x)', target='test2')
        self.assertFalse(permit, "Recursion across theories should fail")
        self.assertEqual(len(errors), 1)
        self.assertTrue("Rules are recursive" in str(errors[0]))
Exemple #20
0
 def test_policy_types(self):
     """Test types for multiple policies."""
     # policy types
     run = runtime.Runtime()
     run.create_policy('test1', kind=NONRECURSIVE_POLICY_TYPE)
     self.assertTrue(
         isinstance(run.policy_object('test1'),
                    runtime.NonrecursiveRuleTheory),
         'Nonrecursive policy addition')
     run.create_policy('test2', kind=ACTION_POLICY_TYPE)
     self.assertTrue(
         isinstance(run.policy_object('test2'), runtime.ActionTheory),
         'Action policy addition')
     run.create_policy('test3', kind=DATABASE_POLICY_TYPE)
     self.assertTrue(
         isinstance(run.policy_object('test3'), runtime.Database),
         'Database policy addition')
     run.create_policy('test4', kind=MATERIALIZED_POLICY_TYPE)
     self.assertTrue(
         isinstance(run.policy_object('test4'),
                    runtime.MaterializedViewTheory),
         'Materialized policy addition')
Exemple #21
0
    def test_multi_policy_update(self):
        """Test updates that apply to multiple policies."""
        def check_equal(actual, correct):
            e = helper.datalog_equal(actual, correct)
            self.assertTrue(e)

        run = runtime.Runtime()
        run.create_policy('th1')
        run.create_policy('th2')

        events1 = [
            runtime.Event(formula=x, insert=True, target='th1')
            for x in helper.str2pol("p(1) p(2) q(1) q(3)")
        ]
        events2 = [
            runtime.Event(formula=x, insert=True, target='th2')
            for x in helper.str2pol("r(1) r(2) t(1) t(4)")
        ]
        run.update(events1 + events2)

        check_equal(run.select('p(x)', 'th1'), 'p(1) p(2)')
        check_equal(run.select('q(x)', 'th1'), 'q(1) q(3)')
        check_equal(run.select('r(x)', 'th2'), 'r(1) r(2)')
        check_equal(run.select('t(x)', 'th2'), 't(1) t(4)')
    def test_module_schemas(self):
        """Test that rules are properly checked against module schemas."""

        run = runtime.Runtime()
        run.create_policy('mod1')
        run.create_policy('mod2')
        run.set_schema('mod1',
                       compile.Schema({
                           'p': (1, 2, 3),
                           'q': (1, )
                       }),
                       complete=True)
        run.set_schema('mod2',
                       compile.Schema({
                           'p': (1, ),
                           'q': (1, 2)
                       }),
                       complete=True)

        def check_err(code_string, theory, emsg, msg, f=compile.rule_errors):
            rule = compile.parse1(code_string)
            errs = f(rule, run.theory, theory)
            self.assertTrue(
                any(emsg in str(err) for err in errs),
                msg + ":: Failed to find error message '" + emsg + "' in: " +
                ";".join(str(e) for e in errs))

        # no errors
        rule = compile.parse1('p(x) :- q(x), mod1:p(x, y, z), mod2:q(x, y), '
                              'mod1:q(t), mod2:p(t)')
        errs = compile.rule_errors(rule, run.theory)
        self.assertEqual(len(errs), 0, "Should not have found any errors")

        # unknown table within module
        check_err('p(x) :- q(x), mod1:r(x), r(x)', 'mod3', 'unknown table',
                  'Unknown table for rule')

        # wrong number of arguments
        check_err('p(x) :- q(x), mod1:p(x,y,z,w), r(x)', 'mod3',
                  'only 3 arguments are permitted',
                  'Wrong number of arguments for rule')

        # same tests for an atom

        # no errors
        atom = compile.parse1('p(1, 2, 2)')
        errs = compile.fact_errors(atom, run.theory, 'mod1')
        self.assertEqual(len(errs), 0, "Should not have found any errors")

        # unknown table within module
        check_err('r(1)',
                  'mod1',
                  'unknown table',
                  'Unknown table for atom',
                  f=compile.fact_errors)

        # wrong number of arguments
        check_err('p(1, 2, 3, 4)',
                  'mod1',
                  'only 3 arguments are permitted',
                  'Wrong number of arguments for atom',
                  f=compile.fact_errors)
    def test_column_references_atom(self):
        """Test column references occurring in a single atom in a rule."""
        run = runtime.Runtime()
        run.create_policy('nova')
        nova_schema = compile.Schema({'q': ('id', 'name', 'status')})
        run.set_schema('nova', nova_schema, complete=True)

        # Multiple column names
        code = ("p(x) :- nova:q(id=x, status=y)")
        actual = run.parse(code)
        correct = "p(x) :- nova:q(x, w, y)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Multiple column names')

        # Multiple column numbers
        code = ("p(x) :- nova:q(0=x, 1=y, 2=z)")
        actual = run.parse(code)
        correct = "p(x) :- nova:q(x, y, z)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Multiple column numbers')

        # Mix column names and numbers
        code = ("p(x) :- nova:q(id=x, 2=y)")
        actual = run.parse(code)
        correct = "p(x) :- nova:q(x, w, y)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Mix names and numbers')

        # Object constants
        code = ("p(x) :- nova:q(id=3, 2=2)")
        actual = run.parse(code)
        correct = "p(x) :- nova:q(3, w, 2)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Object constants')

        # Out of order
        code = ("p(x, y) :- nova:q(status=y, id=x)")
        actual = run.parse(code)
        correct = "p(x, y) :- nova:q(x, z, y)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Out of order')

        # Out of order with numbers
        code = ("p(x, y) :- nova:q(1=y, 0=x)")
        actual = run.parse(code)
        correct = "p(x, y) :- nova:q(x, y, z)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Out of order with numbers')

        # Positional plus named
        code = ("p(x, y) :- nova:q(x, status=y)")
        actual = run.parse(code)
        correct = "p(x, y) :- nova:q(x, z, y)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Positional plus named')

        # Positional plus named 2
        code = ("p(x, y, z) :- nova:q(x, y, 2=z)")
        actual = run.parse(code)
        correct = "p(x, y, z) :- nova:q(x, y, z)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Positional plus named 2')

        # Pure positional (different since we are providing schema)
        code = ("p(x, y, z) :- nova:q(x, y, z)")
        actual = run.parse(code)
        correct = "p(x, y, z) :- nova:q(x, y, z)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Pure positional')

        # Pure positional (without schema)
        code = ("p(x) :- nova:q(x, y, z)")
        run.delete_policy('nova')
        actual = run.parse(code)
        correct = "p(x) :- nova:q(x, y, z)"
        eq = helper.datalog_same(helper.pol2str(actual), correct)
        self.assertTrue(eq, 'Pure positional without schema')
 def prep_runtime(enforce_theory, action_theory, class_theory):
     run = runtime.Runtime()
     run.insert(enforce_theory, target=run.ENFORCEMENT_THEORY)
     run.insert(action_theory, target=run.ACTION_THEORY)
     run.insert(class_theory, target=run.CLASSIFY_THEORY)
     return run
    def test_neutron_actions(self):
        """Test our encoding of the Neutron actions basics by simulation."""
        def check(query, action_sequence, correct, msg):
            actual = run.simulate(query, action_sequence)
            LOG.debug("Simulate results: %s", actual)
            self.check_instance(actual, correct, msg)

        full_path = os.path.realpath(__file__)
        path = os.path.dirname(full_path)
        neutron_path = path + "/../../../examples/neutron.action"
        run = runtime.Runtime()
        run.debug_mode()
        permitted, errs = run.load_file(neutron_path, target=run.ACTION_THEORY)
        if not permitted:
            self.assertTrue(
                permitted, "Error in Neutron file: {}".format("\n".join(
                    [str(x) for x in errs])))
            return

        # Ports
        query = 'neutron:port(x1, x2, x3, x4, x5, x6, x7, x8, x9)'
        acts = 'neutron:create_port("net1", 17), sys:user("tim") :- true'
        correct = ('neutron:port(id, "net1", name, mac, "null",'
                   '"null", z, w, "tim")')
        check(query, acts, correct, 'Simple port creation')

        query = 'neutron:port(x1, x2, x3, x4, x5, x6, x7, x8, x9)'
        # result(uuid): simulation-specific table that holds the results
        #  of the last action invocation
        acts = ('neutron:create_port("net1", 17), sys:user("tim") :- true '
                'neutron:update_port(uuid, 18), sys:user("tim"), '
                '    options:value(18, "name", "tims port") :- result(uuid) ')
        correct = ('neutron:port(id, "net1", "tims port", mac, "null",'
                   '"null", z, w, "tim")')
        check(query, acts, correct, 'Port create, update')

        query = 'neutron:port(x1, x2, x3, x4, x5, x6, x7, x8, x9)'
        # result(uuid): simulation-specific table that holds the results
        #  of the last action invocation
        acts = ('neutron:create_port("net1", 17), sys:user("tim") :- true '
                'neutron:update_port(uuid, 18), sys:user("tim"), '
                '    options:value(18, "name", "tims port") :- result(uuid) '
                'neutron:delete_port(uuid), sys:user("tim")'
                '    :- result(uuid) ')
        correct = ''
        check(query, acts, correct, 'Port create, update, delete')

        # Networks
        query = ('neutron:network(id, name, status, admin_state, shared,'
                 'tenenant_id)')
        acts = 'neutron:create_network(17), sys:user("tim") :- true'
        correct = 'neutron:network(id, "", status, "true", "true", "tim")'
        check(query, acts, correct, 'Simple network creation')

        query = ('neutron:network(id, name, status, admin_state, '
                 'shared, tenenant_id)')
        acts = ('neutron:create_network(17), sys:user("tim") :- true '
                'neutron:update_network(uuid, 18), sys:user("tim"), '
                '  options:value(18, "admin_state", "false") :- result(uuid)')
        correct = 'neutron:network(id, "", status, "false", "true", "tim")'
        check(query, acts, correct, 'Network creation, update')

        query = ('neutron:network(id, name, status, admin_state, shared, '
                 'tenenant_id)')
        acts = ('neutron:create_network(17), sys:user("tim") :- true '
                'neutron:update_network(uuid, 18), sys:user("tim"), '
                '  options:value(18, "admin_state", "false") :- result(uuid)'
                'neutron:delete_network(uuid) :- result(uuid)')
        correct = ''
        check(query, acts, correct, 'Network creation, update')

        # Subnets
        query = ('neutron:subnet(id, name, network_id, '
                 'gateway_ip, ip_version, cidr, enable_dhcp, tenant_id)')
        acts = ('neutron:create_subnet("net1", "10.0.0.1/24", 17), '
                'sys:user("tim") :- true')
        correct = ('neutron:subnet(id, "", "net1", gateway_ip, 4, '
                   '"10.0.0.1/24", "true", "tim")')
        check(query, acts, correct, 'Simple subnet creation')

        query = ('neutron:subnet(id, name, network_id, '
                 'gateway_ip, ip_version, cidr, enable_dhcp, tenant_id)')
        acts = ('neutron:create_subnet("net1", "10.0.0.1/24", 17), '
                'sys:user("tim") :- true '
                'neutron:update_subnet(uuid, 17), sys:user("tim"), '
                '   options:value(17, "enable_dhcp", "false") :- result(uuid)')
        correct = ('neutron:subnet(id, "", "net1", gateway_ip, 4, '
                   '"10.0.0.1/24", "false", "tim")')
        check(query, acts, correct, 'Subnet creation, update')

        query = ('neutron:subnet(id, name, network_id, '
                 'gateway_ip, ip_version, cidr, enable_dhcp, tenant_id)')
        acts = ('neutron:create_subnet("net1", "10.0.0.1/24", 17), '
                'sys:user("tim") :- true '
                'neutron:update_subnet(uuid, 17), sys:user("tim"), '
                '   options:value(17, "enable_dhcp", "false") :- result(uuid)'
                'neutron:delete_subnet(uuid) :- result(uuid)')
        correct = ''
        check(query, acts, correct, 'Subnet creation, update, delete')