summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Maat <tristan.maat@codethink.co.uk>2019-12-17 14:00:24 +0000
committerJürg Billeter <j@bitron.ch>2020-02-05 17:14:28 +0000
commit7a0d01289daf1d8e6c868a8f22736b8829a4c625 (patch)
tree450a8f99846dc9fb690322ca847d3ea4b13bf53d
parente618edf5a7df9b265f3bd62fbd801c412f73812d (diff)
downloadbuildstream-7a0d01289daf1d8e6c868a8f22736b8829a4c625.tar.gz
tests/internals/storage.py: Add merge tests
-rw-r--r--tests/internals/storage.py198
-rw-r--r--tests/internals/storage/empty/.gitkeep0
-rw-r--r--tests/internals/storage/merge-add/added0
-rw-r--r--tests/internals/storage/merge-add/root-file0
-rw-r--r--tests/internals/storage/merge-add/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-base/root-file0
-rw-r--r--tests/internals/storage/merge-base/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-buildtree/root-file0
-rw-r--r--tests/internals/storage/merge-buildtree/root-file.o0
-rw-r--r--tests/internals/storage/merge-buildtree/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-buildtree/subdirectory/subdir-file.o0
l---------tests/internals/storage/merge-link-change/link1
-rw-r--r--tests/internals/storage/merge-link-change/root-file0
l---------tests/internals/storage/merge-link-change/subdirectory/link1
-rw-r--r--tests/internals/storage/merge-link-change/subdirectory/subdir-file0
l---------tests/internals/storage/merge-link/link1
-rw-r--r--tests/internals/storage/merge-link/root-file0
-rw-r--r--tests/internals/storage/merge-link/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-directory/root-file0
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-directory/root-file.o0
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file.o/test0
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-file/root-file0
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-file/root-file.o1
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file.o0
-rw-r--r--tests/internals/storage/merge-override-subdirectory/root-file0
-rw-r--r--tests/internals/storage/merge-override-subdirectory/root-file.o0
-rw-r--r--tests/internals/storage/merge-override-subdirectory/subdirectory0
-rw-r--r--tests/internals/storage/merge-override-with-directory/root-file0
-rw-r--r--tests/internals/storage/merge-override-with-directory/root-file.o/test0
-rw-r--r--tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file.o0
-rw-r--r--tests/internals/storage/merge-override-with-file/root-file0
-rw-r--r--tests/internals/storage/merge-override-with-file/root-file.o1
-rw-r--r--tests/internals/storage/merge-override-with-file/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-override-with-file/subdirectory/subdir-file.o0
-rw-r--r--tests/internals/storage/merge-override-with-new-subdirectory/root-file0
-rw-r--r--tests/internals/storage/merge-override-with-new-subdirectory/subdirectory0
-rwxr-xr-xtests/internals/storage/merge-properties/root-file0
-rw-r--r--tests/internals/storage/merge-properties/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-remove/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-replace/root-file1
-rw-r--r--tests/internals/storage/merge-replace/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-subdirectory-add/root-file0
-rw-r--r--tests/internals/storage/merge-subdirectory-add/subdirectory/added0
-rw-r--r--tests/internals/storage/merge-subdirectory-add/subdirectory/subdir-file1
-rw-r--r--tests/internals/storage/merge-subdirectory-link/root-file0
l---------tests/internals/storage/merge-subdirectory-link/subdirectory/link1
-rw-r--r--tests/internals/storage/merge-subdirectory-link/subdirectory/subdir-file0
-rw-r--r--tests/internals/storage/merge-subdirectory-remove/root-file0
-rw-r--r--tests/internals/storage/merge-subdirectory-remove/subdirectory/.gitkeep0
-rw-r--r--tests/internals/storage/merge-subdirectory-replace/root-file0
-rw-r--r--tests/internals/storage/merge-subdirectory-replace/subdirectory/subdir-file1
54 files changed, 207 insertions, 0 deletions
diff --git a/tests/internals/storage.py b/tests/internals/storage.py
index 8aa7f4a17..89a198d98 100644
--- a/tests/internals/storage.py
+++ b/tests/internals/storage.py
@@ -1,11 +1,17 @@
from contextlib import contextmanager
import os
+import pprint
+import shutil
+import glob
+from pathlib import Path
+from typing import List, Optional
import pytest
from buildstream._cas import CASCache
from buildstream.storage._casbaseddirectory import CasBasedDirectory
from buildstream.storage._filebaseddirectory import FileBasedDirectory
+from buildstream.storage.directory import _FileType
DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "storage")
@@ -51,3 +57,195 @@ def test_modified_file_list(tmpdir, datafiles, backend):
assert "bin/bash" in c.list_relative_paths()
assert "bin/bash" in c.list_modified_paths()
assert "bin/hello" not in c.list_modified_paths()
+
+
+@pytest.mark.parametrize(
+ "directories", [("merge-base", "merge-base"), ("empty", "empty"),],
+)
+@pytest.mark.datafiles(DATA_DIR)
+def test_merge_same_casdirs(tmpdir, datafiles, directories):
+ buildtree = os.path.join(str(datafiles), "merge-buildtree")
+ before = os.path.join(str(datafiles), directories[0])
+ after = os.path.join(str(datafiles), directories[1])
+
+ # Bring the directories into a canonical state
+ for directory in (buildtree, before, after):
+ clear_gitkeeps(directory)
+ utime_recursively(directory, (100, 100))
+
+ with setup_backend(CasBasedDirectory, str(tmpdir)) as c, setup_backend(
+ CasBasedDirectory, str(tmpdir)
+ ) as a, setup_backend(CasBasedDirectory, str(tmpdir)) as b:
+ a.import_files(before)
+ b.import_files(after)
+ c.import_files(buildtree)
+
+ assert a._get_digest() == b._get_digest(), "{}\n{}".format(
+ pprint.pformat(list_relative_paths(a)), pprint.pformat(list_relative_paths(b))
+ )
+ old_digest = c._get_digest()
+ c._apply_changes(a, b)
+ # Assert that the build tree stays the same (since there were
+ # no changes between a and b)
+ assert c._get_digest() == old_digest
+
+
+@pytest.mark.parametrize(
+ "directories",
+ [
+ ("merge-base", "merge-replace"),
+ ("merge-base", "merge-remove"),
+ ("merge-base", "merge-add"),
+ ("merge-base", "merge-link"),
+ ("merge-base", "merge-subdirectory-replace"),
+ ("merge-base", "merge-subdirectory-remove"),
+ ("merge-base", "merge-subdirectory-add"),
+ ("merge-base", "merge-subdirectory-link"),
+ ("merge-link", "merge-link-change"),
+ ("merge-subdirectory-link", "merge-link-change"),
+ ("merge-base", "merge-override-with-file"),
+ ("merge-base", "merge-override-with-directory"),
+ ("merge-base", "merge-override-in-subdir-with-file"),
+ ("merge-base", "merge-override-in-subdir-with-directory"),
+ ("merge-base", "merge-override-subdirectory"),
+ ("merge-override-with-new-subdirectory", "merge-subdirectory-add"),
+ ("empty", "merge-subdirectory-add"),
+ ],
+)
+@pytest.mark.datafiles(DATA_DIR)
+def test_merge_casdirs(tmpdir, datafiles, directories):
+ buildtree = os.path.join(str(datafiles), "merge-buildtree")
+ before = os.path.join(str(datafiles), directories[0])
+ after = os.path.join(str(datafiles), directories[1])
+
+ # Bring the directories into a canonical state
+ for directory in (buildtree, before, after):
+ clear_gitkeeps(directory)
+ utime_recursively(directory, (100, 100))
+
+ _test_merge_dirs(before, after, buildtree, str(tmpdir))
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("modification", ["executable", "time"])
+def test_merge_casdir_properties(tmpdir, datafiles, modification):
+ buildtree = os.path.join(str(datafiles), "merge-buildtree")
+ before = os.path.join(str(datafiles), "merge-base")
+ after = os.path.join(str(tmpdir), "merge-modified")
+ shutil.copytree(before, after, symlinks=True)
+
+ # Bring the directories into a canonical state
+ for directory in (buildtree, before, after):
+ clear_gitkeeps(directory)
+ utime_recursively(directory, (100, 100))
+
+ if modification == "executable":
+ os.chmod(os.path.join(after, "root-file"), 0o755)
+ elif modification == "time":
+ os.utime(os.path.join(after, "root-file"), (200, 200))
+
+ _test_merge_dirs(before, after, buildtree, str(tmpdir), properties=["MTime"])
+
+
+def _test_merge_dirs(
+ before: str, after: str, buildtree: str, tmpdir: str, properties: Optional[List[str]] = None
+) -> bool:
+ with setup_backend(CasBasedDirectory, tmpdir) as c, setup_backend(
+ CasBasedDirectory, tmpdir
+ ) as copy, setup_backend(CasBasedDirectory, tmpdir) as a, setup_backend(CasBasedDirectory, tmpdir) as b:
+ a.import_files(before, properties=properties)
+ b.import_files(after, properties=properties)
+ c.import_files(buildtree, properties=properties)
+ copy.import_files(buildtree, properties=properties)
+
+ assert c._get_digest() == copy._get_digest()
+
+ assert a._get_digest() != b._get_digest(), "{}\n{}".format(
+ pprint.pformat(list_relative_paths(a)), pprint.pformat(list_relative_paths(b))
+ )
+ c._apply_changes(a, b)
+ # The files in c now should contain changes from b, so these
+ # shouldn't be the same anymore
+ assert c._get_digest() != copy._get_digest(), "{}\n{}".format(
+ pprint.pformat(list_relative_paths(c)), pprint.pformat(list_relative_paths(copy))
+ )
+
+ # This is the set of paths that should have been removed
+ removed = [path for path in list_paths_with_properties(a) if path not in list_paths_with_properties(b)]
+
+ # This is the set of paths that were added in the new set
+ added = [path for path in list_paths_with_properties(b) if path not in list_paths_with_properties(a)]
+
+ # We need to strip some types of values, since they're more
+ # than our little list comparisons can handle
+ def make_info(entry, list_props=None):
+ ret = {k: v for k, v in vars(entry).items() if k != "buildstream_object"}
+ if entry.type == _FileType.REGULAR_FILE:
+ # Only file digests make sense here (directory digests
+ # need to be re-calculated taking into account their
+ # contents).
+ ret["digest"] = entry.get_digest()
+ else:
+ ret["digest"] = None
+ return ret
+
+ combined = [path for path in list_paths_with_properties(copy) if path not in removed]
+ # Add the new list, overriding any old entries that already
+ # exist.
+ for path in added:
+ if path.name in (o.name for o in combined):
+ # Any paths that already exist must be removed
+ # first
+ combined = [o for o in combined if o.name != path.name]
+ combined.append(path)
+ else:
+ combined.append(path)
+
+ # If any paths don't have a parent directory, we need to
+ # remove them now
+ for e in combined:
+ path = Path(e.name)
+ for parent in list(path.parents)[:-1]:
+ if not str(parent) in (e.name for e in combined if e.type == _FileType.DIRECTORY):
+ # If not all parent directories are existing
+ # directories
+ combined = [e for e in combined if e.name != str(path)]
+
+ assert sorted(list(make_info(e) for e in combined), key=lambda x: x["name"]) == sorted(
+ list(make_info(e) for e in list_paths_with_properties(c)), key=lambda x: x["name"]
+ )
+
+
+# This is purely for error output; lists relative paths and
+# their digests so differences are human-grokkable
+def list_relative_paths(directory):
+ def entry_output(entry):
+ if entry.type == _FileType.DIRECTORY:
+ return list_relative_paths(entry.get_directory(directory))
+ elif entry.type == _FileType.SYMLINK:
+ return "-> " + entry.target
+ else:
+ return entry.get_digest().hash
+
+ return {name: entry_output(entry) for name, entry in directory.index.items()}
+
+
+def list_paths_with_properties(directory, prefix=""):
+ for leaf in directory.index.keys():
+ entry = directory.index[leaf].clone()
+ if directory.filename:
+ entry.name = directory.filename + os.path.sep + entry.name
+ yield entry
+ if entry.type == _FileType.DIRECTORY:
+ subdir = entry.get_directory(directory)
+ yield from list_paths_with_properties(subdir)
+
+
+def utime_recursively(directory, time):
+ for f in glob.glob(os.path.join(directory, "**"), recursive=True):
+ os.utime(f, time)
+
+
+def clear_gitkeeps(directory):
+ for f in glob.glob(os.path.join(directory, "**", ".gitkeep"), recursive=True):
+ os.remove(f)
diff --git a/tests/internals/storage/empty/.gitkeep b/tests/internals/storage/empty/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/empty/.gitkeep
diff --git a/tests/internals/storage/merge-add/added b/tests/internals/storage/merge-add/added
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-add/added
diff --git a/tests/internals/storage/merge-add/root-file b/tests/internals/storage/merge-add/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-add/root-file
diff --git a/tests/internals/storage/merge-add/subdirectory/subdir-file b/tests/internals/storage/merge-add/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-add/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-base/root-file b/tests/internals/storage/merge-base/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-base/root-file
diff --git a/tests/internals/storage/merge-base/subdirectory/subdir-file b/tests/internals/storage/merge-base/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-base/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-buildtree/root-file b/tests/internals/storage/merge-buildtree/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-buildtree/root-file
diff --git a/tests/internals/storage/merge-buildtree/root-file.o b/tests/internals/storage/merge-buildtree/root-file.o
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-buildtree/root-file.o
diff --git a/tests/internals/storage/merge-buildtree/subdirectory/subdir-file b/tests/internals/storage/merge-buildtree/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-buildtree/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-buildtree/subdirectory/subdir-file.o b/tests/internals/storage/merge-buildtree/subdirectory/subdir-file.o
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-buildtree/subdirectory/subdir-file.o
diff --git a/tests/internals/storage/merge-link-change/link b/tests/internals/storage/merge-link-change/link
new file mode 120000
index 000000000..9da48df08
--- /dev/null
+++ b/tests/internals/storage/merge-link-change/link
@@ -0,0 +1 @@
+subdirectory/subdir-file \ No newline at end of file
diff --git a/tests/internals/storage/merge-link-change/root-file b/tests/internals/storage/merge-link-change/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-link-change/root-file
diff --git a/tests/internals/storage/merge-link-change/subdirectory/link b/tests/internals/storage/merge-link-change/subdirectory/link
new file mode 120000
index 000000000..04db3d236
--- /dev/null
+++ b/tests/internals/storage/merge-link-change/subdirectory/link
@@ -0,0 +1 @@
+../root-file \ No newline at end of file
diff --git a/tests/internals/storage/merge-link-change/subdirectory/subdir-file b/tests/internals/storage/merge-link-change/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-link-change/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-link/link b/tests/internals/storage/merge-link/link
new file mode 120000
index 000000000..c4e282ef7
--- /dev/null
+++ b/tests/internals/storage/merge-link/link
@@ -0,0 +1 @@
+root-file \ No newline at end of file
diff --git a/tests/internals/storage/merge-link/root-file b/tests/internals/storage/merge-link/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-link/root-file
diff --git a/tests/internals/storage/merge-link/subdirectory/subdir-file b/tests/internals/storage/merge-link/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-link/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-override-in-subdir-with-directory/root-file b/tests/internals/storage/merge-override-in-subdir-with-directory/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-directory/root-file
diff --git a/tests/internals/storage/merge-override-in-subdir-with-directory/root-file.o b/tests/internals/storage/merge-override-in-subdir-with-directory/root-file.o
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-directory/root-file.o
diff --git a/tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file b/tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file.o/test b/tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file.o/test
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-directory/subdirectory/subdir-file.o/test
diff --git a/tests/internals/storage/merge-override-in-subdir-with-file/root-file b/tests/internals/storage/merge-override-in-subdir-with-file/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-file/root-file
diff --git a/tests/internals/storage/merge-override-in-subdir-with-file/root-file.o b/tests/internals/storage/merge-override-in-subdir-with-file/root-file.o
new file mode 100644
index 000000000..9daeafb98
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-file/root-file.o
@@ -0,0 +1 @@
+test
diff --git a/tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file b/tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file.o b/tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file.o
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-in-subdir-with-file/subdirectory/subdir-file.o
diff --git a/tests/internals/storage/merge-override-subdirectory/root-file b/tests/internals/storage/merge-override-subdirectory/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-subdirectory/root-file
diff --git a/tests/internals/storage/merge-override-subdirectory/root-file.o b/tests/internals/storage/merge-override-subdirectory/root-file.o
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-subdirectory/root-file.o
diff --git a/tests/internals/storage/merge-override-subdirectory/subdirectory b/tests/internals/storage/merge-override-subdirectory/subdirectory
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-subdirectory/subdirectory
diff --git a/tests/internals/storage/merge-override-with-directory/root-file b/tests/internals/storage/merge-override-with-directory/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-directory/root-file
diff --git a/tests/internals/storage/merge-override-with-directory/root-file.o/test b/tests/internals/storage/merge-override-with-directory/root-file.o/test
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-directory/root-file.o/test
diff --git a/tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file b/tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file.o b/tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file.o
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-directory/subdirectory/subdir-file.o
diff --git a/tests/internals/storage/merge-override-with-file/root-file b/tests/internals/storage/merge-override-with-file/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-file/root-file
diff --git a/tests/internals/storage/merge-override-with-file/root-file.o b/tests/internals/storage/merge-override-with-file/root-file.o
new file mode 100644
index 000000000..9daeafb98
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-file/root-file.o
@@ -0,0 +1 @@
+test
diff --git a/tests/internals/storage/merge-override-with-file/subdirectory/subdir-file b/tests/internals/storage/merge-override-with-file/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-file/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-override-with-file/subdirectory/subdir-file.o b/tests/internals/storage/merge-override-with-file/subdirectory/subdir-file.o
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-file/subdirectory/subdir-file.o
diff --git a/tests/internals/storage/merge-override-with-new-subdirectory/root-file b/tests/internals/storage/merge-override-with-new-subdirectory/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-new-subdirectory/root-file
diff --git a/tests/internals/storage/merge-override-with-new-subdirectory/subdirectory b/tests/internals/storage/merge-override-with-new-subdirectory/subdirectory
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-override-with-new-subdirectory/subdirectory
diff --git a/tests/internals/storage/merge-properties/root-file b/tests/internals/storage/merge-properties/root-file
new file mode 100755
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-properties/root-file
diff --git a/tests/internals/storage/merge-properties/subdirectory/subdir-file b/tests/internals/storage/merge-properties/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-properties/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-remove/subdirectory/subdir-file b/tests/internals/storage/merge-remove/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-remove/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-replace/root-file b/tests/internals/storage/merge-replace/root-file
new file mode 100644
index 000000000..617807982
--- /dev/null
+++ b/tests/internals/storage/merge-replace/root-file
@@ -0,0 +1 @@
+b
diff --git a/tests/internals/storage/merge-replace/subdirectory/subdir-file b/tests/internals/storage/merge-replace/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-replace/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-subdirectory-add/root-file b/tests/internals/storage/merge-subdirectory-add/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-add/root-file
diff --git a/tests/internals/storage/merge-subdirectory-add/subdirectory/added b/tests/internals/storage/merge-subdirectory-add/subdirectory/added
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-add/subdirectory/added
diff --git a/tests/internals/storage/merge-subdirectory-add/subdirectory/subdir-file b/tests/internals/storage/merge-subdirectory-add/subdirectory/subdir-file
new file mode 100644
index 000000000..617807982
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-add/subdirectory/subdir-file
@@ -0,0 +1 @@
+b
diff --git a/tests/internals/storage/merge-subdirectory-link/root-file b/tests/internals/storage/merge-subdirectory-link/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-link/root-file
diff --git a/tests/internals/storage/merge-subdirectory-link/subdirectory/link b/tests/internals/storage/merge-subdirectory-link/subdirectory/link
new file mode 120000
index 000000000..787413cef
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-link/subdirectory/link
@@ -0,0 +1 @@
+subdir-file \ No newline at end of file
diff --git a/tests/internals/storage/merge-subdirectory-link/subdirectory/subdir-file b/tests/internals/storage/merge-subdirectory-link/subdirectory/subdir-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-link/subdirectory/subdir-file
diff --git a/tests/internals/storage/merge-subdirectory-remove/root-file b/tests/internals/storage/merge-subdirectory-remove/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-remove/root-file
diff --git a/tests/internals/storage/merge-subdirectory-remove/subdirectory/.gitkeep b/tests/internals/storage/merge-subdirectory-remove/subdirectory/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-remove/subdirectory/.gitkeep
diff --git a/tests/internals/storage/merge-subdirectory-replace/root-file b/tests/internals/storage/merge-subdirectory-replace/root-file
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-replace/root-file
diff --git a/tests/internals/storage/merge-subdirectory-replace/subdirectory/subdir-file b/tests/internals/storage/merge-subdirectory-replace/subdirectory/subdir-file
new file mode 100644
index 000000000..617807982
--- /dev/null
+++ b/tests/internals/storage/merge-subdirectory-replace/subdirectory/subdir-file
@@ -0,0 +1 @@
+b