3 # Copyright The SCons Foundation
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Test helper functions for Microsoft Visual C/C++.
34 from SCons
.Tool
.MSCommon
.MSVC
import Config
35 from SCons
.Tool
.MSCommon
.MSVC
import Util
36 from SCons
.Tool
.MSCommon
.MSVC
import WinSDK
39 p
= os
.path
.abspath(p
)
40 p
= str(pathlib
.Path(p
).resolve())
43 def normalize(*comps
):
44 p
= os
.path
.join(*comps
)
45 p
= os
.path
.normpath(p
)
46 p
= os
.path
.normcase(p
)
51 IS_WINDOWS
= sys
.platform
== 'win32'
55 UTIL_MODULE
= os
.path
.dirname(Util
.__file
__)
56 UTIL_MODULE_PARENT
= os
.path
.join(UTIL_MODULE
, os
.pardir
)
58 HOME
= pathlib
.Path
.home()
59 HOMEDRIVE
= HOME
.drive
62 REALPATH_CWD
= resolve(CWD
)
64 REALPATH_UTIL_MODULE
= resolve(UTIL_MODULE
)
65 REALPATH_UTIL_MODULE_PARENT
= resolve(UTIL_MODULE_PARENT
)
67 REALPATH_HOMEPATH
= resolve(HOMEPATH
)
68 REALPATH_HOMEPATH_PARENT
= resolve(os
.path
.join(HOMEPATH
, os
.pardir
))
69 REALPATH_HOMEDRIVE
= resolve(HOMEDRIVE
)
70 REALPATH_HOMEDRIVE_CWD
= resolve(HOMEDRIVE
)
72 class UtilTests(unittest
.TestCase
):
74 def test_listdir_dirs(self
) -> None:
75 func
= Util
.listdir_dirs
76 for dirname
, expect
in [
77 (None, False), ('', False), ('doesnotexist.xyz.abc', False),
78 (Data
.UTIL_MODULE_PARENT
, True),
81 self
.assertTrue((len(dirs
) > 0) == expect
, "{}({}): {}".format(
82 func
.__name
__, repr(dirname
), 'list is empty' if expect
else 'list is not empty'
85 def test_resolve_path(self
) -> None:
86 func
= Util
.resolve_path
88 # ignore_drivespec=True
90 (Data
.UTIL_MODULE
, Data
.REALPATH_UTIL_MODULE
, {}),
91 (os
.path
.join(Data
.UTIL_MODULE
, os
.pardir
), Data
.REALPATH_UTIL_MODULE_PARENT
, {}),
92 (Data
.HOMEPATH
, Data
.REALPATH_HOMEPATH
, {}),
93 (os
.path
.join(Data
.HOMEPATH
, os
.pardir
), Data
.REALPATH_HOMEPATH_PARENT
, {}),
97 (Data
.HOMEDRIVE
, Data
.HOMEDRIVE
, {}),
98 (Data
.HOMEDRIVE
, Data
.HOMEDRIVE
, {'ignore_drivespec': True}),
99 (Data
.HOMEDRIVE
, Data
.REALPATH_HOMEDRIVE_CWD
, {'ignore_drivespec': False}),
101 for p
, expect
, kwargs
in test_list
:
102 rval
= func(p
, **kwargs
)
103 # print(repr(p), repr(expect), repr(rval))
104 self
.assertTrue(rval
== expect
, "{}({}): {}".format(
105 func
.__name
__, repr(p
), repr(rval
)
108 def test_normalize_path(self
) -> None:
109 func
= Util
.normalize_path
112 # preserve_trailing=False
115 # ignore_drivespec=True
117 (Data
.UTIL_MODULE
, normalize(Data
.REALPATH_UTIL_MODULE
), {}),
118 (os
.path
.join(Data
.UTIL_MODULE
, os
.pardir
), normalize(Data
.REALPATH_UTIL_MODULE_PARENT
), {}),
120 ('', '', {'realpath': False}),
121 ('', '', {'realpath': True}),
122 ('DoesNotExist.xyz.abc', normalize('DoesNotExist.xyz.abc'), {'realpath': False}),
123 ('DoesNotExist.xyz.abc', normalize(Data
.REALPATH_CWD
, 'DoesNotExist.xyz.abc'), {'realpath': True}),
124 (' DoesNotExist.xyz.abc ', normalize(Data
.REALPATH_CWD
, 'DoesNotExist.xyz.abc'), {'realpath': True}),
125 (' ~ ', '~', {'realpath': False, 'expand': False}),
126 (' ~ ', normalize(Data
.REALPATH_HOMEPATH
), {'realpath': True, 'expand': True}),
130 ('DoesNotExist.xyz.abc/', normalize('DoesNotExist.xyz.abc') + os
.path
.sep
, {'realpath': False, 'preserve_trailing': True}),
131 (' DoesNotExist.xyz.abc\\ ', normalize('DoesNotExist.xyz.abc') + os
.path
.sep
, {'realpath': False, 'preserve_trailing': True}),
132 (' ~/ ', normalize(Data
.REALPATH_HOMEPATH
) + os
.path
.sep
, {'realpath': True, 'expand': True, 'preserve_trailing': True}),
133 (' ~\\ ', normalize(Data
.REALPATH_HOMEPATH
) + os
.path
.sep
, {'realpath': True, 'expand': True, 'preserve_trailing': True}),
134 (' ~/ ', normalize(Data
.REALPATH_CWD
, '~') + os
.path
.sep
, {'realpath': True, 'expand': False, 'preserve_trailing': True}),
135 (' ~\\ ', normalize(Data
.REALPATH_CWD
, '~') + os
.path
.sep
, {'realpath': True, 'expand': False, 'preserve_trailing': True}),
136 (Data
.HOMEDRIVE
, normalize(Data
.HOMEDRIVE
), {}),
137 (Data
.HOMEDRIVE
, normalize(Data
.HOMEDRIVE
), {'ignore_drivespec': True}),
138 (Data
.HOMEDRIVE
, normalize(Data
.REALPATH_HOMEDRIVE_CWD
), {'ignore_drivespec': False}),
140 for p
, expect
, kwargs
in test_list
:
141 rval
= func(p
, **kwargs
)
142 # print(repr(p), repr(expect), repr(rval))
143 self
.assertTrue(rval
== expect
, "{}({}): {}".format(
144 func
.__name
__, repr(p
), repr(rval
)
147 def test_get_version_prefix(self
) -> None:
148 func
= Util
.get_version_prefix
149 for version
, expect
in [
150 (None, ''), ('', ''),
151 ('.', ''), ('0..0', ''), ('.0', ''), ('0.', ''), ('0.0.', ''),
152 ('0', '0'), ('0Abc', '0'), ('0 0', '0'), ('0,0', '0'),
153 ('0.0', '0.0'), ('0.0.0', '0.0.0'), ('0.0.0.0', '0.0.0.0'), ('0.0.0.0.0', '0.0.0.0.0'),
154 ('00.00.00000', '00.00.00000'), ('00.00.00.0', '00.00.00.0'), ('00.00.00.00', '00.00.00.00'), ('00.0.00000.0', '00.0.00000.0'),
155 ('0.0A', '0.0'), ('0.0.0B', '0.0.0'), ('0.0.0.0 C', '0.0.0.0'), ('0.0.0.0.0 D', '0.0.0.0.0'),
157 prefix
= func(version
)
158 self
.assertTrue(prefix
== expect
, "{}({}): {} != {}".format(
159 func
.__name
__, repr(version
), repr(prefix
), repr(expect
)
162 def test_get_msvc_version_prefix(self
) -> None:
163 func
= Util
.get_msvc_version_prefix
164 for version
, expect
in [
165 (None, ''), ('', ''),
166 ('.', ''), ('0..0', ''), ('.0', ''), ('0.', ''), ('0.0.', ''),
167 ('0', ''), ('0Abc', ''), ('0 0', ''), ('0,0', ''),
168 ('0.0', ''), ('0.0.0', ''), ('0.0.0.0', ''), ('0.0.0.0.0', ''),
169 ('1.0A', '1.0'), ('1.0.0B', '1.0'), ('1.0.0.0 C', '1.0'), ('1.0.0.0.0 D', '1.0'),
170 ('1.00A', '1.0'), ('1.00.0B', '1.0'), ('1.00.0.0 C', '1.0'), ('1.00.0.0.0 D', '1.0'),
172 prefix
= func(version
)
173 self
.assertTrue(prefix
== expect
, "{}({}): {} != {}".format(
174 func
.__name
__, repr(version
), repr(prefix
), repr(expect
)
177 def test_is_toolset_full(self
) -> None:
178 func
= Util
.is_toolset_full
179 for toolset
, expect
in [
180 (None, False), ('', False),
181 ('14.1.', False), ('14.10.', False), ('14.10.00000.', False), ('14.10.000000', False), ('14.1Exp', False),
182 ('14.1', True), ('14.10', True), ('14.10.0', True), ('14.10.00', True), ('14.10.000', True), ('14.10.0000', True), ('14.10.0000', True),
185 self
.assertTrue(rval
== expect
, "{}({}) != {}".format(
186 func
.__name
__, repr(toolset
), repr(rval
)
189 def test_is_toolset_140(self
) -> None:
190 func
= Util
.is_toolset_140
191 for toolset
, expect
in [
192 (None, False), ('', False),
193 ('14.0.', False), ('14.00.', False), ('14.00.00000.', False), ('14.00.000000', False), ('14.0Exp', False),
194 ('14.0', True), ('14.00', True), ('14.00.0', True), ('14.00.00', True), ('14.00.000', True), ('14.00.0000', True), ('14.00.0000', True),
197 self
.assertTrue(rval
== expect
, "{}({}) != {}".format(
198 func
.__name
__, repr(toolset
), repr(rval
)
201 def test_is_toolset_sxs(self
) -> None:
202 func
= Util
.is_toolset_sxs
203 for toolset
, expect
in [
204 (None, False), ('', False),
205 ('14.2.', False), ('14.29.', False), ('14.29.1.', False), ('14.29.16.', False), ('14.29.16.1.', False),
206 ('14.29.16.1', True), ('14.29.16.10', True),
209 self
.assertTrue(rval
== expect
, "{}({}) != {}".format(
210 func
.__name
__, repr(toolset
), repr(rval
)
213 def test_msvc_version_components(self
) -> None:
214 func
= Util
.msvc_version_components
215 for vcver
, expect
in [
216 (None, False), ('', False), ('ABC', False), ('14', False), ('14.1.', False), ('14.16', False),
217 ('14.1', True), ('14.1Exp', True),
220 comps_def
= func(vcver
)
221 msg
= 'msvc version components definition is None' if expect
else 'msvc version components definition is not None'
222 self
.assertTrue((comps_def
is not None) == expect
, "{}({}): {}".format(
223 func
.__name
__, repr(vcver
), repr(msg
)
225 for vcver
in Config
.MSVC_VERSION_SUFFIX
.keys():
226 comps_def
= func(vcver
)
227 self
.assertNotEqual(comps_def
, None, "{}({}) is None".format(
228 func
.__name
__, repr(vcver
)
231 def test_msvc_extended_version_components(self
) -> None:
232 func
= Util
.msvc_extended_version_components
234 for vcver
, expect
in [
235 (None, False), ('', False), ('ABC', False), ('14', False), ('14.1.', False),
236 ('14.1', True), ('14.16', True),
237 ('14.1Exp', True), ('14.16Exp', True),
238 ('14.16.2', True), ('14.16.27', True), ('14.16.270', True),
239 ('14.16.2702', True), ('14.16.2702', True), ('14.16.27023', True),
240 ('14.16.270239', False),
241 ('14.16.2Exp', True), ('14.16.27Exp', True), ('14.16.270Exp', True),
242 ('14.16.2702Exp', True), ('14.16.2702Exp', True), ('14.16.27023Exp', True),
243 ('14.16.270239Exp', False),
244 ('14.28.16.9', True), ('14.28.16.10', True),
245 ('14.28.16.9Exp', False), ('14.28.16.10Exp', False),
247 comps_def
= func(vcver
)
248 msg
= 'msvc extended version components definition is None' if expect
else 'msvc extended version components definition is not None'
249 self
.assertTrue((comps_def
is not None) == expect
, "{}({}): {}".format(
250 func
.__name
__, repr(vcver
), repr(msg
)
252 for vcver
in Config
.MSVC_VERSION_SUFFIX
.keys():
253 comps_def
= func(vcver
)
254 self
.assertNotEqual(comps_def
, None, "{}({}) is None".format(
255 func
.__name
__, repr(vcver
)
257 # force 'just in case' guard code path
258 save_re
= Util
.re_extended_version
259 Util
.re_extended_version
= re
.compile(r
'^(?P<version>[0-9]+)$')
260 for vcver
, expect
in [
263 comps_def
= func(vcver
)
264 msg
= 'msvc extended version components definition is None' if expect
else 'msvc extended version components definition is not None'
265 self
.assertTrue((comps_def
is not None) == expect
, "{}({}): {}".format(
266 func
.__name
__, repr(vcver
), repr(msg
)
268 Util
.re_extended_version
= save_re
270 def test_msvc_sdk_version_components(self
) -> None:
271 func
= Util
.msvc_sdk_version_components
272 for vcver
, expect
in [
273 (None, False), ('', False), ('ABC', False), ('14', False), ('14.1.', False), ('14.16', False),
274 ('8.1', True), ('10.0', True), ('10.0.20348.0', True),
276 comps_def
= func(vcver
)
277 msg
= 'msvc sdk version components definition is None' if expect
else 'msvc sdk version components definition is not None'
278 self
.assertTrue((comps_def
is not None) == expect
, "{}({}): {}".format(
279 func
.__name
__, repr(vcver
), repr(msg
)
281 for vcver
in Config
.MSVC_VERSION_SUFFIX
.keys():
282 comps_def
= func(vcver
)
283 sdk_list
= WinSDK
.get_msvc_sdk_version_list(vcver
, msvc_uwp_app
=False)
284 for sdk_version
in sdk_list
:
285 comps_def
= func(sdk_version
)
286 self
.assertNotEqual(comps_def
, None, "{}({}) is None".format(
287 func
.__name
__, repr(vcver
)
290 if __name__
== "__main__":