示例#1
0
 def test_item_predecessors(self):
     dg = DependencyGraph(PATH_TO_ITEM.values(), layer_target='t-34')
     self.assertEqual(
         _fs_root_phases(FilesystemRootItem(from_target='t-34')),
         list(dg.ordered_phases()),
     )
     with TempSubvolumes(sys.argv[0]) as temp_subvolumes:
         subvol = temp_subvolumes.create('subvol')
         phases_provide = PhasesProvideItem(from_target='t', subvol=subvol)
         ns = dg._prep_item_predecessors(phases_provide)
     path_to_item = {'/': phases_provide, **PATH_TO_ITEM}
     self.assertEqual(
         ns.item_to_predecessors, {
             path_to_item[k]: {path_to_item[v]
                               for v in vs}
             for k, vs in {
                 '/a/b/c': {'/'},
                 '/a/d/e': {'/a/b/c'},
                 '/a/b/c/F': {'/a/b/c'},
                 '/a/d/e/G': {'/a/d/e'},
             }.items()
         })
     self.assertEqual(
         ns.predecessor_to_items, {
             path_to_item[k]: {path_to_item[v]
                               for v in vs}
             for k, vs in {
                 '/': {'/a/b/c'},
                 '/a/b/c': {'/a/d/e', '/a/b/c/F'},
                 '/a/b/c/F': set(),
                 '/a/d/e': {'/a/d/e/G'},
                 '/a/d/e/G': set(),
             }.items()
         })
     self.assertEqual(ns.items_without_predecessors, {path_to_item['/']})
示例#2
0
 def __init__(
     self,
     iter_items: {'Iterator of ImageItems'},
     layer_target: str,
 ):
     # Without deduping, dependency diamonds would cause a lot of
     # redundant work below.  `_prep_item_predecessors` mutates this.
     self.items = set()
     # While deduplicating `ImageItem`s, let's also split out the phases.
     self.order_to_phase_items = {}
     for item in iter_items:
         if item.phase_order() is None:
             self.items.add(item)
         else:
             self.order_to_phase_items.setdefault(
                 item.phase_order(),
                 [],
             ).append(item)
     # If there is no MAKE_SUBVOL item, create an empty subvolume.
     make_subvol_items = self.order_to_phase_items.setdefault(
         PhaseOrder.MAKE_SUBVOL,
         [FilesystemRootItem(from_target=layer_target)],
     )
     assert len(make_subvol_items) == 1, make_subvol_items
     # If we have a foreign layer, it must be the only item, besides the
     # mandatory `MAKE_SUBVOL` added above.
     foreign = self.order_to_phase_items.get(PhaseOrder.FOREIGN_LAYER)
     if foreign:
         assert len(foreign) == 1, foreign
         assert not self.items, self.items
         assert set(self.order_to_phase_items.keys()) == {
             PhaseOrder.FOREIGN_LAYER,
             PhaseOrder.MAKE_SUBVOL,
         }, self.order_to_phase_items
示例#3
0
 def test_gen_dependency_graph(self):
     dg = DependencyGraph(PATH_TO_ITEM.values(), layer_target='t-72')
     self.assertEqual(
         _fs_root_phases(FilesystemRootItem(from_target='t-72')),
         list(dg.ordered_phases()),
     )
     with TempSubvolumes(sys.argv[0]) as temp_subvolumes:
         subvol = temp_subvolumes.create('subvol')
         self.assertIn(
             tuple(
                 dg.gen_dependency_order_items(
                     PhasesProvideItem(from_target='t', subvol=subvol), )),
             {
                 tuple(PATH_TO_ITEM[p] for p in paths)
                 for paths in [
                     # A few orders are valid, don't make the test fragile.
                     ['/a/b/c', '/a/b/c/F', '/a/d/e', '/a/d/e/G'],
                     ['/a/b/c', '/a/d/e', '/a/b/c/F', '/a/d/e/G'],
                     ['/a/b/c', '/a/d/e', '/a/d/e/G', '/a/b/c/F'],
                 ]
             },
         )
示例#4
0
    def test_cycle_detection(self):
        def requires_provides_directory_class(requires_dir, provides_dir):
            @dataclass(init=False, frozen=True)
            class RequiresProvidesDirectory(ImageItem):
                def requires(self):
                    yield require_directory(requires_dir)

                def provides(self):
                    yield ProvidesDirectory(path=provides_dir)

            return RequiresProvidesDirectory

        # `dg_ok`: dependency-sorting will work without a cycle
        first = FilesystemRootItem(from_target='')
        second = requires_provides_directory_class('/', 'a')(from_target='')
        third = MakeDirsItem(from_target='', into_dir='a', path_to_make='b/c')
        dg_ok = DependencyGraph([second, first, third], layer_target='t')
        self.assertEqual(_fs_root_phases(first), list(dg_ok.ordered_phases()))

        # `dg_bad`: changes `second` to get a cycle
        dg_bad = DependencyGraph([
            requires_provides_directory_class('a/b', 'a')(from_target=''),
            first,
            third,
        ],
                                 layer_target='t')
        self.assertEqual(_fs_root_phases(first), list(dg_bad.ordered_phases()))

        with TempSubvolumes(sys.argv[0]) as temp_subvolumes:
            subvol = temp_subvolumes.create('subvol')
            provides_root = PhasesProvideItem(from_target='t', subvol=subvol)
            self.assertEqual(
                [second, third],
                list(dg_ok.gen_dependency_order_items(provides_root)),
            )
            with self.assertRaisesRegex(AssertionError, '^Cycle in '):
                list(dg_bad.gen_dependency_order_items(provides_root))
示例#5
0
 def __init__(
     self,
     iter_items: {'Iterator of ImageItems'},
     layer_target: str,
 ):
     # Without deduping, dependency diamonds would cause a lot of
     # redundant work below.  `_prep_item_predecessors` mutates this.
     self.items = set()
     # While deduplicating `ImageItem`s, let's also split out the phases.
     self.order_to_phase_items = {}
     for item in iter_items:
         if item.phase_order() is None:
             self.items.add(item)
         else:
             self.order_to_phase_items.setdefault(
                 item.phase_order(),
                 [],
             ).append(item)
     # If there is no MAKE_SUBVOL item, create an empty subvolume.
     make_subvol_items = self.order_to_phase_items.setdefault(
         PhaseOrder.MAKE_SUBVOL,
         [FilesystemRootItem(from_target=layer_target)],
     )
     assert len(make_subvol_items) == 1, make_subvol_items
示例#6
0
    def test_phase_order(self):
        class FakeRemovePaths:
            get_phase_builder = 'kittycat'

            def phase_order(self):
                return PhaseOrder.REMOVE_PATHS

        first = FilesystemRootItem(from_target='')
        second = FakeRemovePaths()
        third = MakeDirsItem(from_target='', into_dir='/', path_to_make='a/b')
        dg = DependencyGraph([second, first, third], layer_target='t')
        self.assertEqual(
            _fs_root_phases(first) + [
                (FakeRemovePaths.get_phase_builder, (second, )),
            ],
            list(dg.ordered_phases()),
        )
        with TempSubvolumes(sys.argv[0]) as temp_subvolumes:
            subvol = temp_subvolumes.create('subvol')
            self.assertEqual([third],
                             list(
                                 dg.gen_dependency_order_items(
                                     PhasesProvideItem(from_target='t',
                                                       subvol=subvol), )))
示例#7
0
# We rely on Buck setting the environment via the `env =` directive.
assert T_HELLO_WORLD_TAR in TARGET_TO_PATH, 'You must use `buck test`'


def mangle(feature_target):
    return feature_target + (
        '_IF_YOU_REFER_TO_THIS_RULE_YOUR_DEPENDENCIES_WILL_BE_BROKEN_'
        'SO_DO_NOT_DO_THIS_EVER_PLEASE_KTHXBAI')


# This should be a faithful transcription of the `image_feature`
# specifications in `test/TARGETS`.  The IDs currently have no semantics,
# existing only to give names to specific items.
ID_TO_ITEM = {
    '/':
    FilesystemRootItem(from_target=None),

    # From `feature_dirs`:
    'foo/bar':
    MakeDirsItem(from_target=T_DIRS, into_dir='/', path_to_make='/foo/bar'),
    'foo/bar/baz':
    MakeDirsItem(from_target=T_DIRS, into_dir='/foo/bar', path_to_make='baz'),

    # From `feature_bad_dir`:
    'foo/borf/beep':
    MakeDirsItem(
        from_target=T_BAD_DIR,
        into_dir='/foo',
        path_to_make='borf/beep',
        user_group='uuu:ggg',
        mode='mmm',