]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #!/usr/bin/python |
2 | ||
3 | # Copyright 2014-2015 Steven Watanabe | |
4 | # Distributed under the Boost Software License, Version 1.0. | |
5 | # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | # Tests the link-directory rule used to create the | |
8 | # common boost/ directory in the new git layout. | |
9 | ||
10 | import BoostBuild | |
11 | ||
12 | def ignore_config(t): | |
13 | """These files are created by the configuration logic in link.jam | |
14 | They may or may not exist, depending on the system.""" | |
15 | t.ignore("bin/symlink/test-hardlink") | |
16 | t.ignore("bin/test-hardlink-source") | |
17 | t.ignore("bin/test-symlink") | |
18 | t.ignore("bin/test-symlink-source") | |
19 | ||
20 | def test_basic(): | |
21 | """Test creation of a single link""" | |
22 | t = BoostBuild.Tester() | |
23 | t.write("jamroot.jam", """\ | |
24 | import link ; | |
25 | link-directory dir1-link : src/dir1/include : <location>. ; | |
26 | """) | |
27 | ||
28 | t.write("src/dir1/include/file1.h", "file1") | |
29 | ||
30 | t.run_build_system() | |
31 | ||
32 | t.expect_addition("include/file1.h") | |
33 | t.expect_content("include/file1.h", "file1") | |
34 | ignore_config(t) | |
35 | t.expect_nothing_more() | |
36 | t.cleanup() | |
37 | ||
38 | def test_merge_two(): | |
39 | """Test merging two directories""" | |
40 | t = BoostBuild.Tester() | |
41 | t.write("jamroot.jam", """\ | |
42 | import link ; | |
43 | link-directory dir1-link : src/dir1/include : <location>. ; | |
44 | link-directory dir2-link : src/dir2/include : <location>. ; | |
45 | """) | |
46 | ||
47 | t.write("src/dir1/include/file1.h", "file1") | |
48 | t.write("src/dir2/include/file2.h", "file2") | |
49 | ||
50 | t.run_build_system() | |
51 | ||
52 | t.expect_addition("include/file1.h") | |
53 | t.expect_content("include/file1.h", "file1") | |
54 | t.expect_addition("include/file2.h") | |
55 | t.expect_content("include/file2.h", "file2") | |
56 | ignore_config(t) | |
57 | t.expect_nothing_more() | |
58 | t.cleanup() | |
59 | ||
60 | def test_merge_existing(group1, group2): | |
61 | """Test adding a link when a different symlink already exists""" | |
62 | t = BoostBuild.Tester() | |
63 | t.write("jamroot.jam", """\ | |
64 | import link ; | |
65 | link-directory dir1-link : src/dir1/include : <location>. ; | |
66 | link-directory dir2-link : src/dir2/include : <location>. ; | |
67 | """) | |
68 | ||
69 | t.write("src/dir1/include/file1.h", "file1") | |
70 | t.write("src/dir2/include/file2.h", "file2") | |
71 | ||
72 | t.run_build_system(group1) | |
73 | ||
74 | if "dir1-link" in group1: | |
75 | t.expect_addition("include/file1.h") | |
76 | t.expect_content("include/file1.h", "file1") | |
77 | if "dir2-link" in group1: | |
78 | t.expect_addition("include/file2.h") | |
79 | t.expect_content("include/file2.h", "file2") | |
80 | ignore_config(t) | |
81 | t.expect_nothing_more() | |
82 | ||
83 | t.run_build_system(group2) | |
84 | ||
85 | if "dir1-link" in group2: | |
86 | if "dir1-link" not in group1: | |
87 | t.expect_addition("include/file1.h") | |
b32b8144 FG |
88 | else: |
89 | # When a directory is split the link needs to be recreated. | |
90 | # On Windows, the test system checks the mod time of the | |
91 | # link rather than the link target, so this may be seen as | |
92 | # an update. | |
93 | t.ignore_touch("include/file1.h") | |
7c673cae FG |
94 | t.expect_content("include/file1.h", "file1") |
95 | else: | |
96 | t.ignore_removal("include/file1.h") | |
97 | ||
98 | if "dir2-link" in group2: | |
99 | if "dir2-link" not in group1: | |
100 | t.expect_addition("include/file2.h") | |
b32b8144 FG |
101 | else: |
102 | t.ignore_touch("include/file2.h") | |
7c673cae FG |
103 | t.expect_content("include/file2.h", "file2") |
104 | else: | |
105 | t.ignore_removal("include/file2.h") | |
106 | ignore_config(t) | |
107 | t.expect_nothing_more() | |
108 | ||
109 | t.cleanup() | |
110 | ||
111 | def test_merge_existing_all(): | |
112 | test_merge_existing(["dir1-link"], ["dir2-link"]) | |
113 | test_merge_existing(["dir2-link"], ["dir1-link"]) | |
114 | test_merge_existing(["dir1-link"], ["dir1-link", "dir2-link"]) | |
115 | test_merge_existing(["dir2-link"], ["dir1-link", "dir2-link"]) | |
116 | ||
117 | def test_merge_recursive(): | |
118 | "Test merging several directories including common prefixes" | |
119 | t = BoostBuild.Tester() | |
120 | t.write("jamroot.jam", """\ | |
121 | import link ; | |
122 | link-directory dir1-link : src/dir1/include : <location>. ; | |
123 | link-directory dir2-link : src/dir2/include : <location>. ; | |
124 | link-directory dir3-link : src/dir3/include : <location>. ; | |
125 | """) | |
126 | ||
127 | t.write("src/dir1/include/file1.h", "file1") | |
128 | t.write("src/dir2/include/file2.h", "file2") | |
129 | t.write("src/dir2/include/nested/file3.h", "file3") | |
130 | t.write("src/dir3/include/nested/file4.h", "file4") | |
131 | ||
132 | t.run_build_system() | |
133 | ||
134 | t.expect_addition("include/file1.h") | |
135 | t.expect_content("include/file1.h", "file1") | |
136 | t.expect_addition("include/file2.h") | |
137 | t.expect_content("include/file2.h", "file2") | |
138 | t.expect_addition("include/nested/file3.h") | |
139 | t.expect_content("include/nested/file3.h", "file3") | |
140 | t.expect_addition("include/nested/file4.h") | |
141 | t.expect_content("include/nested/file4.h", "file4") | |
142 | ignore_config(t) | |
143 | t.expect_nothing_more() | |
144 | ||
145 | t.cleanup() | |
146 | ||
147 | def test_merge_recursive_existing(group1, group2): | |
148 | "Test merging several directories including common prefixes." | |
149 | t = BoostBuild.Tester() | |
150 | t.write("jamroot.jam", """\ | |
151 | import link ; | |
152 | link-directory dir1-link : src/dir1/include : <location>. ; | |
153 | link-directory dir2-link : src/dir2/include : <location>. ; | |
154 | link-directory dir3-link : src/dir3/include : <location>. ; | |
155 | link-directory dir4-link : src/dir4/include : <location>. ; | |
156 | link-directory dir5-link : src/dir5/include : <location>. ; | |
157 | """) | |
158 | ||
159 | t.write("src/dir1/include/file1.h", "file1") | |
160 | t.write("src/dir2/include/nested/file2.h", "file2") | |
161 | t.write("src/dir3/include/nested/file3.h", "file3") | |
162 | t.write("src/dir4/include/nested/xxx/yyy/file4.h", "file4") | |
163 | t.write("src/dir5/include/nested/xxx/yyy/file5.h", "file5") | |
164 | ||
165 | t.run_build_system(group1) | |
166 | t.run_build_system(group2 + ["-d+12"]) | |
167 | ||
b32b8144 FG |
168 | def check_file(target, file): |
169 | if target in group2: | |
170 | if target in group1: | |
171 | t.ignore_touch(file) | |
172 | else: | |
173 | t.expect_addition(file) | |
174 | ||
175 | check_file("dir1-link", "include/file1.h") | |
176 | check_file("dir2-link", "include/nested/file2.h") | |
177 | check_file("dir3-link", "include/nested/file3.h") | |
178 | check_file("dir4-link", "include/nested/xxx/yyy/file4.h") | |
179 | check_file("dir5-link", "include/nested/xxx/yyy/file5.h") | |
7c673cae FG |
180 | ignore_config(t) |
181 | t.expect_nothing_more() | |
182 | ||
183 | t.cleanup() | |
184 | ||
185 | def test_merge_recursive_existing_all(): | |
186 | # These should create a link | |
187 | test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir1-link"]) | |
188 | test_merge_recursive_existing(["dir2-link"], ["dir1-link", "dir2-link"]) | |
189 | # These should create a directory | |
190 | test_merge_recursive_existing(["dir2-link"], ["dir2-link", "dir3-link"]) | |
191 | test_merge_recursive_existing(["dir2-link"], ["dir3-link", "dir2-link"]) | |
192 | # It should work even if we have to create many intermediate subdirectories | |
193 | test_merge_recursive_existing(["dir4-link"], ["dir4-link", "dir5-link"]) | |
194 | test_merge_recursive_existing(["dir4-link"], ["dir5-link", "dir4-link"]) | |
195 | ||
196 | def test_include_scan(): | |
197 | """Make sure that the #include scanner finds the headers""" | |
198 | t = BoostBuild.Tester() | |
199 | t.write("jamroot.jam", """\ | |
200 | import link ; | |
201 | link-directory dir1-link : src/dir1/include : <location>. ; | |
202 | link-directory dir2-link : src/dir2/include : <location>. ; | |
203 | obj test : test.cpp : | |
204 | <include>include | |
205 | <implicit-dependency>dir1-link | |
206 | <implicit-dependency>dir2-link ; | |
207 | """) | |
208 | ||
209 | t.write("src/dir1/include/file1.h", "#include <file2.h>\n") | |
210 | t.write("src/dir2/include/file2.h", "int f();\n") | |
211 | t.write("test.cpp", """\ | |
212 | #include <file1.h> | |
213 | int main() { f(); } | |
214 | """); | |
215 | ||
216 | t.run_build_system(["test"]) | |
217 | ||
b32b8144 | 218 | t.expect_addition("bin/$toolset/debug*/test.obj") |
7c673cae FG |
219 | |
220 | t.run_build_system() | |
221 | t.expect_nothing_more() | |
222 | ||
223 | t.cleanup() | |
224 | ||
225 | def test_include_scan_merge_existing(): | |
226 | """Make sure that files are replaced if needed when merging in | |
227 | a new directory""" | |
228 | t = BoostBuild.Tester() | |
229 | ||
230 | t.write("jamroot.jam", """\ | |
231 | import link ; | |
232 | link-directory dir1-link : src/dir1/include : <location>. ; | |
233 | link-directory dir2-link : src/dir2/include : <location>. ; | |
234 | obj test : test.cpp : | |
235 | <include>include | |
236 | <implicit-dependency>dir1-link | |
237 | <implicit-dependency>dir2-link ; | |
238 | """) | |
239 | ||
240 | t.write("src/dir1/include/file1.h", "int f();") | |
241 | t.write("src/dir2/include/file2.h", "#include <file1.h>") | |
242 | t.write("test.cpp", """\ | |
243 | #include <file2.h> | |
244 | int main() { f(); } | |
245 | """) | |
246 | ||
247 | t.run_build_system(["dir2-link"]) | |
248 | ||
249 | t.run_build_system(["test"]) | |
250 | t.expect_addition("include/file1.h") | |
b32b8144 FG |
251 | t.expect_addition("bin/$toolset/debug*/test.obj") |
252 | t.ignore_touch("include/file2.h") | |
7c673cae FG |
253 | t.expect_nothing_more() |
254 | ||
255 | t.cleanup() | |
256 | ||
257 | def test_update_file_link(params1, params2): | |
258 | """Tests the behavior of updates when changing the link mode. | |
259 | The link needs to be updated iff the original was a copy.""" | |
260 | t = BoostBuild.Tester() | |
261 | ||
262 | t.write("jamroot.jam", """\ | |
263 | import link ; | |
264 | import project ; | |
265 | import property-set ; | |
266 | import modules ; | |
267 | ||
268 | if --no-symlinks in [ modules.peek : ARGV ] | |
269 | { | |
270 | modules.poke link : .can-symlink : false ; | |
271 | } | |
272 | ||
273 | if --no-hardlinks in [ modules.peek : ARGV ] | |
274 | { | |
275 | modules.poke link : .can-hardlink : false ; | |
276 | } | |
277 | ||
278 | .project = [ project.current ] ; | |
279 | .has-files = [ glob include/file1.h ] ; | |
280 | ||
281 | rule can-link ( properties * ) { | |
282 | if ( ! [ link.can-symlink $(.project) : [ property-set.empty ] ] ) && | |
283 | ( ! [ link.can-hardlink $(.project) : [ property-set.empty ] ] ) | |
284 | { | |
285 | ECHO links unsupported ; | |
286 | } | |
287 | } | |
288 | ||
289 | # Use two directories so that we link to individual files. | |
290 | link-directory dir1-link : src/dir1/include : <location>. ; | |
291 | link-directory dir2-link : src/dir2/include : <location>. ; | |
292 | alias check-linking : : <conditional>@can-link ; | |
293 | """) | |
294 | t.write("src/dir1/include/file1.h", "file1") | |
295 | t.write("src/dir2/include/file2.h", "file2") | |
296 | ||
297 | t.run_build_system(params1) | |
298 | ignore_config(t) | |
299 | t.expect_addition("include/file1.h") | |
300 | t.expect_addition("include/file2.h") | |
301 | t.expect_nothing_more() | |
302 | ||
303 | using_links = "links unsupported" not in t.stdout() | |
304 | ||
305 | t.touch("src/dir1/include/file1.h") | |
306 | ||
307 | t.run_build_system(params2) | |
308 | if not using_links: t.expect_touch("include/file1.h") | |
309 | ignore_config(t) | |
310 | t.expect_nothing_more() | |
311 | ||
312 | t.cleanup() | |
313 | ||
314 | def test_update_file_link_all(): | |
315 | """Test all nine possible combinations of two runs.""" | |
316 | possible_args = [[], ["--no-symlinks"], ["--no-symlinks", "--no-hardlinks"]] | |
317 | for arg1 in possible_args: | |
318 | for arg2 in possible_args: | |
319 | test_update_file_link(arg1, arg2) | |
320 | ||
321 | def test_error_duplicate(): | |
322 | """Test that linking a single file from | |
323 | multiple sources causes a hard error.""" | |
324 | t = BoostBuild.Tester() | |
325 | ||
326 | t.write("jamroot.jam", """\ | |
327 | import link ; | |
328 | link-directory dir1-link : src/dir1/include : <location>. ; | |
329 | link-directory dir2-link : src/dir2/include : <location>. ; | |
330 | """) | |
331 | ||
332 | t.write("src/dir1/include/file1.h", "file1") | |
333 | t.write("src/dir2/include/file1.h", "file2") | |
334 | ||
335 | t.run_build_system(status=1) | |
336 | t.expect_output_lines( | |
337 | ["error: Cannot create link include/file1.h to src/dir2/include/file1.h.", | |
338 | "error: Link previously defined to another file, src/dir1/include/file1.h."]) | |
339 | ||
340 | t.cleanup() | |
341 | ||
342 | test_basic() | |
343 | test_merge_two() | |
344 | test_merge_existing_all() | |
345 | test_merge_recursive() | |
346 | test_merge_recursive_existing_all() | |
347 | test_include_scan() | |
348 | test_include_scan_merge_existing() | |
349 | test_update_file_link_all() | |
350 | test_error_duplicate() |