1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
11 from catapult_base
import dependency_manager
12 from catapult_base
import cloud_storage
13 from catapult_base
.dependency_manager
import exceptions
16 class DependencyManagerTest(unittest
.TestCase
):
18 'catapult_base.dependency_manager.DependencyManager._UpdateDependencies')
19 def testInit(self
, update_mock
):
20 self
.assertRaises(ValueError, dependency_manager
.DependencyManager
, None)
21 self
.assertFalse(update_mock
.call_args
)
22 self
.assertRaises(ValueError, dependency_manager
.DependencyManager
,
24 self
.assertFalse(update_mock
.call_args
)
26 dependency_manager
.DependencyManager([])
27 self
.assertFalse(update_mock
.call_args
)
29 dependency_manager
.DependencyManager(['config_file'])
30 update_mock
.called_once_with_args('config_file')
31 update_mock
.reset_mock()
33 dependency_manager
.DependencyManager(
34 ['config_file1', 'config_file2', 'config_file3', 'config_file4'])
35 expected_calls
= [mock
.call('config_file1'), mock
.call('config_file2'),
36 mock
.call('config_file3'), mock
.call('config_file4')]
37 update_mock
.assert_has_calls(expected_calls
, any_order
=True)
38 update_mock
.reset_mock()
41 @mock.patch('os.path')
42 @mock.patch('catapult_base.support_binaries.FindPath')
44 'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
46 'catapult_base.dependency_manager.DependencyManager._CloudStoragePath')
47 @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
48 def testFetchPathUnititializedDependency(
49 self
, local_path_mock
, cs_path_mock
, dep_info_mock
, sb_find_path_mock
,
51 dep_manager
= dependency_manager
.DependencyManager([])
52 self
.assertFalse(local_path_mock
.call_args
)
53 self
.assertFalse(cs_path_mock
.call_args
)
54 self
.assertFalse(sb_find_path_mock
.call_args
)
56 local_path
= 'local_path'
58 local_path_mock
.return_value
= local_path
59 cs_path_mock
.return_value
= cs_path
60 sb_find_path_mock
.return_value
= sb_path
61 dep_info_mock
.return_value
= None
64 with self
.assertRaises(exceptions
.NoPathFoundError
):
65 dep_manager
.FetchPath('dep', 'plat_arch_x86')
66 dep_info_mock
.reset_mock()
68 found_path
= dep_manager
.FetchPath(
69 'dep', 'plat_arch_x86', try_support_binaries
=True)
70 self
.assertEqual(sb_path
, found_path
)
71 self
.assertFalse(local_path_mock
.call_args
)
72 self
.assertFalse(cs_path_mock
.call_args
)
73 dep_info_mock
.assert_called_once_with('dep', 'plat_arch_x86')
74 sb_find_path_mock
.assert_called_once_with('dep', 'arch_x86', 'plat')
75 local_path_mock
.reset_mock()
76 cs_path_mock
.reset_mock()
77 sb_find_path_mock
.reset_mock()
78 dep_info_mock
.reset_mock()
80 # Non-empty lookup dict that doesn't contain the dependency we're looking
82 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
83 'dep2': mock
.MagicMock()}
84 with self
.assertRaises(exceptions
.NoPathFoundError
):
85 dep_manager
.FetchPath('dep', 'plat_arch_x86')
86 dep_info_mock
.reset_mock()
88 found_path
= dep_manager
.FetchPath(
89 'dep', 'plat_arch_x86', try_support_binaries
=True)
90 self
.assertEqual(sb_path
, found_path
)
91 self
.assertFalse(local_path_mock
.call_args
)
92 self
.assertFalse(cs_path_mock
.call_args
)
93 dep_info_mock
.assert_called_once_with('dep', 'plat_arch_x86')
94 sb_find_path_mock
.assert_called_once_with('dep', 'arch_x86', 'plat')
95 local_path_mock
.reset_mock()
96 cs_path_mock
.reset_mock()
97 sb_find_path_mock
.reset_mock()
99 @mock.patch('os.path')
100 @mock.patch('catapult_base.support_binaries.FindPath')
102 'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
104 'catapult_base.dependency_manager.DependencyManager._CloudStoragePath')
105 @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
106 def testFetchPathLocalFile(self
, local_path_mock
, cs_path_mock
, dep_info_mock
,
107 sb_find_path_mock
, path_mock
):
108 dep_manager
= dependency_manager
.DependencyManager([])
109 self
.assertFalse(local_path_mock
.call_args
)
110 self
.assertFalse(cs_path_mock
.call_args
)
111 self
.assertFalse(sb_find_path_mock
.call_args
)
113 local_path
= 'local_path'
115 dep_info
= 'dep_info'
116 local_path_mock
.return_value
= local_path
117 cs_path_mock
.return_value
= cs_path
118 sb_find_path_mock
.return_value
= sb_path
119 # The DependencyInfo returned should be passed through to LocalPath.
120 dep_info_mock
.return_value
= dep_info
123 # Non-empty lookup dict that contains the dependency we're looking for.
125 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
126 'dep2': mock
.MagicMock()}
127 path_mock
.exists
.return_value
= True
128 found_path
= dep_manager
.FetchPath('dep1', 'plat')
130 self
.assertEqual(local_path
, found_path
)
131 local_path_mock
.assert_called_with('dep_info')
132 dep_info_mock
.assert_called_once_with('dep1', 'plat')
133 self
.assertFalse(cs_path_mock
.call_args
)
134 self
.assertFalse(sb_find_path_mock
.call_args
)
135 # If the below assert fails, the ordering assumption that determined the
136 # path_mock return values is incorrect, and should be updated.
137 path_mock
.exists
.assert_called_once_with('local_path')
138 local_path_mock
.reset_mock()
139 cs_path_mock
.reset_mock()
140 sb_find_path_mock
.reset_mock()
141 dep_info_mock
.reset_mock()
144 @mock.patch('os.path')
145 @mock.patch('catapult_base.support_binaries.FindPath')
147 'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
149 'catapult_base.dependency_manager.DependencyManager._CloudStoragePath')
150 @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
151 def testFetchPathRemoteFile(self
, local_path_mock
, cs_path_mock
,
152 dep_info_mock
, sb_find_path_mock
, path_mock
):
153 dep_manager
= dependency_manager
.DependencyManager([])
154 self
.assertFalse(local_path_mock
.call_args
)
155 self
.assertFalse(cs_path_mock
.call_args
)
156 self
.assertFalse(sb_find_path_mock
.call_args
)
157 local_path
= 'local_path'
159 dep_info
= 'dep_info'
160 cs_path_mock
.return_value
= cs_path
161 dep_info_mock
.return_value
= dep_info
163 # Non-empty lookup dict that contains the dependency we're looking for.
164 # Local path doesn't exist, but cloud_storage_path is downloaded.
165 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
166 'dep2': mock
.MagicMock()}
167 path_mock
.exists
.side_effect
= [False, True]
168 local_path_mock
.return_value
= local_path
169 found_path
= dep_manager
.FetchPath('dep1', 'plat')
171 self
.assertEqual(cs_path
, found_path
)
172 local_path_mock
.assert_called_with(dep_info
)
173 dep_info_mock
.assert_called_once_with('dep1', 'plat')
174 cs_path_mock
.assert_called_once_with(dep_info
)
175 self
.assertFalse(sb_find_path_mock
.call_args
)
176 # If the below assert fails, the ordering assumption that determined the
177 # path_mock return values is incorrect, and should be updated.
178 path_mock
.exists
.assert_has_calls([mock
.call(local_path
),
179 mock
.call(cs_path
)], any_order
=False)
180 local_path_mock
.reset_mock()
181 cs_path_mock
.reset_mock()
182 sb_find_path_mock
.reset_mock()
183 dep_info_mock
.reset_mock()
185 # Non-empty lookup dict that contains the dependency we're looking for.
186 # Local path isn't found, but cloud_storage_path is downloaded.
187 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
188 'dep2': mock
.MagicMock()}
189 path_mock
.exists
.side_effect
= [True]
190 local_path_mock
.return_value
= None
191 found_path
= dep_manager
.FetchPath('dep1', 'plat')
193 self
.assertEqual(cs_path
, found_path
)
194 local_path_mock
.assert_called_with(dep_info
)
195 cs_path_mock
.assert_called_once_with(dep_info
)
196 dep_info_mock
.assert_called_once_with('dep1', 'plat')
197 self
.assertFalse(sb_find_path_mock
.call_args
)
198 # If the below assert fails, the ordering assumption that determined the
199 # path_mock return values is incorrect, and should be updated.
200 path_mock
.exists
.assert_has_calls([mock
.call(local_path
),
201 mock
.call(cs_path
)], any_order
=False)
203 @mock.patch('os.path')
204 @mock.patch('catapult_base.support_binaries.FindPath')
206 'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
208 'catapult_base.dependency_manager.DependencyManager._CloudStoragePath')
209 @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
210 def testFetchPathError(self
, local_path_mock
, cs_path_mock
, dep_info_mock
,
211 sb_find_path_mock
, path_mock
):
212 dep_manager
= dependency_manager
.DependencyManager([])
213 self
.assertFalse(local_path_mock
.call_args
)
214 self
.assertFalse(cs_path_mock
.call_args
)
215 self
.assertFalse(sb_find_path_mock
.call_args
)
216 local_path_mock
.return_value
= None
217 cs_path_mock
.return_value
= None
218 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
219 'dep2': mock
.MagicMock()}
220 # Non-empty lookup dict that contains the dependency we're looking for.
221 # Local path doesn't exist, and cloud_storage path wasn't successfully
223 self
.assertRaises(exceptions
.NoPathFoundError
,
224 dep_manager
.FetchPath
, 'dep1', 'plat')
226 cs_path_mock
.side_effect
= cloud_storage
.CredentialsError
227 self
.assertRaises(cloud_storage
.CredentialsError
,
228 dep_manager
.FetchPath
, 'dep1', 'plat')
230 cs_path_mock
.side_effect
= cloud_storage
.CloudStorageError
231 self
.assertRaises(cloud_storage
.CloudStorageError
,
232 dep_manager
.FetchPath
, 'dep1', 'plat')
234 cs_path_mock
.side_effect
= cloud_storage
.PermissionError
235 self
.assertRaises(cloud_storage
.PermissionError
,
236 dep_manager
.FetchPath
, 'dep1', 'plat')
238 @mock.patch('os.path')
239 @mock.patch('catapult_base.support_binaries.FindLocallyBuiltPath')
241 'catapult_base.dependency_manager.DependencyManager._GetDependencyInfo')
242 @mock.patch('catapult_base.dependency_manager.DependencyManager._LocalPath')
243 def testLocalPath(self
, local_path_mock
, dep_info_mock
, sb_find_path_mock
,
245 dep_manager
= dependency_manager
.DependencyManager([])
246 self
.assertFalse(local_path_mock
.call_args
)
247 self
.assertFalse(sb_find_path_mock
.call_args
)
249 local_path
= 'local_path'
250 dep_info
= 'dep_info'
251 local_path_mock
.return_value
= local_path
252 sb_find_path_mock
.return_value
= sb_path
254 # GetDependencyInfo should return None when missing from the lookup dict.
255 dep_info_mock
.return_value
= None
258 with self
.assertRaises(exceptions
.NoPathFoundError
):
259 dep_manager
.LocalPath('dep', 'plat')
260 dep_info_mock
.reset_mock()
262 found_path
= dep_manager
.LocalPath(
263 'dep', 'plat', try_support_binaries
=True)
264 self
.assertEqual(sb_path
, found_path
)
265 self
.assertFalse(local_path_mock
.call_args
)
266 sb_find_path_mock
.assert_called_once_with('dep')
267 dep_info_mock
.assert_called_once_with('dep', 'plat')
268 local_path_mock
.reset_mock()
269 sb_find_path_mock
.reset_mock()
270 dep_info_mock
.reset_mock()
272 # Non-empty lookup dict that doesn't contain the dependency we're looking
274 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
275 'dep2': mock
.MagicMock()}
276 with self
.assertRaises(exceptions
.NoPathFoundError
):
277 dep_manager
.LocalPath('dep', 'plat')
278 dep_info_mock
.reset_mock()
280 found_path
= dep_manager
.LocalPath(
281 'dep', 'plat', try_support_binaries
=True)
282 self
.assertEqual(sb_path
, found_path
)
283 self
.assertFalse(local_path_mock
.call_args
)
284 sb_find_path_mock
.assert_called_once_with('dep')
285 dep_info_mock
.assert_called_once_with('dep', 'plat')
286 local_path_mock
.reset_mock()
287 sb_find_path_mock
.reset_mock()
288 dep_info_mock
.reset_mock()
290 # The DependencyInfo returned should be passed through to LocalPath.
291 dep_info_mock
.return_value
= dep_info
293 # Non-empty lookup dict that contains the dependency we're looking for.
295 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
296 'dep2': mock
.MagicMock()}
297 path_mock
.exists
.return_value
= True
298 found_path
= dep_manager
.LocalPath('dep1', 'plat')
300 self
.assertEqual(local_path
, found_path
)
301 local_path_mock
.assert_called_with('dep_info')
302 self
.assertFalse(sb_find_path_mock
.call_args
)
303 # If the below assert fails, the ordering assumption that determined the
304 # path_mock return values is incorrect, and should be updated.
305 path_mock
.exists
.assert_called_once_with('local_path')
306 dep_info_mock
.assert_called_once_with('dep1', 'plat')
307 local_path_mock
.reset_mock()
308 sb_find_path_mock
.reset_mock()
309 dep_info_mock
.reset_mock()
311 # Non-empty lookup dict that contains the dependency we're looking for.
312 # Local path is found but doesn't exist.
313 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
314 'dep2': mock
.MagicMock()}
315 path_mock
.exists
.return_value
= False
316 local_path_mock
.return_value
= local_path
317 self
.assertRaises(exceptions
.NoPathFoundError
,
318 dep_manager
.LocalPath
, 'dep1', 'plat')
320 # Non-empty lookup dict that contains the dependency we're looking for.
321 # Local path isn't found.
322 dep_manager
._lookup
_dict
= {'dep1': mock
.MagicMock(),
323 'dep2': mock
.MagicMock()}
324 local_path_mock
.return_value
= None
325 self
.assertRaises(exceptions
.NoPathFoundError
,
326 dep_manager
.LocalPath
, 'dep1', 'plat')
328 def testInitialUpdateDependencies(self
):
329 dep_manager
= dependency_manager
.DependencyManager([])
332 dep_manager
._lookup
_dict
= {}
333 base_config_mock
= mock
.MagicMock(spec
=dependency_manager
.BaseConfig
)
334 base_config_mock
.IterDependencyInfo
.return_value
= iter([])
335 dep_manager
._UpdateDependencies
(base_config_mock
)
336 self
.assertFalse(dep_manager
._lookup
_dict
)
338 # One dependency/platform in a BaseConfig.
339 dep_manager
._lookup
_dict
= {}
340 base_config_mock
= mock
.MagicMock(spec
=dependency_manager
.BaseConfig
)
341 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
344 dep_info
.dependency
= dep
345 dep_info
.platform
= plat
346 base_config_mock
.IterDependencyInfo
.return_value
= iter([dep_info
])
347 expected_lookup_dict
= {dep
: {plat
: dep_info
}}
348 dep_manager
._UpdateDependencies
(base_config_mock
)
349 self
.assertEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
350 self
.assertFalse(dep_info
.Update
.called
)
352 # One dependency multiple platforms in a BaseConfig.
353 dep_manager
._lookup
_dict
= {}
354 base_config_mock
= mock
.MagicMock(spec
=dependency_manager
.BaseConfig
)
358 dep_info1
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
359 dep_info1
.dependency
= dep
360 dep_info1
.platform
= plat1
361 dep_info2
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
362 dep_info2
.dependency
= dep
363 dep_info2
.platform
= plat2
364 base_config_mock
.IterDependencyInfo
.return_value
= iter([dep_info1
,
366 expected_lookup_dict
= {dep
: {plat1
: dep_info1
,
368 dep_manager
._UpdateDependencies
(base_config_mock
)
369 self
.assertEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
370 self
.assertFalse(dep_info1
.Update
.called
)
371 self
.assertFalse(dep_info2
.Update
.called
)
373 # Multiple dependencies, multiple platforms in a BaseConfig.
374 dep_manager
._lookup
_dict
= {}
375 base_config_mock
= mock
.MagicMock(spec
=dependency_manager
.BaseConfig
)
380 dep_info1
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
381 dep_info1
.dependency
= dep1
382 dep_info1
.platform
= plat1
383 dep_info2
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
384 dep_info2
.dependency
= dep1
385 dep_info2
.platform
= plat2
386 dep_info3
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
387 dep_info3
.dependency
= dep2
388 dep_info3
.platform
= plat2
389 base_config_mock
.IterDependencyInfo
.return_value
= iter(
390 [dep_info1
, dep_info2
, dep_info3
])
391 expected_lookup_dict
= {dep1
: {plat1
: dep_info1
,
393 dep2
: {plat2
: dep_info3
}}
394 dep_manager
._UpdateDependencies
(base_config_mock
)
395 self
.assertEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
396 self
.assertFalse(dep_info1
.Update
.called
)
397 self
.assertFalse(dep_info2
.Update
.called
)
398 self
.assertFalse(dep_info3
.Update
.called
)
400 def testFollowupUpdateDependenciesNoOverlap(self
):
401 dep_manager
= dependency_manager
.DependencyManager([])
409 dep_info_a
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
410 dep_info_a
.dependency
= dep1
411 dep_info_a
.platform
= plat1
412 dep_info_b
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
413 dep_info_b
.dependency
= dep1
414 dep_info_b
.platform
= plat2
415 dep_info_c
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
416 dep_info_c
.dependency
= dep
417 dep_info_c
.platform
= plat1
419 start_lookup_dict
= {dep
: {plat1
: dep_info_a
,
421 dep1
: {plat1
: dep_info_c
}}
422 base_config_mock
= mock
.MagicMock(spec
=dependency_manager
.BaseConfig
)
425 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
426 base_config_mock
.IterDependencyInfo
.return_value
= iter([])
427 dep_manager
._UpdateDependencies
(base_config_mock
)
428 self
.assertEqual(start_lookup_dict
, dep_manager
._lookup
_dict
)
430 # One dependency/platform in a BaseConfig.
431 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
432 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
433 dep_info
.dependency
= dep3
434 dep_info
.platform
= plat1
435 base_config_mock
.IterDependencyInfo
.return_value
= iter([dep_info
])
436 expected_lookup_dict
= {dep
: {plat1
: dep_info_a
,
438 dep1
: {plat1
: dep_info_c
},
439 dep3
: {plat3
: dep_info
}}
441 dep_manager
._UpdateDependencies
(base_config_mock
)
442 self
.assertItemsEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
443 self
.assertFalse(dep_info
.Update
.called
)
444 self
.assertFalse(dep_info_a
.Update
.called
)
445 self
.assertFalse(dep_info_b
.Update
.called
)
446 self
.assertFalse(dep_info_c
.Update
.called
)
448 # One dependency multiple platforms in a BaseConfig.
449 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
450 dep_info1
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
451 dep_info1
.dependency
= dep2
452 dep_info1
.platform
= plat1
453 dep_info2
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
454 dep_info2
.dependency
= dep2
455 dep_info2
.platform
= plat2
456 base_config_mock
.IterDependencyInfo
.return_value
= iter([dep_info1
,
458 expected_lookup_dict
= {dep
: {plat1
: dep_info_a
,
460 dep1
: {plat1
: dep_info_c
},
461 dep2
: {plat1
: dep_info1
,
463 dep_manager
._UpdateDependencies
(base_config_mock
)
464 self
.assertEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
465 self
.assertFalse(dep_info1
.Update
.called
)
466 self
.assertFalse(dep_info2
.Update
.called
)
467 self
.assertFalse(dep_info_a
.Update
.called
)
468 self
.assertFalse(dep_info_b
.Update
.called
)
469 self
.assertFalse(dep_info_c
.Update
.called
)
471 # Multiple dependencies, multiple platforms in a BaseConfig.
472 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
476 dep_info1
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
477 dep_info1
.dependency
= dep2
478 dep_info1
.platform
= plat1
479 dep_info2
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
480 dep_info2
.dependency
= dep2
481 dep_info2
.platform
= plat2
482 dep_info3
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
483 dep_info3
.dependency
= dep3
484 dep_info3
.platform
= plat2
485 base_config_mock
.IterDependencyInfo
.return_value
= iter(
486 [dep_info1
, dep_info2
, dep_info3
])
487 expected_lookup_dict
= {dep
: {plat1
: dep_info_a
,
489 dep1
: {plat1
: dep_info_c
},
490 dep2
: {plat1
: dep_info1
,
492 dep3
: {plat2
: dep_info3
}}
493 dep_manager
._UpdateDependencies
(base_config_mock
)
494 self
.assertEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
495 self
.assertFalse(dep_info1
.Update
.called
)
496 self
.assertFalse(dep_info2
.Update
.called
)
497 self
.assertFalse(dep_info3
.Update
.called
)
498 self
.assertFalse(dep_info_a
.Update
.called
)
499 self
.assertFalse(dep_info_b
.Update
.called
)
500 self
.assertFalse(dep_info_c
.Update
.called
)
502 # Ensure the testing data wasn't corrupted.
503 self
.assertEqual(start_lookup_dict
,
504 {dep
: {plat1
: dep_info_a
,
506 dep1
: {plat1
: dep_info_c
}})
508 def testFollowupUpdateDependenciesWithCollisions(self
):
509 dep_manager
= dependency_manager
.DependencyManager([])
515 dep_info_a
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
516 dep_info_a
.dependency
= dep1
517 dep_info_a
.platform
= plat1
518 dep_info_b
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
519 dep_info_b
.dependency
= dep1
520 dep_info_b
.platform
= plat2
521 dep_info_c
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
522 dep_info_c
.dependency
= dep
523 dep_info_c
.platform
= plat1
525 start_lookup_dict
= {dep
: {plat1
: dep_info_a
,
527 dep1
: {plat1
: dep_info_c
}}
528 base_config_mock
= mock
.MagicMock(spec
=dependency_manager
.BaseConfig
)
530 # One dependency/platform.
531 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
532 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
533 dep_info
.dependency
= dep
534 dep_info
.platform
= plat1
535 base_config_mock
.IterDependencyInfo
.return_value
= iter([dep_info
])
536 expected_lookup_dict
= {dep
: {plat1
: dep_info_a
,
538 dep1
: {plat1
: dep_info_c
}}
540 dep_manager
._UpdateDependencies
(base_config_mock
)
541 self
.assertItemsEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
542 dep_info_a
.Update
.assert_called_once_with(dep_info
)
543 self
.assertFalse(dep_info
.Update
.called
)
544 self
.assertFalse(dep_info_b
.Update
.called
)
545 self
.assertFalse(dep_info_c
.Update
.called
)
546 dep_info_a
.reset_mock()
547 dep_info_b
.reset_mock()
548 dep_info_c
.reset_mock()
550 # One dependency multiple platforms in a BaseConfig.
551 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
552 dep_info1
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
553 dep_info1
.dependency
= dep1
554 dep_info1
.platform
= plat1
555 dep_info2
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
556 dep_info2
.dependency
= dep2
557 dep_info2
.platform
= plat2
558 base_config_mock
.IterDependencyInfo
.return_value
= iter([dep_info1
,
560 expected_lookup_dict
= {dep
: {plat1
: dep_info_a
,
562 dep1
: {plat1
: dep_info_c
},
563 dep2
: {plat2
: dep_info2
}}
564 dep_manager
._UpdateDependencies
(base_config_mock
)
565 self
.assertEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
566 self
.assertFalse(dep_info1
.Update
.called
)
567 self
.assertFalse(dep_info2
.Update
.called
)
568 self
.assertFalse(dep_info_a
.Update
.called
)
569 self
.assertFalse(dep_info_b
.Update
.called
)
570 dep_info_c
.Update
.assert_called_once_with(dep_info1
)
571 dep_info_a
.reset_mock()
572 dep_info_b
.reset_mock()
573 dep_info_c
.reset_mock()
575 # Multiple dependencies, multiple platforms in a BaseConfig.
576 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
580 dep_info1
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
581 dep_info1
.dependency
= dep
582 dep_info1
.platform
= plat1
583 dep_info2
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
584 dep_info2
.dependency
= dep1
585 dep_info2
.platform
= plat1
586 dep_info3
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
587 dep_info3
.dependency
= dep2
588 dep_info3
.platform
= plat2
589 base_config_mock
.IterDependencyInfo
.return_value
= iter(
590 [dep_info1
, dep_info2
, dep_info3
])
591 expected_lookup_dict
= {dep
: {plat1
: dep_info_a
,
593 dep1
: {plat1
: dep_info_c
},
594 dep2
: {plat2
: dep_info3
}}
595 dep_manager
._UpdateDependencies
(base_config_mock
)
596 self
.assertEqual(expected_lookup_dict
, dep_manager
._lookup
_dict
)
597 self
.assertFalse(dep_info1
.Update
.called
)
598 self
.assertFalse(dep_info2
.Update
.called
)
599 self
.assertFalse(dep_info3
.Update
.called
)
600 self
.assertFalse(dep_info_b
.Update
.called
)
601 dep_info_a
.Update
.assert_called_once_with(dep_info1
)
602 dep_info_c
.Update
.assert_called_once_with(dep_info2
)
605 dep_manager
._lookup
_dict
= start_lookup_dict
.copy()
606 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
607 dep_info
.dependency
= dep
608 dep_info
.platform
= plat1
609 base_config_mock
.IterDependencyInfo
.return_value
= iter([dep_info
])
610 dep_info_a
.Update
.side_effect
= ValueError
611 self
.assertRaises(ValueError,
612 dep_manager
._UpdateDependencies
, base_config_mock
)
614 # Ensure the testing data wasn't corrupted.
615 self
.assertEqual(start_lookup_dict
,
616 {dep
: {plat1
: dep_info_a
,
618 dep1
: {plat1
: dep_info_c
}})
620 def testGetDependencyInfo(self
):
621 dep_manager
= dependency_manager
.DependencyManager([])
622 self
.assertFalse(dep_manager
._lookup
_dict
)
624 # No dependencies in the dependency manager.
625 self
.assertEqual(None, dep_manager
._GetDependencyInfo
('missing_dep',
628 dep_manager
._lookup
_dict
= {'dep1': {'plat1': 'dep_info11',
629 'plat2': 'dep_info12',
630 'plat3': 'dep_info13'},
631 'dep2': {'plat1': 'dep_info11',
632 'plat2': 'dep_info21',
633 'plat3': 'dep_info23',
634 'default': 'dep_info2d'},
635 'dep3': {'plat1': 'dep_info31',
636 'plat2': 'dep_info32',
637 'default': 'dep_info3d'}}
638 # Dependency not in the dependency manager.
639 self
.assertEqual(None, dep_manager
._GetDependencyInfo
(
640 'missing_dep', 'missing_plat'))
641 # Dependency in the dependency manager, but not the platform. No default.
642 self
.assertEqual(None, dep_manager
._GetDependencyInfo
(
643 'dep1', 'missing_plat'))
644 # Dependency in the dependency manager, but not the platform, but a default
646 self
.assertEqual('dep_info2d', dep_manager
._GetDependencyInfo
(
647 'dep2', 'missing_plat'))
648 # Dependency and platform in the dependency manager. A default exists.
649 self
.assertEqual('dep_info23', dep_manager
._GetDependencyInfo
(
651 # Dependency and platform in the dependency manager. No default exists.
652 self
.assertEqual('dep_info12', dep_manager
._GetDependencyInfo
(
656 @mock.patch('os.path.exists')
657 def testLocalPathHelper(self
, exists_mock
):
658 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
660 # There is no local path for the given dependency.
661 dep_info
.local_paths
= {}
662 self
.assertEqual(None,
663 dependency_manager
.DependencyManager
._LocalPath
(dep_info
))
665 # There is a local path for the given dependency, but it doesn't exist.
666 exists_mock
.side_effect
= [False]
667 dep_info
.local_paths
= {'local_path0'}
668 self
.assertEqual(None,
669 dependency_manager
.DependencyManager
._LocalPath
(dep_info
))
670 exists_mock
.assert_called_once_with('local_path0')
671 exists_mock
.reset_mock()
673 # There is a local path for the given dependency, and it does exist.
674 exists_mock
.side_effect
= [True]
675 dep_info
.local_paths
= {'local_path0'}
676 self
.assertEqual('local_path0',
677 dependency_manager
.DependencyManager
._LocalPath
(dep_info
))
678 exists_mock
.assert_called_once_with('local_path0')
679 exists_mock
.reset_mock()
681 # There are multiple local paths for the given dependency, and the first one
683 exists_mock
.side_effect
= [True]
684 dep_info
.local_paths
= {'local_path0', 'local_path1', 'local_path2'}
685 self
.assertEqual('local_path0',
686 dependency_manager
.DependencyManager
._LocalPath
(dep_info
))
687 exists_mock
.assert_called_once_with('local_path0')
688 exists_mock
.reset_mock()
690 # There are multiple local paths for the given dependency, and the first one
691 # doesn't exist but the second one does.
692 exists_mock
.side_effect
= [False, True]
693 dep_info
.local_paths
= {'local_path0', 'local_path1', 'local_path2'}
694 self
.assertEqual('local_path1',
695 dependency_manager
.DependencyManager
._LocalPath
(dep_info
))
696 expected_calls
= [mock
.call('local_path0'), mock
.call('local_path1')]
697 exists_mock
.assert_has_calls(expected_calls
, any_order
=False)
698 exists_mock
.reset_mock()
700 # There are multiple local paths for the given dependency, and the first and
701 # second ones don't exist but the third one does.
702 exists_mock
.side_effect
= [False, False, True]
703 dep_info
.local_paths
= {'local_path0', 'local_path1', 'local_path2'}
704 self
.assertEqual('local_path2',
705 dependency_manager
.DependencyManager
._LocalPath
(dep_info
))
706 expected_calls
= [mock
.call('local_path0'), mock
.call('local_path1'),
707 mock
.call('local_path2')]
708 exists_mock
.assert_has_calls(expected_calls
, any_order
=False)
709 exists_mock
.reset_mock()
711 # There are multiple local paths for the given dependency, but none of them
713 exists_mock
.side_effect
= [False, False, False]
714 dep_info
.local_paths
= {'local_path0', 'local_path1', 'local_path2'}
715 self
.assertEqual(None,
716 dependency_manager
.DependencyManager
._LocalPath
(dep_info
))
717 expected_calls
= [mock
.call('local_path0'), mock
.call('local_path1'),
718 mock
.call('local_path2')]
719 exists_mock
.assert_has_calls(expected_calls
, any_order
=False)
720 exists_mock
.reset_mock()
723 @mock.patch('os.path.exists')
724 @mock.patch('os.chmod')
726 'catapult_base.cloud_storage.GetIfHashChanged')
727 def testCloudStoragePathMissingData(
728 self
, cs_get_mock
, chmod_mock
, exists_mock
):
729 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
730 cs_remote_path
= 'cs_remote_path'
732 cs_bucket
= 'cs_bucket'
733 download_path
= 'download_path'
735 # No dependency info.
737 None, dependency_manager
.DependencyManager
._CloudStoragePath
(None))
739 # There is no cloud_storage information for the dependency.
740 dep_info
.cs_remote_path
= None
741 dep_info
.cs_hash
= None
742 dep_info
.cs_bucket
= None
743 dep_info
.download_path
= None
745 None, dependency_manager
.DependencyManager
._CloudStoragePath
(dep_info
))
747 # There is no cloud_storage remote_path the dependency.
748 dep_info
.cs_remote_path
= None
749 dep_info
.cs_hash
= cs_hash
750 dep_info
.cs_bucket
= cs_bucket
751 dep_info
.download_path
= download_path
753 None, dependency_manager
.DependencyManager
._CloudStoragePath
(dep_info
))
755 # There is no cloud_storage hash for the dependency.
756 dep_info
.cs_remote_path
= cs_remote_path
757 dep_info
.cs_hash
= None
758 dep_info
.cs_bucket
= cs_bucket
759 dep_info
.download_path
= download_path
761 None, dependency_manager
.DependencyManager
._CloudStoragePath
(dep_info
))
763 # There is no cloud_storage bucket for the dependency.
764 dep_info
.cs_remote_path
= cs_remote_path
765 dep_info
.cs_hash
= cs_hash
766 dep_info
.cs_bucket
= None
767 dep_info
.download_path
= download_path
769 None, dependency_manager
.DependencyManager
._CloudStoragePath
(dep_info
))
771 # There is no download_path for the dependency.
772 dep_info
.cs_remote_path
= cs_remote_path
773 dep_info
.cs_hash
= cs_hash
774 dep_info
.cs_bucket
= cs_bucket
775 dep_info
.download_path
= None
777 None, dependency_manager
.DependencyManager
._CloudStoragePath
(dep_info
))
779 @mock.patch('os.path.exists')
780 @mock.patch('os.chmod')
782 'catapult_base.cloud_storage.GetIfHashChanged')
783 def testCloudStoragePath(self
, cs_get_mock
, chmod_mock
, exists_mock
):
784 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
785 cs_remote_path
= 'cs_remote_path'
787 cs_bucket
= 'cs_bucket'
788 download_path
= 'download_path'
790 # All of the needed information is given, and the downloaded path exists
791 # after calling cloud storage.
792 dep_info
.cs_remote_path
= cs_remote_path
793 dep_info
.cs_hash
= cs_hash
794 dep_info
.cs_bucket
= cs_bucket
795 dep_info
.download_path
= download_path
796 exists_mock
.return_value
= True
798 os
.path
.abspath(download_path
),
799 dependency_manager
.DependencyManager
._CloudStoragePath
(dep_info
))
800 chmod_mock
.assert_called_once_with(
802 stat
.S_IRUSR | stat
.S_IWUSR | stat
.S_IXUSR | stat
.S_IRGRP
)
804 # All of the needed information is given, but the downloaded path doesn't
805 # exists after calling cloud storage.
806 dep_info
.cs_remote_path
= cs_remote_path
807 dep_info
.cs_hash
= cs_hash
808 dep_info
.cs_bucket
= cs_bucket
809 dep_info
.download_path
= download_path
810 exists_mock
.return_value
= False
812 'catapult_base.dependency_manager.dependency_manager.os.makedirs'):
814 exceptions
.FileNotFoundError
,
815 dependency_manager
.DependencyManager
._CloudStoragePath
, dep_info
)
816 exists_mock
.assert_called_with(download_path
)
818 @mock.patch('os.path.exists')
820 'catapult_base.cloud_storage.GetIfHashChanged')
821 def testCloudStoragePathCloudStorageErrors(self
, cs_get_mock
, exists_mock
):
822 dep_info
= mock
.MagicMock(spec
=dependency_manager
.DependencyInfo
)
823 dep_info
.download_path
= 'download_path'
825 cs_get_mock
.side_effect
= cloud_storage
.CloudStorageError
827 cloud_storage
.CloudStorageError
,
828 dependency_manager
.DependencyManager
._CloudStoragePath
, dep_info
)
830 cs_get_mock
.side_effect
= cloud_storage
.ServerError
832 cloud_storage
.ServerError
,
833 dependency_manager
.DependencyManager
._CloudStoragePath
, dep_info
)
835 cs_get_mock
.side_effect
= cloud_storage
.NotFoundError
837 cloud_storage
.NotFoundError
,
838 dependency_manager
.DependencyManager
._CloudStoragePath
, dep_info
)
840 cs_get_mock
.side_effect
= cloud_storage
.PermissionError
842 cloud_storage
.PermissionError
,
843 dependency_manager
.DependencyManager
._CloudStoragePath
, dep_info
)
845 cs_get_mock
.side_effect
= cloud_storage
.CredentialsError
847 cloud_storage
.CredentialsError
,
848 dependency_manager
.DependencyManager
._CloudStoragePath
, dep_info
)