summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/format/junctions.py54
-rw-r--r--tests/format/junctions/config-target/elements/invalid-source-target.bst8
-rw-r--r--tests/format/junctions/config-target/elements/nested-junction-target.bst4
-rw-r--r--tests/format/junctions/config-target/elements/target.bst4
-rw-r--r--tests/format/link.py145
-rw-r--r--tests/format/link/conditional-junctions/elements/subproject.bst (renamed from tests/format/junctions/config-target/elements/subproject.bst)0
-rw-r--r--tests/format/link/conditional-junctions/elements/subsubproject-link.bst8
-rw-r--r--tests/format/link/conditional-junctions/elements/target.bst4
-rw-r--r--tests/format/link/conditional-junctions/project.conf13
-rw-r--r--tests/format/link/conditional-junctions/subproject/elements/hello.bst (renamed from tests/format/junctions/config-target/subproject/subsubproject/elements/hello.bst)0
-rw-r--r--tests/format/link/conditional-junctions/subproject/elements/subsubproject-goodbye-junction.bst5
-rw-r--r--tests/format/link/conditional-junctions/subproject/elements/subsubproject-hello-junction.bst5
-rw-r--r--tests/format/link/conditional-junctions/subproject/project.conf (renamed from tests/format/junctions/config-target/subproject/project.conf)0
-rw-r--r--tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/elements/target.bst5
-rw-r--r--tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/files/goodbye.txt (renamed from tests/format/junctions/config-target/subproject/subsubproject/files/hello.txt)0
-rw-r--r--tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/project.conf (renamed from tests/format/junctions/config-target/subproject/subsubproject/project.conf)0
-rw-r--r--tests/format/link/conditional-junctions/subproject/subsubproject-hello/elements/target.bst5
-rw-r--r--tests/format/link/conditional-junctions/subproject/subsubproject-hello/files/hello.txt1
-rw-r--r--tests/format/link/conditional-junctions/subproject/subsubproject-hello/project.conf (renamed from tests/format/junctions/config-target/project.conf)2
-rw-r--r--tests/format/link/conditional/elements/goodbye.bst5
-rw-r--r--tests/format/link/conditional/elements/hello.bst5
-rw-r--r--tests/format/link/conditional/elements/target-link.bst8
-rw-r--r--tests/format/link/conditional/elements/target.bst4
-rw-r--r--tests/format/link/conditional/files/goodbye.txt1
-rw-r--r--tests/format/link/conditional/files/hello.txt1
-rw-r--r--tests/format/link/conditional/project.conf13
-rw-r--r--tests/format/link/invalid/elements/base-file.bst5
-rw-r--r--tests/format/link/invalid/elements/link-with-dependencies.bst7
-rw-r--r--tests/format/link/invalid/elements/link-with-sources.bst8
-rw-r--r--tests/format/link/invalid/elements/target-link-with-sources.bst4
-rw-r--r--tests/format/link/invalid/project.conf4
-rw-r--r--tests/format/link/notfound/elements/depends-on-link-target.bst4
-rw-r--r--tests/format/link/notfound/elements/link-target.bst4
-rw-r--r--tests/format/link/notfound/elements/linked-local-junction-target.bst4
-rw-r--r--tests/format/link/notfound/elements/linked-local-junction.bst4
-rw-r--r--tests/format/link/notfound/elements/linked-nested-junction-target.bst4
-rw-r--r--tests/format/link/notfound/elements/linked-nested-junction.bst4
-rw-r--r--tests/format/link/notfound/elements/subproject-link-notfound.bst4
-rw-r--r--tests/format/link/notfound/elements/subproject-link.bst (renamed from tests/format/junctions/config-target/elements/no-junction.bst)2
-rw-r--r--tests/format/link/notfound/elements/subproject.bst5
-rw-r--r--tests/format/link/notfound/elements/subsubproject-link-notfound.bst4
-rw-r--r--tests/format/link/notfound/elements/subsubproject-link.bst (renamed from tests/format/junctions/config-target/elements/subsubproject.bst)2
-rw-r--r--tests/format/link/notfound/project.conf4
-rw-r--r--tests/format/link/notfound/subproject/elements/subsubproject-junction.bst (renamed from tests/format/junctions/config-target/subproject/elements/subsubproject-junction.bst)0
-rw-r--r--tests/format/link/notfound/subproject/project.conf4
-rw-r--r--tests/format/link/notfound/subproject/subsubproject/project.conf2
-rw-r--r--tests/format/link/simple-junctions/elements/subproject-link.bst4
-rw-r--r--tests/format/link/simple-junctions/elements/subproject.bst5
-rw-r--r--tests/format/link/simple-junctions/elements/subsubproject-link.bst4
-rw-r--r--tests/format/link/simple-junctions/elements/target-local.bst4
-rw-r--r--tests/format/link/simple-junctions/elements/target-nested.bst4
-rw-r--r--tests/format/link/simple-junctions/project.conf4
-rw-r--r--tests/format/link/simple-junctions/subproject/elements/hello.bst5
-rw-r--r--tests/format/link/simple-junctions/subproject/elements/subsubproject-junction.bst5
-rw-r--r--tests/format/link/simple-junctions/subproject/files/hello.txt1
-rw-r--r--tests/format/link/simple-junctions/subproject/project.conf4
-rw-r--r--tests/format/link/simple-junctions/subproject/subsubproject/elements/hello.bst5
-rw-r--r--tests/format/link/simple-junctions/subproject/subsubproject/files/hello.txt1
-rw-r--r--tests/format/link/simple-junctions/subproject/subsubproject/project.conf4
-rw-r--r--tests/format/link/simple/elements/hello-link.bst4
-rw-r--r--tests/format/link/simple/elements/hello.bst5
-rw-r--r--tests/format/link/simple/elements/target.bst4
-rw-r--r--tests/format/link/simple/files/hello.txt1
-rw-r--r--tests/format/link/simple/project.conf4
64 files changed, 374 insertions, 73 deletions
diff --git a/tests/format/junctions.py b/tests/format/junctions.py
index 70572ee3e..f097e0b8b 100644
--- a/tests/format/junctions.py
+++ b/tests/format/junctions.py
@@ -411,60 +411,6 @@ def test_build_git_cross_junction_names(cli, tmpdir, datafiles):
@pytest.mark.datafiles(DATA_DIR)
-def test_config_target(cli, tmpdir, datafiles):
- project = os.path.join(str(datafiles), "config-target")
- checkoutdir = os.path.join(str(tmpdir), "checkout")
-
- # Build, checkout
- result = cli.run(project=project, args=["build", "target.bst"])
- result.assert_success()
- result = cli.run(project=project, args=["artifact", "checkout", "target.bst", "--directory", checkoutdir])
- result.assert_success()
-
- # Check that the checkout contains the expected files from sub-sub-project
- assert os.path.exists(os.path.join(checkoutdir, "hello.txt"))
-
-
-@pytest.mark.datafiles(DATA_DIR)
-def test_invalid_sources_and_target(cli, tmpdir, datafiles):
- project = os.path.join(str(datafiles), "config-target")
-
- result = cli.run(project=project, args=["show", "invalid-source-target.bst"])
- result.assert_main_error(ErrorDomain.ELEMENT, None)
-
- assert "junction elements cannot define both 'sources' and 'target' config option" in result.stderr
-
-
-@pytest.mark.datafiles(DATA_DIR)
-def test_invalid_target_name(cli, tmpdir, datafiles):
- project = os.path.join(str(datafiles), "config-target")
-
- # Rename our junction element to the same name as its target
- old_path = os.path.join(project, "elements/subsubproject.bst")
- new_path = os.path.join(project, "elements/subsubproject-junction.bst")
- os.rename(old_path, new_path)
-
- # This should fail now
- result = cli.run(project=project, args=["show", "subsubproject-junction.bst"])
- result.assert_main_error(ErrorDomain.ELEMENT, None)
-
- assert "junction elements cannot target an element with the same name" in result.stderr
-
-
-# We cannot exhaustively test all possible ways in which this can go wrong, so
-# test a couple of common ways in which we expect this to go wrong.
-@pytest.mark.parametrize("target", ["no-junction.bst", "nested-junction-target.bst"])
-@pytest.mark.datafiles(DATA_DIR)
-def test_invalid_target_format(cli, tmpdir, datafiles, target):
- project = os.path.join(str(datafiles), "config-target")
-
- result = cli.run(project=project, args=["show", target])
- result.assert_main_error(ErrorDomain.ELEMENT, None)
-
- assert "'target' option must be in format '{junction-name}:{element-name}'" in result.stderr
-
-
-@pytest.mark.datafiles(DATA_DIR)
def test_junction_show(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "foo")
copy_subprojects(project, datafiles, ["base"])
diff --git a/tests/format/junctions/config-target/elements/invalid-source-target.bst b/tests/format/junctions/config-target/elements/invalid-source-target.bst
deleted file mode 100644
index b97d09034..000000000
--- a/tests/format/junctions/config-target/elements/invalid-source-target.bst
+++ /dev/null
@@ -1,8 +0,0 @@
-kind: junction
-
-sources:
-- kind: local
- path: subproject/subsubproject
-
-config:
- target: subproject.bst:subsubproject-junction.bst
diff --git a/tests/format/junctions/config-target/elements/nested-junction-target.bst b/tests/format/junctions/config-target/elements/nested-junction-target.bst
deleted file mode 100644
index f76a264e5..000000000
--- a/tests/format/junctions/config-target/elements/nested-junction-target.bst
+++ /dev/null
@@ -1,4 +0,0 @@
-kind: junction
-
-config:
- target: subproject.bst:subsubproject.bst:hello.bst
diff --git a/tests/format/junctions/config-target/elements/target.bst b/tests/format/junctions/config-target/elements/target.bst
deleted file mode 100644
index 50d74489a..000000000
--- a/tests/format/junctions/config-target/elements/target.bst
+++ /dev/null
@@ -1,4 +0,0 @@
-kind: stack
-
-depends:
-- subsubproject.bst:hello.bst
diff --git a/tests/format/link.py b/tests/format/link.py
new file mode 100644
index 000000000..47e19b90c
--- /dev/null
+++ b/tests/format/link.py
@@ -0,0 +1,145 @@
+# Pylint doesn't play well with fixtures and dependency injection from pytest
+# pylint: disable=redefined-outer-name
+
+import os
+
+import pytest
+
+from buildstream.testing import cli # pylint: disable=unused-import
+from buildstream.exceptions import ErrorDomain, LoadErrorReason
+
+
+DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "link",)
+
+#
+# Test links to elements, this tests both specifying the link as
+# the main target, and also as a dependency of the main target.
+#
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("target", ["target.bst", "hello-link.bst"])
+def test_simple_link(cli, tmpdir, datafiles, target):
+ project = os.path.join(str(datafiles), "simple")
+ checkoutdir = os.path.join(str(tmpdir), "checkout")
+
+ # Build, checkout
+ result = cli.run(project=project, args=["build", target])
+ result.assert_success()
+ result = cli.run(project=project, args=["artifact", "checkout", target, "--directory", checkoutdir])
+ result.assert_success()
+
+ # Check that the checkout contains the expected files from sub-sub-project
+ assert os.path.exists(os.path.join(checkoutdir, "hello.txt"))
+
+
+#
+# Test links to elements, this tests both specifying the link as
+# the main target, and also as a dependency of the main target, while
+# also using a conditional statement in the link
+#
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("target", ["target.bst", "target-link.bst"])
+@pytest.mark.parametrize("greeting,expected_file", [("hello", "hello.txt"), ("goodbye", "goodbye.txt")])
+def test_conditional_link(cli, tmpdir, datafiles, target, greeting, expected_file):
+ project = os.path.join(str(datafiles), "conditional")
+ checkoutdir = os.path.join(str(tmpdir), "checkout")
+
+ # Build, checkout
+ result = cli.run(project=project, args=["-o", "greeting", greeting, "build", target])
+ result.assert_success()
+ result = cli.run(
+ project=project, args=["-o", "greeting", greeting, "artifact", "checkout", target, "--directory", checkoutdir]
+ )
+ result.assert_success()
+
+ # Check that the checkout contains the expected files from sub-sub-project
+ assert os.path.exists(os.path.join(checkoutdir, expected_file))
+
+
+#
+# Test links to junctions from local projects and subprojects
+#
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("target", ["target-local.bst", "target-nested.bst"])
+def test_simple_junctions(cli, tmpdir, datafiles, target):
+ project = os.path.join(str(datafiles), "simple-junctions")
+ checkoutdir = os.path.join(str(tmpdir), "checkout")
+
+ # Build, checkout
+ result = cli.run(project=project, args=["build", target])
+ result.assert_success()
+ result = cli.run(project=project, args=["artifact", "checkout", target, "--directory", checkoutdir])
+ result.assert_success()
+
+ # Check that the checkout contains the expected files from sub-sub-project
+ assert os.path.exists(os.path.join(checkoutdir, "hello.txt"))
+
+
+#
+# Test links which resolve junction targets conditionally
+#
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("greeting,expected_file", [("hello", "hello.txt"), ("goodbye", "goodbye.txt")])
+def test_conditional_junctions(cli, tmpdir, datafiles, greeting, expected_file):
+ project = os.path.join(str(datafiles), "conditional-junctions")
+ checkoutdir = os.path.join(str(tmpdir), "checkout")
+
+ # Build, checkout
+ result = cli.run(project=project, args=["-o", "greeting", greeting, "build", "target.bst"])
+ result.assert_success()
+ result = cli.run(
+ project=project,
+ args=["-o", "greeting", greeting, "artifact", "checkout", "target.bst", "--directory", checkoutdir],
+ )
+ result.assert_success()
+
+ # Check that the checkout contains the expected files from sub-sub-project
+ assert os.path.exists(os.path.join(checkoutdir, expected_file))
+
+
+#
+# Tests links which refer to non-existing elements or junctions
+#
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize(
+ "target,provenance",
+ [
+ # Target is a link to a non-existing local element
+ ("link-target.bst", "link-target.bst [line 4 column 10]"),
+ # Target is a stack depending on a link to a non-existing local element
+ ("depends-on-link-target.bst", "link-target.bst [line 4 column 10]",),
+ # Depends on non-existing subproject element, via a local link
+ ("linked-local-junction-target.bst", "linked-local-junction-target.bst [line 4 column 2]",),
+ # Depends on non-existing subsubproject element, via a local link
+ ("linked-nested-junction-target.bst", "linked-nested-junction-target.bst [line 4 column 2]",),
+ # Depends on an element via a link to a non-existing local junction
+ ("linked-local-junction.bst", "subproject-link-notfound.bst [line 4 column 10]",),
+ # Depends on an element via a link to a non-existing subproject junction
+ ("linked-nested-junction.bst", "subsubproject-link-notfound.bst [line 4 column 10]",),
+ ],
+)
+def test_link_not_found(cli, tmpdir, datafiles, target, provenance):
+ project = os.path.join(str(datafiles), "notfound")
+ result = cli.run(project=project, args=["build", target])
+
+ result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.MISSING_FILE)
+ assert provenance in result.stderr
+
+
+#
+# Tests links with invalid configurations
+#
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize(
+ "target,expected_error,expected_reason",
+ [
+ # Test link which declares sources, either directly of via a dependency
+ ("link-with-sources.bst", ErrorDomain.ELEMENT, "element-forbidden-sources"),
+ ("target-link-with-sources.bst", ErrorDomain.ELEMENT, "element-forbidden-sources"),
+ # Test link which declares dependencies, either directly of via a dependency
+ ("link-with-dependencies.bst", ErrorDomain.LOAD, LoadErrorReason.LINK_FORBIDDEN_DEPENDENCIES),
+ ],
+)
+def test_link_invalid_config(cli, tmpdir, datafiles, target, expected_error, expected_reason):
+ project = os.path.join(str(datafiles), "invalid")
+ result = cli.run(project=project, args=["show", target])
+ result.assert_main_error(expected_error, expected_reason)
diff --git a/tests/format/junctions/config-target/elements/subproject.bst b/tests/format/link/conditional-junctions/elements/subproject.bst
index 6664eeec6..6664eeec6 100644
--- a/tests/format/junctions/config-target/elements/subproject.bst
+++ b/tests/format/link/conditional-junctions/elements/subproject.bst
diff --git a/tests/format/link/conditional-junctions/elements/subsubproject-link.bst b/tests/format/link/conditional-junctions/elements/subsubproject-link.bst
new file mode 100644
index 000000000..97e54c0ad
--- /dev/null
+++ b/tests/format/link/conditional-junctions/elements/subsubproject-link.bst
@@ -0,0 +1,8 @@
+kind: link
+
+config:
+ (?):
+ - greeting == "hello":
+ target: subproject.bst:subsubproject-hello-junction.bst
+ - greeting == "goodbye":
+ target: subproject.bst:subsubproject-goodbye-junction.bst
diff --git a/tests/format/link/conditional-junctions/elements/target.bst b/tests/format/link/conditional-junctions/elements/target.bst
new file mode 100644
index 000000000..583061a29
--- /dev/null
+++ b/tests/format/link/conditional-junctions/elements/target.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- subsubproject-link.bst:target.bst
diff --git a/tests/format/link/conditional-junctions/project.conf b/tests/format/link/conditional-junctions/project.conf
new file mode 100644
index 000000000..aae690c84
--- /dev/null
+++ b/tests/format/link/conditional-junctions/project.conf
@@ -0,0 +1,13 @@
+name: conditional
+min-version: 2.0
+
+element-path: elements
+
+options:
+ greeting:
+ type: enum
+ description: The greeting
+ values:
+ - hello
+ - goodbye
+ default: hello
diff --git a/tests/format/junctions/config-target/subproject/subsubproject/elements/hello.bst b/tests/format/link/conditional-junctions/subproject/elements/hello.bst
index a04a856cd..a04a856cd 100644
--- a/tests/format/junctions/config-target/subproject/subsubproject/elements/hello.bst
+++ b/tests/format/link/conditional-junctions/subproject/elements/hello.bst
diff --git a/tests/format/link/conditional-junctions/subproject/elements/subsubproject-goodbye-junction.bst b/tests/format/link/conditional-junctions/subproject/elements/subsubproject-goodbye-junction.bst
new file mode 100644
index 000000000..ab37f9a45
--- /dev/null
+++ b/tests/format/link/conditional-junctions/subproject/elements/subsubproject-goodbye-junction.bst
@@ -0,0 +1,5 @@
+kind: junction
+
+sources:
+- kind: local
+ path: subsubproject-goodbye
diff --git a/tests/format/link/conditional-junctions/subproject/elements/subsubproject-hello-junction.bst b/tests/format/link/conditional-junctions/subproject/elements/subsubproject-hello-junction.bst
new file mode 100644
index 000000000..99db3b997
--- /dev/null
+++ b/tests/format/link/conditional-junctions/subproject/elements/subsubproject-hello-junction.bst
@@ -0,0 +1,5 @@
+kind: junction
+
+sources:
+- kind: local
+ path: subsubproject-hello
diff --git a/tests/format/junctions/config-target/subproject/project.conf b/tests/format/link/conditional-junctions/subproject/project.conf
index 1529ece04..1529ece04 100644
--- a/tests/format/junctions/config-target/subproject/project.conf
+++ b/tests/format/link/conditional-junctions/subproject/project.conf
diff --git a/tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/elements/target.bst b/tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/elements/target.bst
new file mode 100644
index 000000000..f7217c514
--- /dev/null
+++ b/tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/elements/target.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/goodbye.txt
diff --git a/tests/format/junctions/config-target/subproject/subsubproject/files/hello.txt b/tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/files/goodbye.txt
index ce0136250..ce0136250 100644
--- a/tests/format/junctions/config-target/subproject/subsubproject/files/hello.txt
+++ b/tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/files/goodbye.txt
diff --git a/tests/format/junctions/config-target/subproject/subsubproject/project.conf b/tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/project.conf
index 162143c80..162143c80 100644
--- a/tests/format/junctions/config-target/subproject/subsubproject/project.conf
+++ b/tests/format/link/conditional-junctions/subproject/subsubproject-goodbye/project.conf
diff --git a/tests/format/link/conditional-junctions/subproject/subsubproject-hello/elements/target.bst b/tests/format/link/conditional-junctions/subproject/subsubproject-hello/elements/target.bst
new file mode 100644
index 000000000..a04a856cd
--- /dev/null
+++ b/tests/format/link/conditional-junctions/subproject/subsubproject-hello/elements/target.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/hello.txt
diff --git a/tests/format/link/conditional-junctions/subproject/subsubproject-hello/files/hello.txt b/tests/format/link/conditional-junctions/subproject/subsubproject-hello/files/hello.txt
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/tests/format/link/conditional-junctions/subproject/subsubproject-hello/files/hello.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/format/junctions/config-target/project.conf b/tests/format/link/conditional-junctions/subproject/subsubproject-hello/project.conf
index d9e1d7a4f..162143c80 100644
--- a/tests/format/junctions/config-target/project.conf
+++ b/tests/format/link/conditional-junctions/subproject/subsubproject-hello/project.conf
@@ -1,4 +1,4 @@
-name: config-target
+name: subsubproject
min-version: 2.0
element-path: elements
diff --git a/tests/format/link/conditional/elements/goodbye.bst b/tests/format/link/conditional/elements/goodbye.bst
new file mode 100644
index 000000000..f7217c514
--- /dev/null
+++ b/tests/format/link/conditional/elements/goodbye.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/goodbye.txt
diff --git a/tests/format/link/conditional/elements/hello.bst b/tests/format/link/conditional/elements/hello.bst
new file mode 100644
index 000000000..a04a856cd
--- /dev/null
+++ b/tests/format/link/conditional/elements/hello.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/hello.txt
diff --git a/tests/format/link/conditional/elements/target-link.bst b/tests/format/link/conditional/elements/target-link.bst
new file mode 100644
index 000000000..43bffebce
--- /dev/null
+++ b/tests/format/link/conditional/elements/target-link.bst
@@ -0,0 +1,8 @@
+kind: link
+
+config:
+ (?):
+ - greeting == "hello":
+ target: hello.bst
+ - greeting == "goodbye":
+ target: goodbye.bst
diff --git a/tests/format/link/conditional/elements/target.bst b/tests/format/link/conditional/elements/target.bst
new file mode 100644
index 000000000..92ccc16a7
--- /dev/null
+++ b/tests/format/link/conditional/elements/target.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- target-link.bst
diff --git a/tests/format/link/conditional/files/goodbye.txt b/tests/format/link/conditional/files/goodbye.txt
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/tests/format/link/conditional/files/goodbye.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/format/link/conditional/files/hello.txt b/tests/format/link/conditional/files/hello.txt
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/tests/format/link/conditional/files/hello.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/format/link/conditional/project.conf b/tests/format/link/conditional/project.conf
new file mode 100644
index 000000000..aae690c84
--- /dev/null
+++ b/tests/format/link/conditional/project.conf
@@ -0,0 +1,13 @@
+name: conditional
+min-version: 2.0
+
+element-path: elements
+
+options:
+ greeting:
+ type: enum
+ description: The greeting
+ values:
+ - hello
+ - goodbye
+ default: hello
diff --git a/tests/format/link/invalid/elements/base-file.bst b/tests/format/link/invalid/elements/base-file.bst
new file mode 100644
index 000000000..92948a068
--- /dev/null
+++ b/tests/format/link/invalid/elements/base-file.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: .
diff --git a/tests/format/link/invalid/elements/link-with-dependencies.bst b/tests/format/link/invalid/elements/link-with-dependencies.bst
new file mode 100644
index 000000000..f30a00560
--- /dev/null
+++ b/tests/format/link/invalid/elements/link-with-dependencies.bst
@@ -0,0 +1,7 @@
+kind: link
+
+depends:
+- base-file.bst
+
+config:
+ target: base-file.bst
diff --git a/tests/format/link/invalid/elements/link-with-sources.bst b/tests/format/link/invalid/elements/link-with-sources.bst
new file mode 100644
index 000000000..90ef16601
--- /dev/null
+++ b/tests/format/link/invalid/elements/link-with-sources.bst
@@ -0,0 +1,8 @@
+kind: link
+
+sources:
+- kind: local
+ path: .
+
+config:
+ target: base-file.bst
diff --git a/tests/format/link/invalid/elements/target-link-with-sources.bst b/tests/format/link/invalid/elements/target-link-with-sources.bst
new file mode 100644
index 000000000..8fd00433d
--- /dev/null
+++ b/tests/format/link/invalid/elements/target-link-with-sources.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- link-with-sources.bst
diff --git a/tests/format/link/invalid/project.conf b/tests/format/link/invalid/project.conf
new file mode 100644
index 000000000..b4fb73ba9
--- /dev/null
+++ b/tests/format/link/invalid/project.conf
@@ -0,0 +1,4 @@
+name: invalid
+min-version: 2.0
+
+element-path: elements
diff --git a/tests/format/link/notfound/elements/depends-on-link-target.bst b/tests/format/link/notfound/elements/depends-on-link-target.bst
new file mode 100644
index 000000000..1f3c7a61e
--- /dev/null
+++ b/tests/format/link/notfound/elements/depends-on-link-target.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- link-target.bst
diff --git a/tests/format/link/notfound/elements/link-target.bst b/tests/format/link/notfound/elements/link-target.bst
new file mode 100644
index 000000000..7ab8902b0
--- /dev/null
+++ b/tests/format/link/notfound/elements/link-target.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: no-element-found.bst
diff --git a/tests/format/link/notfound/elements/linked-local-junction-target.bst b/tests/format/link/notfound/elements/linked-local-junction-target.bst
new file mode 100644
index 000000000..ac89cf604
--- /dev/null
+++ b/tests/format/link/notfound/elements/linked-local-junction-target.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- subproject-link.bst:hello.bst
diff --git a/tests/format/link/notfound/elements/linked-local-junction.bst b/tests/format/link/notfound/elements/linked-local-junction.bst
new file mode 100644
index 000000000..6b0be9370
--- /dev/null
+++ b/tests/format/link/notfound/elements/linked-local-junction.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- subproject-link-notfound.bst:element.bst
diff --git a/tests/format/link/notfound/elements/linked-nested-junction-target.bst b/tests/format/link/notfound/elements/linked-nested-junction-target.bst
new file mode 100644
index 000000000..b39a75f0a
--- /dev/null
+++ b/tests/format/link/notfound/elements/linked-nested-junction-target.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- subsubproject-link.bst:hello.bst
diff --git a/tests/format/link/notfound/elements/linked-nested-junction.bst b/tests/format/link/notfound/elements/linked-nested-junction.bst
new file mode 100644
index 000000000..5edf294e0
--- /dev/null
+++ b/tests/format/link/notfound/elements/linked-nested-junction.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- subsubproject-link-notfound.bst:element.bst
diff --git a/tests/format/link/notfound/elements/subproject-link-notfound.bst b/tests/format/link/notfound/elements/subproject-link-notfound.bst
new file mode 100644
index 000000000..ec00414db
--- /dev/null
+++ b/tests/format/link/notfound/elements/subproject-link-notfound.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: subproject-notfound.bst
diff --git a/tests/format/junctions/config-target/elements/no-junction.bst b/tests/format/link/notfound/elements/subproject-link.bst
index 15d1842f6..5e72e81f1 100644
--- a/tests/format/junctions/config-target/elements/no-junction.bst
+++ b/tests/format/link/notfound/elements/subproject-link.bst
@@ -1,4 +1,4 @@
-kind: junction
+kind: link
config:
target: subproject.bst
diff --git a/tests/format/link/notfound/elements/subproject.bst b/tests/format/link/notfound/elements/subproject.bst
new file mode 100644
index 000000000..6664eeec6
--- /dev/null
+++ b/tests/format/link/notfound/elements/subproject.bst
@@ -0,0 +1,5 @@
+kind: junction
+
+sources:
+- kind: local
+ path: subproject
diff --git a/tests/format/link/notfound/elements/subsubproject-link-notfound.bst b/tests/format/link/notfound/elements/subsubproject-link-notfound.bst
new file mode 100644
index 000000000..1277713e7
--- /dev/null
+++ b/tests/format/link/notfound/elements/subsubproject-link-notfound.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: subproject.bst:subsubproject-junction-notfound.bst
diff --git a/tests/format/junctions/config-target/elements/subsubproject.bst b/tests/format/link/notfound/elements/subsubproject-link.bst
index 20dc4a0c4..be08bb5fe 100644
--- a/tests/format/junctions/config-target/elements/subsubproject.bst
+++ b/tests/format/link/notfound/elements/subsubproject-link.bst
@@ -1,4 +1,4 @@
-kind: junction
+kind: link
config:
target: subproject.bst:subsubproject-junction.bst
diff --git a/tests/format/link/notfound/project.conf b/tests/format/link/notfound/project.conf
new file mode 100644
index 000000000..b792ee157
--- /dev/null
+++ b/tests/format/link/notfound/project.conf
@@ -0,0 +1,4 @@
+name: notfound
+min-version: 2.0
+
+element-path: elements
diff --git a/tests/format/junctions/config-target/subproject/elements/subsubproject-junction.bst b/tests/format/link/notfound/subproject/elements/subsubproject-junction.bst
index 018fb8ec4..018fb8ec4 100644
--- a/tests/format/junctions/config-target/subproject/elements/subsubproject-junction.bst
+++ b/tests/format/link/notfound/subproject/elements/subsubproject-junction.bst
diff --git a/tests/format/link/notfound/subproject/project.conf b/tests/format/link/notfound/subproject/project.conf
new file mode 100644
index 000000000..1529ece04
--- /dev/null
+++ b/tests/format/link/notfound/subproject/project.conf
@@ -0,0 +1,4 @@
+name: subproject
+min-version: 2.0
+
+element-path: elements
diff --git a/tests/format/link/notfound/subproject/subsubproject/project.conf b/tests/format/link/notfound/subproject/subsubproject/project.conf
new file mode 100644
index 000000000..3b470ccf2
--- /dev/null
+++ b/tests/format/link/notfound/subproject/subsubproject/project.conf
@@ -0,0 +1,2 @@
+name: subsubproject
+min-version: 2.0
diff --git a/tests/format/link/simple-junctions/elements/subproject-link.bst b/tests/format/link/simple-junctions/elements/subproject-link.bst
new file mode 100644
index 000000000..5e72e81f1
--- /dev/null
+++ b/tests/format/link/simple-junctions/elements/subproject-link.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: subproject.bst
diff --git a/tests/format/link/simple-junctions/elements/subproject.bst b/tests/format/link/simple-junctions/elements/subproject.bst
new file mode 100644
index 000000000..6664eeec6
--- /dev/null
+++ b/tests/format/link/simple-junctions/elements/subproject.bst
@@ -0,0 +1,5 @@
+kind: junction
+
+sources:
+- kind: local
+ path: subproject
diff --git a/tests/format/link/simple-junctions/elements/subsubproject-link.bst b/tests/format/link/simple-junctions/elements/subsubproject-link.bst
new file mode 100644
index 000000000..be08bb5fe
--- /dev/null
+++ b/tests/format/link/simple-junctions/elements/subsubproject-link.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: subproject.bst:subsubproject-junction.bst
diff --git a/tests/format/link/simple-junctions/elements/target-local.bst b/tests/format/link/simple-junctions/elements/target-local.bst
new file mode 100644
index 000000000..ac89cf604
--- /dev/null
+++ b/tests/format/link/simple-junctions/elements/target-local.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- subproject-link.bst:hello.bst
diff --git a/tests/format/link/simple-junctions/elements/target-nested.bst b/tests/format/link/simple-junctions/elements/target-nested.bst
new file mode 100644
index 000000000..b39a75f0a
--- /dev/null
+++ b/tests/format/link/simple-junctions/elements/target-nested.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- subsubproject-link.bst:hello.bst
diff --git a/tests/format/link/simple-junctions/project.conf b/tests/format/link/simple-junctions/project.conf
new file mode 100644
index 000000000..4e2fb0063
--- /dev/null
+++ b/tests/format/link/simple-junctions/project.conf
@@ -0,0 +1,4 @@
+name: simple
+min-version: 2.0
+
+element-path: elements
diff --git a/tests/format/link/simple-junctions/subproject/elements/hello.bst b/tests/format/link/simple-junctions/subproject/elements/hello.bst
new file mode 100644
index 000000000..a04a856cd
--- /dev/null
+++ b/tests/format/link/simple-junctions/subproject/elements/hello.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/hello.txt
diff --git a/tests/format/link/simple-junctions/subproject/elements/subsubproject-junction.bst b/tests/format/link/simple-junctions/subproject/elements/subsubproject-junction.bst
new file mode 100644
index 000000000..018fb8ec4
--- /dev/null
+++ b/tests/format/link/simple-junctions/subproject/elements/subsubproject-junction.bst
@@ -0,0 +1,5 @@
+kind: junction
+
+sources:
+- kind: local
+ path: subsubproject
diff --git a/tests/format/link/simple-junctions/subproject/files/hello.txt b/tests/format/link/simple-junctions/subproject/files/hello.txt
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/tests/format/link/simple-junctions/subproject/files/hello.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/format/link/simple-junctions/subproject/project.conf b/tests/format/link/simple-junctions/subproject/project.conf
new file mode 100644
index 000000000..1529ece04
--- /dev/null
+++ b/tests/format/link/simple-junctions/subproject/project.conf
@@ -0,0 +1,4 @@
+name: subproject
+min-version: 2.0
+
+element-path: elements
diff --git a/tests/format/link/simple-junctions/subproject/subsubproject/elements/hello.bst b/tests/format/link/simple-junctions/subproject/subsubproject/elements/hello.bst
new file mode 100644
index 000000000..a04a856cd
--- /dev/null
+++ b/tests/format/link/simple-junctions/subproject/subsubproject/elements/hello.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/hello.txt
diff --git a/tests/format/link/simple-junctions/subproject/subsubproject/files/hello.txt b/tests/format/link/simple-junctions/subproject/subsubproject/files/hello.txt
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/tests/format/link/simple-junctions/subproject/subsubproject/files/hello.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/format/link/simple-junctions/subproject/subsubproject/project.conf b/tests/format/link/simple-junctions/subproject/subsubproject/project.conf
new file mode 100644
index 000000000..162143c80
--- /dev/null
+++ b/tests/format/link/simple-junctions/subproject/subsubproject/project.conf
@@ -0,0 +1,4 @@
+name: subsubproject
+min-version: 2.0
+
+element-path: elements
diff --git a/tests/format/link/simple/elements/hello-link.bst b/tests/format/link/simple/elements/hello-link.bst
new file mode 100644
index 000000000..83b0fbe46
--- /dev/null
+++ b/tests/format/link/simple/elements/hello-link.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: hello.bst
diff --git a/tests/format/link/simple/elements/hello.bst b/tests/format/link/simple/elements/hello.bst
new file mode 100644
index 000000000..a04a856cd
--- /dev/null
+++ b/tests/format/link/simple/elements/hello.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/hello.txt
diff --git a/tests/format/link/simple/elements/target.bst b/tests/format/link/simple/elements/target.bst
new file mode 100644
index 000000000..7c1be3a42
--- /dev/null
+++ b/tests/format/link/simple/elements/target.bst
@@ -0,0 +1,4 @@
+kind: stack
+
+depends:
+- hello-link.bst
diff --git a/tests/format/link/simple/files/hello.txt b/tests/format/link/simple/files/hello.txt
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/tests/format/link/simple/files/hello.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/format/link/simple/project.conf b/tests/format/link/simple/project.conf
new file mode 100644
index 000000000..4e2fb0063
--- /dev/null
+++ b/tests/format/link/simple/project.conf
@@ -0,0 +1,4 @@
+name: simple
+min-version: 2.0
+
+element-path: elements