1#!/usr/local/bin/python3.8
2
3# Copyright 2014 Steven Watanabe
4# Copyright 2015 Artur Shepilko
5# Distributed under the Boost Software License, Version 1.0.
6# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
7
8# This tests the GLOB_ARCHIVE rule.
9
10import os
11import sys
12try:
13    from StringIO import StringIO
14except:
15    from io import StringIO
16import BoostBuild
17
18vms = ( os.name == 'posix' and sys.platform == 'OpenVMS')
19
20t = BoostBuild.Tester()
21
22## Setup test archive sources and symbols they contain.
23sources = {
24    "a.cpp" : ["a"],
25    "b.cpp" : ["b"],
26    "b_match.cpp" : ["b_match"],
27    "c/nopath_check.cpp" : ["nopath_check"],
28    "CaseCheck.cpp" : ["CaseCheck"],
29    "seq_check1.cpp" : ["seq_check1"],
30    "seq_check2.cpp" : ["seq_check2"],
31    "seq_check3.cpp" : ["seq_check3"],
32    "symbols_check.c" : ["symbol", "symbol_match"],
33    "members_and_symbols_check.c" : ["member_and_symbol_match"],
34    "symbol_case_check.c" : ["SymbolCaseCheck"],
35    "main_check.cpp" : ["main"]
36}
37
38
39def create_sources(path, sources):
40    for s in sources :
41        f = os.path.join(path, s)
42        t.write(f, "")
43        output = StringIO()
44        for sym in sources[s] :
45            output.write("int %s() { return 0; }\n" % sym)
46        t.write(f, output.getvalue())
47
48
49def setup_archive(name, sources):
50    global archive
51    global obj_suffix
52    archive = t.adjust_names(name)[0]
53    obj_suffix = t.adjust_names(".obj")[0]
54    output = StringIO()
55    t.write("jamroot.jam","")
56    output.write("""\
57static-lib %s :
58""" % name.split(".")[0])
59    ## sort the sources, so we can test order of the globbed members
60    for s in sorted(sources) :
61        output.write("""\
62    %s
63""" % s)
64    output.write("""\
65    ;
66""")
67    t.write("lib/jamfile.jam", output.getvalue())
68    create_sources("lib", sources)
69    t.run_build_system(subdir="lib")
70    built_archive = "lib/bin/$toolset/debug*/%s" % name
71    t.expect_addition(built_archive)
72    t.copy(built_archive, name)
73    t.rm("lib")
74
75
76def test_glob_archive(archives, glob, expected, sort_results = False):
77    output = StringIO()
78    ## replace placeholders
79    glob = glob.replace("$archive1", archives[0]).replace("$obj", obj_suffix)
80    expected = [ m.replace("$archive1",
81               archives[0]).replace("$obj", obj_suffix) for m in expected ]
82    if len(archives) > 1 :
83        glob = glob.replace("$archive2", archives[1]).replace("$obj", obj_suffix)
84        expected = [ m.replace("$archive2",
85               archives[1]).replace("$obj", obj_suffix) for m in expected ]
86    ## create test jamfile
87    if sort_results : glob = "[ SORT %s ]" % glob
88    output.write("""\
89    for local p in %s
90    {
91        ECHO $(p) ;
92    }
93    UPDATE ;
94    """ % glob)
95    t.write("file.jam", output.getvalue())
96    ## run test jamfile and match against expected results
97    if sort_results : expected.sort()
98    t.run_build_system(["-ffile.jam"], stdout="\n".join(expected + [""]))
99    t.rm("file.jam")
100
101
102## RUN TESTS
103setup_archive("auxilliary1.lib", sources)
104archive1 = archive
105setup_archive("auxilliary2.lib", sources)
106archive2 = archive
107
108## all arguments empty
109test_glob_archive([archive1], "[ GLOB_ARCHIVE ]", [])
110
111## empty query
112test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : ]", [])
113
114## no-match
115test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : a ]", [])
116
117## match exact
118test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : a$obj ]",
119                  ["$archive1(a$obj)"])
120
121## glob wildcards:1
122test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : b.* ]",
123                  ["$archive1(b$obj)"])
124
125## glob wildcards:2
126test_glob_archive([archive1], '[ GLOB_ARCHIVE $archive1 : "\\b?match[\.]*" ]',
127                  ["$archive1(b_match$obj)"])
128
129## glob wildcards:3
130test_glob_archive([archive1], "[ SORT [ GLOB_ARCHIVE $archive1 : b* ] ]",
131                  ["$archive1(b$obj)", "$archive1(b_match$obj)"])
132
133## glob multiple patterns with multiple results.
134test_glob_archive([archive1], "[ SORT [ GLOB_ARCHIVE $archive1 : b.* b_* ] ]",
135                  ["$archive1(b$obj)", "$archive1(b_match$obj)"])
136
137## glob multiple archives and patterns.
138test_glob_archive([archive1, archive2],
139                  "[ SORT [ GLOB_ARCHIVE $archive1 $archive2 : b.* b_* ] ]",
140                  ["$archive1(b$obj)", "$archive1(b_match$obj)",
141                   "$archive2(b$obj)", "$archive2(b_match$obj)"])
142
143## glob same archive multiple times.
144test_glob_archive([archive1, archive1],
145                  "[ GLOB_ARCHIVE $archive1 $archive2 $archive1 : b.* ]",
146                   ["$archive1(b$obj)", "$archive2(b$obj)", "$archive1(b$obj)"])
147
148## returned archive member has no path, even though its source object-file did.
149## this is rather NT-specific, where members also store their object-file's path.
150test_glob_archive([archive1], "[ GLOB_ARCHIVE $archive1 : nopath_check$obj ]",
151                  ["$archive1(nopath_check$obj)"])
152
153## case insensitive matching, when archives support case sensitive member names.
154## VMS implementation forces case-insensitive matching and downcased member names.
155
156case_sensitive_members = ( not vms )
157
158if case_sensitive_members:
159    test_glob_archive([archive1],
160                      "[ GLOB_ARCHIVE $archive1 : casecheck$obj : true ]",
161                      ["$archive1(CaseCheck$obj)"])
162elif vms:
163    test_glob_archive([archive1],
164                      "[ GLOB_ARCHIVE $archive1 : CaseCheck$obj : false ]",
165                      ["$archive1(casecheck$obj)"])
166
167
168## test the order of matched members, in general it should match the
169## insertion sequence.
170test_glob_archive([archive1], "[ SORT [ GLOB_ARCHIVE $archive1 : seq_check*$obj ] ]",
171                  ["$archive1(seq_check1$obj)", "$archive1(seq_check2$obj)",
172                   "$archive1(seq_check3$obj)"])
173
174
175## glob members by symbols they contain.
176## Currently supported only on VMS.
177symbol_glob_supported = ( vms )
178
179if symbol_glob_supported :
180    ## NOTE: generated symbols are compiler-dependent and may be specifically
181    ## mangled (as in C++ case), so globbing by exact symbol is non-trivial.
182    ## However, C-generated symbols are likely to have more portable names,
183    ## so for the glob-by-symbol tests we glob C-generated archive members.
184
185    ## glob members by exact symbol.
186    test_glob_archive([archive1],
187                      "[ GLOB_ARCHIVE $archive1 : : : symbol ]",
188                      ["$archive1(symbols_check$obj)"])
189
190    ## glob members by symbol wildcard.
191    test_glob_archive([archive1],
192                      "[ GLOB_ARCHIVE $archive1 : : : symbol_* ]",
193                      ["$archive1(symbols_check$obj)"])
194
195    ## glob members by member pattern AND symbol pattern.
196    test_glob_archive([archive1],
197                      "[ GLOB_ARCHIVE $archive1 : *symbol* : : *member* ]",
198                      ["$archive1(members_and_symbols_check$obj)"])
199
200    ## case insensitive symbol glob.
201    test_glob_archive([archive1],
202                      "[ GLOB_ARCHIVE $archive1 : : true : symbolcasecheck ]",
203                      ["$archive1(symbol_case_check$obj)"])
204
205    ## glob member that contains main symbol.
206    test_glob_archive([archive1],
207                      "[ GLOB_ARCHIVE $archive1 : : : main _main ]",
208                      ["$archive1(main_check$obj)"])
209
210else:
211    test_glob_archive([archive1],
212                      "[ GLOB_ARCHIVE $archive1 : : : symbol ]",
213                      [])
214
215
216t.cleanup()
217
218