diff --git a/tests/test_create_layout.py b/tests/test_create_layout.py index 2817c5a..397ddf2 100644 --- a/tests/test_create_layout.py +++ b/tests/test_create_layout.py @@ -1,9 +1,10 @@ import unittest -import before_after_filesystem_snapshot +import create_layout +import in_toto.models.link -class Test_before_after_filesystem_snapshot(unittest.TestCase): +class Test_CreateLayout(unittest.TestCase): - '''Check whether the output of before_after_filesystem_snapshot is as defined + '''Check whether the output of create_layout is as defined by each test case.''' before = { @@ -13,6 +14,44 @@ class Test_before_after_filesystem_snapshot(unittest.TestCase): 'bar/bat/four.tgz': '6677889900112233' } + first_step_link_str = { + '_type': 'link', + 'name': 'first_step', + 'byproducts': {}, + 'environment': {}, + 'materials': {}, + 'command': [], + 'products': { + 'one.tgz': {'sha256': '1234567890abcdef'}, + 'foo/two.tgz': {'sha256': '0000001111112222'}, + 'three.txt': {'sha256': '1111222233334444'}, + 'bar/bat/four.tgz': {'sha256': '6677889900112233'} + } + } + + second_step_link_str = { + '_type': 'link', + 'name': 'second_step', + 'byproducts': {}, + 'environment': {}, + 'materials': { + 'one.tgz': {'sha256': '1234567890abcdef'}, + 'foo/two.tgz': {'sha256': '0000001111112222'}, + 'three.txt': {'sha256': '1111222233334444'}, + 'bar/bat/four.tgz': {'sha256': '6677889900112233'} + }, + 'command': [], + 'products': { + 'five.txt': {'sha256': '5555555555555555'}, + 'one.tgz': {'sha256': '1234567890abcdef'}, + 'foo/two.tgz': {'sha256': 'ffffffffffffffff'}, + 'bar/bat/four.tgz': {'sha256': '6677889900112233'}, + 'baz/six.tgz': {'sha256': '6666666666666666'} + } + } + + empty_set = set() + def test_same_filesystem_snapshot(self): after = { @@ -22,18 +61,28 @@ def test_same_filesystem_snapshot(self): 'bar/bat/four.tgz': '6677889900112233' } - snapshot = before_after_filesystem_snapshot.snapshot(self.before, after) - self.assertEqual(snapshot, (['bar/bat/four.tgz', 'foo/two.tgz', 'one.tgz', - 'three.txt'], [], [], [])) + unchanged, modified, added, deleted = \ + create_layout.changes_between_snapshots(self.before, after) + + self.assertEqual(unchanged, + {'one.tgz', 'foo/two.tgz', 'three.txt', 'bar/bat/four.tgz'}) + self.assertSetEqual(modified, self.empty_set) + self.assertSetEqual(added, self.empty_set) + self.assertSetEqual(deleted, self.empty_set) def test_removed_files_filesystem_snapshot(self): after = {} - snapshot = before_after_filesystem_snapshot.snapshot(self.before, after) - self.assertEqual(snapshot, ([], [], [], ['bar/bat/four.tgz', 'foo/two.tgz', - 'one.tgz', 'three.txt'])) + unchanged, modified, added, deleted = \ + create_layout.changes_between_snapshots(self.before, after) + + self.assertSetEqual(unchanged, self.empty_set) + self.assertSetEqual(modified, self.empty_set) + self.assertSetEqual(added, self.empty_set) + self.assertSetEqual(deleted, + {'bar/bat/four.tgz', 'foo/two.tgz', 'one.tgz', 'three.txt'}) def test_new_filesystem_snapshot(self): @@ -43,10 +92,15 @@ def test_new_filesystem_snapshot(self): 'foofoo/seven.txt': '1111222233334555' } - snapshot = before_after_filesystem_snapshot.snapshot(self.before, after) - self.assertEqual(snapshot, ([], [], ['five.tgz', 'foo/bar/six.tgz', - 'foofoo/seven.txt'], ['bar/bat/four.tgz', 'foo/two.tgz', 'one.tgz', - 'three.txt'])) + unchanged, modified, added, deleted = \ + create_layout.changes_between_snapshots(self.before, after) + + self.assertSetEqual(unchanged, self.empty_set) + self.assertSetEqual(modified, self.empty_set) + self.assertSetEqual(added, + {'five.tgz', 'foo/bar/six.tgz', 'foofoo/seven.txt'}) + self.assertSetEqual(deleted, + {'bar/bat/four.tgz', 'foo/two.tgz', 'one.tgz', 'three.txt'}) def test_fully_modified_filesystem_snapshot(self): @@ -58,9 +112,14 @@ def test_fully_modified_filesystem_snapshot(self): 'bar/bat/four.tgz': '6677889900123456' } - snapshot = before_after_filesystem_snapshot.snapshot(self.before, after) - self.assertEqual(snapshot, ([], ['bar/bat/four.tgz', 'foo/two.tgz', - 'one.tgz', 'three.txt'], [], [])) + unchanged, modified, added, deleted = \ + create_layout.changes_between_snapshots(self.before, after) + + self.assertSetEqual(unchanged, self.empty_set) + self.assertSetEqual(modified, + {'bar/bat/four.tgz', 'foo/two.tgz', 'one.tgz', 'three.txt'}) + self.assertSetEqual(added, self.empty_set) + self.assertSetEqual(deleted, self.empty_set) def test_partially_modified_filesystem_snapshot(self): @@ -73,41 +132,70 @@ def test_partially_modified_filesystem_snapshot(self): 'baz/six.tgz': '6666666666666666' } - snapshot = before_after_filesystem_snapshot.snapshot(self.before, after) - self.assertEqual(snapshot, (['one.tgz'], ['bar/bat/four.tgz', - 'foo/two.tgz'], ['baz/six.tgz', 'five.txt'], ['three.txt'])) - - def test_generate_artifact_rules(self): - - after = { - 'five.txt': '5555555555555555', - 'one.tgz': '1234567890abcdef', - 'foo/two.tgz': 'ffffffffffffffff', - 'bar/bat/four.tgz': '6677889900112233', - 'baz/six.tgz': '6666666666666666' - } - - artifact_rules = { - 'expected_materials': [ - ['ALLOW', 'bar/bat/four.tgz'], - ['ALLOW', 'one.tgz'], - ['ALLOW', 'foo/two.tgz'], - ['DELETE', 'three.txt'], - ['DISALLOW', '*'] - ], - 'expected_products': [ - ['ALLOW', 'bar/bat/four.tgz'], - ['ALLOW', 'one.tgz'], - ['MODIFY', 'foo/two.tgz'], - ['CREATE', 'baz/six.tgz'], - ['CREATE', 'five.txt'], - ['DISALLOW', '*'] - ] - } - - snapshot = before_after_filesystem_snapshot.snapshot(self.before, after) - rules = before_after_filesystem_snapshot.generate_artifact_rules(snapshot) - self.assertDictEqual(artifact_rules, rules) + unchanged, modified, added, deleted = \ + create_layout.changes_between_snapshots(self.before, after) + + self.assertSetEqual(unchanged, {'one.tgz'}) + self.assertSetEqual(modified, {'bar/bat/four.tgz', 'foo/two.tgz'}) + self.assertSetEqual(added, {'baz/six.tgz', 'five.txt'}) + self.assertSetEqual(deleted, {'three.txt'}) + + + def test_create_material_rules_of_initial_step(self): + # Zero index means that the current step is the initial step, + # so we need to ALLOW all the existing files instead of matching. + second_link = in_toto.models.link.Link.read(self.second_step_link_str) + links = [second_link] + + expected_materials = [ + ['ALLOW', 'bar/bat/four.tgz'], + ['ALLOW', 'foo/two.tgz'], + ['ALLOW', 'one.tgz'], + ['DELETE', 'three.txt'], + ['DISALLOW', '*'] + ] + + self.assertEqual(expected_materials, + create_layout.create_material_rules(None, second_link)) + + def test_create_material_rules_of_not_initial_step(self): + # Nonzero index means that the current step is not the initial step, + # so we need to MATCH materials with products of the previous step. + first_link = in_toto.models.link.Link.read(self.first_step_link_str) + second_link = in_toto.models.link.Link.read(self.second_step_link_str) + links = [first_link, second_link] + + # WARNING: if we have a MATCH rule and a DELETE rule on the same artifact, + # the first MATCH rule will moot the subsequent DELETE rule. + expected_materials = [ + ['MATCH', 'bar/bat/four.tgz', 'WITH', 'PRODUCTS', 'FROM', 'first_step'], + ['MATCH', 'foo/two.tgz', 'WITH', 'PRODUCTS', 'FROM', 'first_step'], + ['MATCH', 'one.tgz', 'WITH', 'PRODUCTS', 'FROM', 'first_step'], + ['MATCH', 'three.txt', 'WITH', 'PRODUCTS', 'FROM', 'first_step'], + ['DELETE', 'three.txt'], + ['DISALLOW', '*'] + ] + + self.assertEqual(expected_materials, + create_layout.create_material_rules(first_link, second_link)) + + def test_create_product_rules(self): + # Given the changes of second step's materials and product, + # generate the product rules. + second_link = in_toto.models.link.Link.read(self.second_step_link_str) + expected_products = [ + ['ALLOW', 'bar/bat/four.tgz'], + ['ALLOW', 'one.tgz'], + ['MODIFY', 'foo/two.tgz'], + ['CREATE', 'baz/six.tgz'], + ['CREATE', 'five.txt'], + ['DISALLOW', '*'] + ] + + self.assertTrue(expected_products, + create_layout.create_product_rules(second_link)) + + # TODO: missing test for create_layout_from_ordered_links if __name__ == '__main__': unittest.main()