diff options
Diffstat (limited to 'src/boost/tools/build/test/link.py')
-rwxr-xr-x | src/boost/tools/build/test/link.py | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/src/boost/tools/build/test/link.py b/src/boost/tools/build/test/link.py new file mode 100755 index 00000000..e0524ef0 --- /dev/null +++ b/src/boost/tools/build/test/link.py @@ -0,0 +1,350 @@ +#!/usr/bin/python + +# Copyright 2014-2015 Steven Watanabe +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +# Tests the link-directory rule used to create the +# common boost/ directory in the new git layout. + +import BoostBuild + +def ignore_config(t): + """These files are created by the configuration logic in link.jam + They may or may not exist, depending on the system.""" + t.ignore("bin/symlink/test-hardlink") + t.ignore("bin/test-hardlink-source") + t.ignore("bin/test-symlink") + t.ignore("bin/test-symlink-source") + +def test_basic(): + """Test creation of a single link""" + t = BoostBuild.Tester() + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + """) + + t.write("src/dir1/include/file1.h", "file1") + + t.run_build_system() + + t.expect_addition("include/file1.h") + t.expect_content("include/file1.h", "file1") + ignore_config(t) + t.expect_nothing_more() + t.cleanup() + +def test_merge_two(): + """Test merging two directories""" + t = BoostBuild.Tester() + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + """) + + t.write("src/dir1/include/file1.h", "file1") + t.write("src/dir2/include/file2.h", "file2") + + t.run_build_system() + + t.expect_addition("include/file1.h") + t.expect_content("include/file1.h", "file1") + t.expect_addition("include/file2.h") + t.expect_content("include/file2.h", "file2") + ignore_config(t) + t.expect_nothing_more() + t.cleanup() + +def test_merge_existing(group1, group2): + """Test adding a link when a different symlink already exists""" + t = BoostBuild.Tester() + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + """) + + t.write("src/dir1/include/file1.h", "file1") + t.write("src/dir2/include/file2.h", "file2") + + t.run_build_system(group1) + + if "dir1-link" in group1: + t.expect_addition("include/file1.h") + t.expect_content("include/file1.h", "file1") + if "dir2-link" in group1: + t.expect_addition("include/file2.h") + t.expect_content("include/file2.h", "file2") + ignore_config(t) + t.expect_nothing_more() + + t.run_build_system(group2) + + if "dir1-link" in group2: + if "dir1-link" not in group1: + t.expect_addition("include/file1.h") + else: + # When a directory is split the link needs to be recreated. + # On Windows, the test system checks the mod time of the + # link rather than the link target, so this may be seen as + # an update. + t.ignore_touch("include/file1.h") + t.expect_content("include/file1.h", "file1") + else: + t.ignore_removal("include/file1.h") + + if "dir2-link" in group2: + if "dir2-link" not in group1: + t.expect_addition("include/file2.h") + else: + t.ignore_touch("include/file2.h") + t.expect_content("include/file2.h", "file2") + else: + t.ignore_removal("include/file2.h") + ignore_config(t) + t.expect_nothing_more() + + t.cleanup() + +def test_merge_existing_all(): + test_merge_existing(["dir1-link"], ["dir2-link"]) + test_merge_existing(["dir2-link"], ["dir1-link"]) + test_merge_existing(["dir1-link"], ["dir1-link", "dir2-link"]) + test_merge_existing(["dir2-link"], ["dir1-link", "dir2-link"]) + +def test_merge_recursive(): + "Test merging several directories including common prefixes" + t = BoostBuild.Tester() + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + link-directory dir3-link : src/dir3/include : <location>. ; + """) + + t.write("src/dir1/include/file1.h", "file1") + t.write("src/dir2/include/file2.h", "file2") + t.write("src/dir2/include/nested/file3.h", "file3") + t.write("src/dir3/include/nested/file4.h", "file4") + + t.run_build_system() + + t.expect_addition("include/file1.h") + t.expect_content("include/file1.h", "file1") + t.expect_addition("include/file2.h") + t.expect_content("include/file2.h", "file2") + t.expect_addition("include/nested/file3.h") + t.expect_content("include/nested/file3.h", "file3") + t.expect_addition("include/nested/file4.h") + t.expect_content("include/nested/file4.h", "file4") + ignore_config(t) + t.expect_nothing_more() + + t.cleanup() + +def test_merge_recursive_existing(group1, group2): + "Test merging several directories including common prefixes." + t = BoostBuild.Tester() + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + link-directory dir3-link : src/dir3/include : <location>. ; + link-directory dir4-link : src/dir4/include : <location>. ; + link-directory dir5-link : src/dir5/include : <location>. ; + """) + + t.write("src/dir1/include/file1.h", "file1") + t.write("src/dir2/include/nested/file2.h", "file2") + t.write("src/dir3/include/nested/file3.h", "file3") + t.write("src/dir4/include/nested/xxx/yyy/file4.h", "file4") + t.write("src/dir5/include/nested/xxx/yyy/file5.h", "file5") + + t.run_build_system(group1) + t.run_build_system(group2 + ["-d+12"]) + + def check_file(target, file): + if target in group2: + if target in group1: + t.ignore_touch(file) + else: + t.expect_addition(file) + + check_file("dir1-link", "include/file1.h") + check_file("dir2-link", "include/nested/file2.h") + check_file("dir3-link", "include/nested/file3.h") + check_file("dir4-link", "include/nested/xxx/yyy/file4.h") + check_file("dir5-link", "include/nested/xxx/yyy/file5.h") + ignore_config(t) + t.expect_nothing_more() + + t.cleanup() + +def test_merge_recursive_existing_all(): + # These should create a link + test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir1-link"]) + test_merge_recursive_existing(["dir2-link"], ["dir1-link", "dir2-link"]) + # These should create a directory + test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir3-link"]) + test_merge_recursive_existing(["dir2-link"], ["dir3-link", "dir2-link"]) + # It should work even if we have to create many intermediate subdirectories + test_merge_recursive_existing(["dir4-link"], ["dir4-link", "dir5-link"]) + test_merge_recursive_existing(["dir4-link"], ["dir5-link", "dir4-link"]) + +def test_include_scan(): + """Make sure that the #include scanner finds the headers""" + t = BoostBuild.Tester() + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + obj test : test.cpp : + <include>include + <implicit-dependency>dir1-link + <implicit-dependency>dir2-link ; + """) + + t.write("src/dir1/include/file1.h", "#include <file2.h>\n") + t.write("src/dir2/include/file2.h", "int f();\n") + t.write("test.cpp", """\ + #include <file1.h> + int main() { f(); } + """); + + t.run_build_system(["test"]) + + t.expect_addition("bin/$toolset/debug*/test.obj") + + t.run_build_system() + t.expect_nothing_more() + + t.cleanup() + +def test_include_scan_merge_existing(): + """Make sure that files are replaced if needed when merging in + a new directory""" + t = BoostBuild.Tester() + + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + obj test : test.cpp : + <include>include + <implicit-dependency>dir1-link + <implicit-dependency>dir2-link ; + """) + + t.write("src/dir1/include/file1.h", "int f();") + t.write("src/dir2/include/file2.h", "#include <file1.h>") + t.write("test.cpp", """\ + #include <file2.h> + int main() { f(); } + """) + + t.run_build_system(["dir2-link"]) + + t.run_build_system(["test"]) + t.expect_addition("include/file1.h") + t.expect_addition("bin/$toolset/debug*/test.obj") + t.ignore_touch("include/file2.h") + t.expect_nothing_more() + + t.cleanup() + +def test_update_file_link(params1, params2): + """Tests the behavior of updates when changing the link mode. + The link needs to be updated iff the original was a copy.""" + t = BoostBuild.Tester() + + t.write("jamroot.jam", """\ + import link ; + import project ; + import property-set ; + import modules ; + + if --no-symlinks in [ modules.peek : ARGV ] + { + modules.poke link : .can-symlink : false ; + } + + if --no-hardlinks in [ modules.peek : ARGV ] + { + modules.poke link : .can-hardlink : false ; + } + + .project = [ project.current ] ; + .has-files = [ glob include/file1.h ] ; + + rule can-link ( properties * ) { + if ( ! [ link.can-symlink $(.project) ] ) && + ( ! [ link.can-hardlink $(.project) ] ) + { + ECHO links unsupported ; + } + } + + # Use two directories so that we link to individual files. + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + alias check-linking : : <conditional>@can-link ; + """) + t.write("src/dir1/include/file1.h", "file1") + t.write("src/dir2/include/file2.h", "file2") + + t.run_build_system(params1) + ignore_config(t) + t.expect_addition("include/file1.h") + t.expect_addition("include/file2.h") + t.expect_nothing_more() + + using_links = "links unsupported" not in t.stdout() + + t.touch("src/dir1/include/file1.h") + + t.run_build_system(params2) + if not using_links: t.expect_touch("include/file1.h") + ignore_config(t) + t.expect_nothing_more() + + t.cleanup() + +def test_update_file_link_all(): + """Test all nine possible combinations of two runs.""" + possible_args = [[], ["--no-symlinks"], ["--no-symlinks", "--no-hardlinks"]] + for arg1 in possible_args: + for arg2 in possible_args: + test_update_file_link(arg1, arg2) + +def test_error_duplicate(): + """Test that linking a single file from + multiple sources causes a hard error.""" + t = BoostBuild.Tester() + + t.write("jamroot.jam", """\ + import link ; + link-directory dir1-link : src/dir1/include : <location>. ; + link-directory dir2-link : src/dir2/include : <location>. ; + """) + + t.write("src/dir1/include/file1.h", "file1") + t.write("src/dir2/include/file1.h", "file2") + + t.run_build_system(status=1) + t.expect_output_lines( + ["error: Cannot create link include/file1.h to src/dir2/include/file1.h.", + "error: Link previously defined to another file, src/dir1/include/file1.h."]) + + t.cleanup() + +test_basic() +test_merge_two() +test_merge_existing_all() +test_merge_recursive() +test_merge_recursive_existing_all() +test_include_scan() +test_include_scan_merge_existing() +test_update_file_link_all() +test_error_duplicate() |