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. 4 5 # pylint: disable=unused-argument 6 7 import os 8 import unittest 9 10 from py_utils import cloud_storage 11 import mock 12 from pyfakefs import fake_filesystem_unittest 13 from pyfakefs import fake_filesystem 14 15 import dependency_manager 16 from dependency_manager import uploader 17 18 19 class BaseConfigCreationAndUpdateUnittests(fake_filesystem_unittest.TestCase): 20 def setUp(self): 21 self.addTypeEqualityFunc(uploader.CloudStorageUploader, 22 uploader.CloudStorageUploader.__eq__) 23 self.setUpPyfakefs() 24 self.dependencies = { 25 'dep1': {'cloud_storage_bucket': 'bucket1', 26 'cloud_storage_base_folder': 'dependencies_folder', 27 'file_info': { 28 'plat1': { 29 'cloud_storage_hash': 'hash11', 30 'download_path': '../../relative/dep1/path1'}, 31 'plat2': { 32 'cloud_storage_hash': 'hash12', 33 'download_path': '../../relative/dep1/path2'}}}, 34 'dep2': {'cloud_storage_bucket': 'bucket2', 35 'file_info': { 36 'plat1': { 37 'cloud_storage_hash': 'hash21', 38 'download_path': '../../relative/dep2/path1'}, 39 'plat2': { 40 'cloud_storage_hash': 'hash22', 41 'download_path': '../../relative/dep2/path2'}}}} 42 43 self.expected_file_lines = [ 44 # pylint: disable=bad-continuation 45 '{', '"config_type": "BaseConfig",', '"dependencies": {', 46 '"dep1": {', '"cloud_storage_base_folder": "dependencies_folder",', 47 '"cloud_storage_bucket": "bucket1",', '"file_info": {', 48 '"plat1": {', '"cloud_storage_hash": "hash11",', 49 '"download_path": "../../relative/dep1/path1"', '},', 50 '"plat2": {', '"cloud_storage_hash": "hash12",', 51 '"download_path": "../../relative/dep1/path2"', '}', '}', '},', 52 '"dep2": {', '"cloud_storage_bucket": "bucket2",', '"file_info": {', 53 '"plat1": {', '"cloud_storage_hash": "hash21",', 54 '"download_path": "../../relative/dep2/path1"', '},', 55 '"plat2": {', '"cloud_storage_hash": "hash22",', 56 '"download_path": "../../relative/dep2/path2"', '}', '}', '}', 57 '}', '}'] 58 59 self.file_path = os.path.abspath(os.path.join( 60 'path', 'to', 'config', 'file')) 61 62 self.new_dep_path = 'path/to/new/dep' 63 self.fs.CreateFile(self.new_dep_path) 64 self.new_dep_hash = 'A23B56B7F23E798601F' 65 self.new_dependencies = { 66 'dep1': {'cloud_storage_bucket': 'bucket1', 67 'cloud_storage_base_folder': 'dependencies_folder', 68 'file_info': { 69 'plat1': { 70 'cloud_storage_hash': 'hash11', 71 'download_path': '../../relative/dep1/path1'}, 72 'plat2': { 73 'cloud_storage_hash': self.new_dep_hash, 74 'download_path': '../../relative/dep1/path2'}}}, 75 'dep2': {'cloud_storage_bucket': 'bucket2', 76 'file_info': { 77 'plat1': { 78 'cloud_storage_hash': 'hash21', 79 'download_path': '../../relative/dep2/path1'}, 80 'plat2': { 81 'cloud_storage_hash': 'hash22', 82 'download_path': '../../relative/dep2/path2'}}}} 83 self.new_bucket = 'bucket1' 84 self.new_remote_path = 'dependencies_folder/dep1_%s' % self.new_dep_hash 85 self.new_pending_upload = uploader.CloudStorageUploader( 86 self.new_bucket, self.new_remote_path, self.new_dep_path) 87 self.expected_new_backup_path = '.'.join([self.new_remote_path, 'old']) 88 self.new_expected_file_lines = [ 89 # pylint: disable=bad-continuation 90 '{', '"config_type": "BaseConfig",', '"dependencies": {', 91 '"dep1": {', '"cloud_storage_base_folder": "dependencies_folder",', 92 '"cloud_storage_bucket": "bucket1",', '"file_info": {', 93 '"plat1": {', '"cloud_storage_hash": "hash11",', 94 '"download_path": "../../relative/dep1/path1"', '},', 95 '"plat2": {', '"cloud_storage_hash": "%s",' % self.new_dep_hash, 96 '"download_path": "../../relative/dep1/path2"', '}', '}', '},', 97 '"dep2": {', '"cloud_storage_bucket": "bucket2",', '"file_info": {', 98 '"plat1": {', '"cloud_storage_hash": "hash21",', 99 '"download_path": "../../relative/dep2/path1"', '},', 100 '"plat2": {', '"cloud_storage_hash": "hash22",', 101 '"download_path": "../../relative/dep2/path2"', '}', '}', '}', 102 '}', '}'] 103 104 self.final_dep_path = 'path/to/final/dep' 105 self.fs.CreateFile(self.final_dep_path) 106 self.final_dep_hash = 'B34662F23B56B7F98601F' 107 self.final_bucket = 'bucket2' 108 self.final_remote_path = 'dep1_%s' % self.final_dep_hash 109 self.final_pending_upload = uploader.CloudStorageUploader( 110 self.final_bucket, self.final_remote_path, self.final_dep_path) 111 self.expected_final_backup_path = '.'.join([self.final_remote_path, 112 'old']) 113 self.final_dependencies = { 114 'dep1': {'cloud_storage_bucket': 'bucket1', 115 'cloud_storage_base_folder': 'dependencies_folder', 116 'file_info': { 117 'plat1': { 118 'cloud_storage_hash': 'hash11', 119 'download_path': '../../relative/dep1/path1'}, 120 'plat2': { 121 'cloud_storage_hash': self.new_dep_hash, 122 'download_path': '../../relative/dep1/path2'}}}, 123 'dep2': {'cloud_storage_bucket': 'bucket2', 124 'file_info': { 125 'plat1': { 126 'cloud_storage_hash': self.final_dep_hash, 127 'download_path': '../../relative/dep2/path1'}, 128 'plat2': { 129 'cloud_storage_hash': 'hash22', 130 'download_path': '../../relative/dep2/path2'}}}} 131 self.final_expected_file_lines = [ 132 # pylint: disable=bad-continuation 133 '{', '"config_type": "BaseConfig",', '"dependencies": {', 134 '"dep1": {', '"cloud_storage_base_folder": "dependencies_folder",', 135 '"cloud_storage_bucket": "bucket1",', '"file_info": {', 136 '"plat1": {', '"cloud_storage_hash": "hash11",', 137 '"download_path": "../../relative/dep1/path1"', '},', 138 '"plat2": {', '"cloud_storage_hash": "%s",' % self.new_dep_hash, 139 '"download_path": "../../relative/dep1/path2"', '}', '}', '},', 140 '"dep2": {', '"cloud_storage_bucket": "bucket2",', '"file_info": {', 141 '"plat1": {', '"cloud_storage_hash": "%s",' % self.final_dep_hash, 142 '"download_path": "../../relative/dep2/path1"', '},', 143 '"plat2": {', '"cloud_storage_hash": "hash22",', 144 '"download_path": "../../relative/dep2/path2"', '}', '}', '}', 145 '}', '}'] 146 147 148 def tearDown(self): 149 self.tearDownPyfakefs() 150 151 # Init is not meant to be overridden, so we should be mocking the 152 # base_config's json module, even in subclasses. 153 def testCreateEmptyConfig(self): 154 expected_file_lines = ['{', 155 '"config_type": "BaseConfig",', 156 '"dependencies": {}', 157 '}'] 158 config = dependency_manager.BaseConfig(self.file_path, writable=True) 159 160 file_module = fake_filesystem.FakeFileOpen(self.fs) 161 for line in file_module(self.file_path): 162 self.assertEqual(expected_file_lines.pop(0), line.strip()) 163 self.fs.CloseOpenFile(file_module(self.file_path)) 164 self.assertEqual({}, config._config_data) 165 self.assertEqual(self.file_path, config._config_path) 166 167 def testCreateEmptyConfigError(self): 168 self.assertRaises(dependency_manager.EmptyConfigError, 169 dependency_manager.BaseConfig, self.file_path) 170 171 def testCloudStorageRemotePath(self): 172 dependency = 'dep_name' 173 cs_hash = self.new_dep_hash 174 cs_base_folder = 'dependency_remote_folder' 175 expected_remote_path = '%s/%s_%s' % (cs_base_folder, dependency, cs_hash) 176 remote_path = dependency_manager.BaseConfig._CloudStorageRemotePath( 177 dependency, cs_hash, cs_base_folder) 178 self.assertEqual(expected_remote_path, remote_path) 179 180 cs_base_folder = 'dependency_remote_folder' 181 expected_remote_path = '%s_%s' % (dependency, cs_hash) 182 remote_path = dependency_manager.BaseConfig._CloudStorageRemotePath( 183 dependency, cs_hash, cs_base_folder) 184 185 def testGetEmptyJsonDict(self): 186 expected_json_dict = {'config_type': 'BaseConfig', 187 'dependencies': {}} 188 json_dict = dependency_manager.BaseConfig._GetJsonDict() 189 self.assertEqual(expected_json_dict, json_dict) 190 191 def testGetNonEmptyJsonDict(self): 192 expected_json_dict = {"config_type": "BaseConfig", 193 "dependencies": self.dependencies} 194 json_dict = dependency_manager.BaseConfig._GetJsonDict(self.dependencies) 195 self.assertEqual(expected_json_dict, json_dict) 196 197 def testWriteEmptyConfigToFile(self): 198 expected_file_lines = ['{', '"config_type": "BaseConfig",', 199 '"dependencies": {}', '}'] 200 self.assertFalse(os.path.exists(self.file_path)) 201 dependency_manager.BaseConfig._WriteConfigToFile(self.file_path) 202 self.assertTrue(os.path.exists(self.file_path)) 203 file_module = fake_filesystem.FakeFileOpen(self.fs) 204 for line in file_module(self.file_path): 205 self.assertEqual(expected_file_lines.pop(0), line.strip()) 206 self.fs.CloseOpenFile(file_module(self.file_path)) 207 208 def testWriteNonEmptyConfigToFile(self): 209 self.assertFalse(os.path.exists(self.file_path)) 210 dependency_manager.BaseConfig._WriteConfigToFile(self.file_path, 211 self.dependencies) 212 self.assertTrue(os.path.exists(self.file_path)) 213 expected_file_lines = list(self.expected_file_lines) 214 file_module = fake_filesystem.FakeFileOpen(self.fs) 215 for line in file_module(self.file_path): 216 self.assertEqual(expected_file_lines.pop(0), line.strip()) 217 self.fs.CloseOpenFile(file_module(self.file_path)) 218 219 @mock.patch('dependency_manager.uploader.cloud_storage') 220 def testExecuteUpdateJobsNoOp(self, uploader_cs_mock): 221 self.fs.CreateFile(self.file_path, 222 contents='\n'.join(self.expected_file_lines)) 223 config = dependency_manager.BaseConfig(self.file_path, writable=True) 224 225 self.assertFalse(config.ExecuteUpdateJobs()) 226 self.assertFalse(config._IsDirty()) 227 self.assertFalse(config._pending_uploads) 228 self.assertEqual(self.dependencies, config._config_data) 229 file_module = fake_filesystem.FakeFileOpen(self.fs) 230 expected_file_lines = list(self.expected_file_lines) 231 for line in file_module(self.file_path): 232 self.assertEqual(expected_file_lines.pop(0), line.strip()) 233 self.fs.CloseOpenFile(file_module(self.file_path)) 234 235 @mock.patch('dependency_manager.uploader.cloud_storage') 236 def testExecuteUpdateJobsFailureOnInsertNoCSCollision( 237 self, uploader_cs_mock): 238 uploader_cs_mock.Exists.return_value = False 239 uploader_cs_mock.Insert.side_effect = cloud_storage.CloudStorageError 240 self.fs.CreateFile(self.file_path, 241 contents='\n'.join(self.expected_file_lines)) 242 config = dependency_manager.BaseConfig(self.file_path, writable=True) 243 config._config_data = self.new_dependencies.copy() 244 config._is_dirty = True 245 config._pending_uploads = [self.new_pending_upload] 246 self.assertEqual(self.new_dependencies, config._config_data) 247 self.assertTrue(config._is_dirty) 248 self.assertEqual(1, len(config._pending_uploads)) 249 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 250 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 251 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 252 self.new_dep_path)] 253 expected_copy_calls = [] 254 expected_delete_calls = [] 255 256 self.assertRaises(cloud_storage.CloudStorageError, 257 config.ExecuteUpdateJobs) 258 self.assertTrue(config._is_dirty) 259 self.assertEqual(1, len(config._pending_uploads)) 260 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 261 self.assertEqual(self.new_dependencies, config._config_data) 262 file_module = fake_filesystem.FakeFileOpen(self.fs) 263 expected_file_lines = list(self.expected_file_lines) 264 for line in file_module(self.file_path): 265 self.assertEqual(expected_file_lines.pop(0), line.strip()) 266 self.fs.CloseOpenFile(file_module(self.file_path)) 267 self.assertEqual(1, len(config._pending_uploads)) 268 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 269 self.assertEqual(expected_insert_calls, 270 uploader_cs_mock.Insert.call_args_list) 271 self.assertEqual(expected_exists_calls, 272 uploader_cs_mock.Exists.call_args_list) 273 self.assertEqual(expected_copy_calls, 274 uploader_cs_mock.Copy.call_args_list) 275 self.assertEqual(expected_delete_calls, 276 uploader_cs_mock.Delete.call_args_list) 277 278 @mock.patch('dependency_manager.uploader.cloud_storage') 279 def testExecuteUpdateJobsFailureOnInsertCSCollisionForce( 280 self, uploader_cs_mock): 281 uploader_cs_mock.Exists.return_value = True 282 uploader_cs_mock.Insert.side_effect = cloud_storage.CloudStorageError 283 self.fs.CreateFile(self.file_path, 284 contents='\n'.join(self.expected_file_lines)) 285 config = dependency_manager.BaseConfig(self.file_path, writable=True) 286 config._config_data = self.new_dependencies.copy() 287 config._is_dirty = True 288 config._pending_uploads = [self.new_pending_upload] 289 self.assertEqual(self.new_dependencies, config._config_data) 290 self.assertTrue(config._is_dirty) 291 self.assertEqual(1, len(config._pending_uploads)) 292 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 293 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 294 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 295 self.new_dep_path)] 296 expected_copy_calls = [mock.call(self.new_bucket, self.new_bucket, 297 self.new_remote_path, 298 self.expected_new_backup_path), 299 mock.call(self.new_bucket, self.new_bucket, 300 self.expected_new_backup_path, 301 self.new_remote_path)] 302 expected_delete_calls = [] 303 304 self.assertRaises(cloud_storage.CloudStorageError, 305 config.ExecuteUpdateJobs, force=True) 306 self.assertTrue(config._is_dirty) 307 self.assertEqual(1, len(config._pending_uploads)) 308 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 309 self.assertEqual(self.new_dependencies, config._config_data) 310 file_module = fake_filesystem.FakeFileOpen(self.fs) 311 expected_file_lines = list(self.expected_file_lines) 312 for line in file_module(self.file_path): 313 self.assertEqual(expected_file_lines.pop(0), line.strip()) 314 self.fs.CloseOpenFile(file_module(self.file_path)) 315 self.assertEqual(1, len(config._pending_uploads)) 316 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 317 self.assertEqual(expected_insert_calls, 318 uploader_cs_mock.Insert.call_args_list) 319 self.assertEqual(expected_exists_calls, 320 uploader_cs_mock.Exists.call_args_list) 321 self.assertEqual(expected_copy_calls, 322 uploader_cs_mock.Copy.call_args_list) 323 self.assertEqual(expected_delete_calls, 324 uploader_cs_mock.Delete.call_args_list) 325 326 @mock.patch('dependency_manager.uploader.cloud_storage') 327 def testExecuteUpdateJobsFailureOnInsertCSCollisionNoForce( 328 self, uploader_cs_mock): 329 uploader_cs_mock.Exists.return_value = True 330 uploader_cs_mock.Insert.side_effect = cloud_storage.CloudStorageError 331 self.fs.CreateFile(self.file_path, 332 contents='\n'.join(self.expected_file_lines)) 333 config = dependency_manager.BaseConfig(self.file_path, writable=True) 334 config._config_data = self.new_dependencies.copy() 335 config._is_dirty = True 336 config._pending_uploads = [self.new_pending_upload] 337 self.assertEqual(self.new_dependencies, config._config_data) 338 self.assertTrue(config._is_dirty) 339 self.assertEqual(1, len(config._pending_uploads)) 340 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 341 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 342 expected_insert_calls = [] 343 expected_copy_calls = [] 344 expected_delete_calls = [] 345 346 self.assertRaises(cloud_storage.CloudStorageError, 347 config.ExecuteUpdateJobs) 348 self.assertTrue(config._is_dirty) 349 self.assertEqual(1, len(config._pending_uploads)) 350 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 351 self.assertEqual(self.new_dependencies, config._config_data) 352 file_module = fake_filesystem.FakeFileOpen(self.fs) 353 expected_file_lines = list(self.expected_file_lines) 354 for line in file_module(self.file_path): 355 self.assertEqual(expected_file_lines.pop(0), line.strip()) 356 self.fs.CloseOpenFile(file_module(self.file_path)) 357 self.assertEqual(1, len(config._pending_uploads)) 358 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 359 self.assertEqual(expected_insert_calls, 360 uploader_cs_mock.Insert.call_args_list) 361 self.assertEqual(expected_exists_calls, 362 uploader_cs_mock.Exists.call_args_list) 363 self.assertEqual(expected_copy_calls, 364 uploader_cs_mock.Copy.call_args_list) 365 self.assertEqual(expected_delete_calls, 366 uploader_cs_mock.Delete.call_args_list) 367 368 @mock.patch('dependency_manager.uploader.cloud_storage') 369 def testExecuteUpdateJobsFailureOnCopy( 370 self, uploader_cs_mock): 371 uploader_cs_mock.Exists.return_value = True 372 uploader_cs_mock.Copy.side_effect = cloud_storage.CloudStorageError 373 self.fs.CreateFile(self.file_path, 374 contents='\n'.join(self.expected_file_lines)) 375 config = dependency_manager.BaseConfig(self.file_path, writable=True) 376 config._config_data = self.new_dependencies.copy() 377 config._is_dirty = True 378 config._pending_uploads = [self.new_pending_upload] 379 self.assertEqual(self.new_dependencies, config._config_data) 380 self.assertTrue(config._is_dirty) 381 self.assertEqual(1, len(config._pending_uploads)) 382 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 383 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 384 expected_insert_calls = [] 385 expected_copy_calls = [mock.call(self.new_bucket, self.new_bucket, 386 self.new_remote_path, 387 self.expected_new_backup_path)] 388 expected_delete_calls = [] 389 390 self.assertRaises(cloud_storage.CloudStorageError, 391 config.ExecuteUpdateJobs, force=True) 392 self.assertTrue(config._is_dirty) 393 self.assertEqual(1, len(config._pending_uploads)) 394 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 395 self.assertEqual(self.new_dependencies, config._config_data) 396 file_module = fake_filesystem.FakeFileOpen(self.fs) 397 expected_file_lines = list(self.expected_file_lines) 398 for line in file_module(self.file_path): 399 self.assertEqual(expected_file_lines.pop(0), line.strip()) 400 self.fs.CloseOpenFile(file_module(self.file_path)) 401 self.assertEqual(1, len(config._pending_uploads)) 402 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 403 self.assertEqual(expected_insert_calls, 404 uploader_cs_mock.Insert.call_args_list) 405 self.assertEqual(expected_exists_calls, 406 uploader_cs_mock.Exists.call_args_list) 407 self.assertEqual(expected_copy_calls, 408 uploader_cs_mock.Copy.call_args_list) 409 self.assertEqual(expected_delete_calls, 410 uploader_cs_mock.Delete.call_args_list) 411 412 @mock.patch('dependency_manager.uploader.cloud_storage') 413 def testExecuteUpdateJobsFailureOnSecondInsertNoCSCollision( 414 self, uploader_cs_mock): 415 uploader_cs_mock.Exists.return_value = False 416 uploader_cs_mock.Insert.side_effect = [ 417 True, cloud_storage.CloudStorageError] 418 self.fs.CreateFile(self.file_path, 419 contents='\n'.join(self.expected_file_lines)) 420 config = dependency_manager.BaseConfig(self.file_path, writable=True) 421 config._config_data = self.new_dependencies.copy() 422 config._is_dirty = True 423 config._pending_uploads = [self.new_pending_upload, 424 self.final_pending_upload] 425 self.assertEqual(self.new_dependencies, config._config_data) 426 self.assertTrue(config._is_dirty) 427 self.assertEqual(2, len(config._pending_uploads)) 428 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 429 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 430 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path), 431 mock.call(self.final_bucket, 432 self.final_remote_path)] 433 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 434 self.new_dep_path), 435 mock.call(self.final_bucket, 436 self.final_remote_path, 437 self.final_dep_path)] 438 expected_copy_calls = [] 439 expected_delete_calls = [mock.call(self.new_bucket, self.new_remote_path)] 440 441 self.assertRaises(cloud_storage.CloudStorageError, 442 config.ExecuteUpdateJobs) 443 self.assertTrue(config._is_dirty) 444 self.assertEqual(2, len(config._pending_uploads)) 445 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 446 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 447 self.assertEqual(self.new_dependencies, config._config_data) 448 file_module = fake_filesystem.FakeFileOpen(self.fs) 449 expected_file_lines = list(self.expected_file_lines) 450 for line in file_module(self.file_path): 451 self.assertEqual(expected_file_lines.pop(0), line.strip()) 452 self.fs.CloseOpenFile(file_module(self.file_path)) 453 self.assertEqual(expected_insert_calls, 454 uploader_cs_mock.Insert.call_args_list) 455 self.assertEqual(expected_exists_calls, 456 uploader_cs_mock.Exists.call_args_list) 457 self.assertEqual(expected_copy_calls, 458 uploader_cs_mock.Copy.call_args_list) 459 self.assertEqual(expected_delete_calls, 460 uploader_cs_mock.Delete.call_args_list) 461 462 @mock.patch('dependency_manager.uploader.cloud_storage') 463 def testExecuteUpdateJobsFailureOnSecondInsertCSCollisionForce( 464 self, uploader_cs_mock): 465 uploader_cs_mock.Exists.return_value = True 466 uploader_cs_mock.Insert.side_effect = [ 467 True, cloud_storage.CloudStorageError] 468 self.fs.CreateFile(self.file_path, 469 contents='\n'.join(self.expected_file_lines)) 470 config = dependency_manager.BaseConfig(self.file_path, writable=True) 471 config._config_data = self.new_dependencies.copy() 472 config._is_dirty = True 473 config._pending_uploads = [self.new_pending_upload, 474 self.final_pending_upload] 475 self.assertEqual(self.new_dependencies, config._config_data) 476 self.assertTrue(config._is_dirty) 477 self.assertEqual(2, len(config._pending_uploads)) 478 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 479 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 480 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path), 481 mock.call(self.final_bucket, 482 self.final_remote_path)] 483 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 484 self.new_dep_path), 485 mock.call(self.final_bucket, 486 self.final_remote_path, 487 self.final_dep_path)] 488 expected_copy_calls = [mock.call(self.new_bucket, self.new_bucket, 489 self.new_remote_path, 490 self.expected_new_backup_path), 491 mock.call(self.final_bucket, self.final_bucket, 492 self.final_remote_path, 493 self.expected_final_backup_path), 494 mock.call(self.final_bucket, self.final_bucket, 495 self.expected_final_backup_path, 496 self.final_remote_path), 497 mock.call(self.new_bucket, self.new_bucket, 498 self.expected_new_backup_path, 499 self.new_remote_path)] 500 expected_delete_calls = [] 501 502 self.assertRaises(cloud_storage.CloudStorageError, 503 config.ExecuteUpdateJobs, force=True) 504 self.assertTrue(config._is_dirty) 505 self.assertEqual(2, len(config._pending_uploads)) 506 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 507 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 508 self.assertEqual(self.new_dependencies, config._config_data) 509 file_module = fake_filesystem.FakeFileOpen(self.fs) 510 expected_file_lines = list(self.expected_file_lines) 511 for line in file_module(self.file_path): 512 self.assertEqual(expected_file_lines.pop(0), line.strip()) 513 self.fs.CloseOpenFile(file_module(self.file_path)) 514 self.assertEqual(expected_insert_calls, 515 uploader_cs_mock.Insert.call_args_list) 516 self.assertEqual(expected_exists_calls, 517 uploader_cs_mock.Exists.call_args_list) 518 self.assertEqual(expected_copy_calls, 519 uploader_cs_mock.Copy.call_args_list) 520 self.assertEqual(expected_delete_calls, 521 uploader_cs_mock.Delete.call_args_list) 522 523 @mock.patch('dependency_manager.uploader.cloud_storage') 524 def testExecuteUpdateJobsFailureOnSecondInsertFirstCSCollisionForce( 525 self, uploader_cs_mock): 526 uploader_cs_mock.Exists.side_effect = [True, False, True] 527 uploader_cs_mock.Insert.side_effect = [ 528 True, cloud_storage.CloudStorageError] 529 self.fs.CreateFile(self.file_path, 530 contents='\n'.join(self.expected_file_lines)) 531 config = dependency_manager.BaseConfig(self.file_path, writable=True) 532 config._config_data = self.new_dependencies.copy() 533 config._is_dirty = True 534 config._pending_uploads = [self.new_pending_upload, 535 self.final_pending_upload] 536 self.assertEqual(self.new_dependencies, config._config_data) 537 self.assertTrue(config._is_dirty) 538 self.assertEqual(2, len(config._pending_uploads)) 539 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 540 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 541 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path), 542 mock.call(self.final_bucket, 543 self.final_remote_path)] 544 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 545 self.new_dep_path), 546 mock.call(self.final_bucket, 547 self.final_remote_path, 548 self.final_dep_path)] 549 expected_copy_calls = [mock.call(self.new_bucket, self.new_bucket, 550 self.new_remote_path, 551 self.expected_new_backup_path), 552 mock.call(self.new_bucket, self.new_bucket, 553 self.expected_new_backup_path, 554 self.new_remote_path)] 555 expected_delete_calls = [] 556 557 self.assertRaises(cloud_storage.CloudStorageError, 558 config.ExecuteUpdateJobs, force=True) 559 self.assertTrue(config._is_dirty) 560 self.assertEqual(2, len(config._pending_uploads)) 561 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 562 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 563 self.assertEqual(self.new_dependencies, config._config_data) 564 file_module = fake_filesystem.FakeFileOpen(self.fs) 565 expected_file_lines = list(self.expected_file_lines) 566 for line in file_module(self.file_path): 567 self.assertEqual(expected_file_lines.pop(0), line.strip()) 568 self.fs.CloseOpenFile(file_module(self.file_path)) 569 self.assertEqual(expected_insert_calls, 570 uploader_cs_mock.Insert.call_args_list) 571 self.assertEqual(expected_exists_calls, 572 uploader_cs_mock.Exists.call_args_list) 573 self.assertEqual(expected_copy_calls, 574 uploader_cs_mock.Copy.call_args_list) 575 self.assertEqual(expected_delete_calls, 576 uploader_cs_mock.Delete.call_args_list) 577 578 @mock.patch('dependency_manager.uploader.cloud_storage') 579 def testExecuteUpdateJobsFailureOnFirstCSCollisionNoForce( 580 self, uploader_cs_mock): 581 uploader_cs_mock.Exists.side_effect = [True, False, True] 582 uploader_cs_mock.Insert.side_effect = [ 583 True, cloud_storage.CloudStorageError] 584 self.fs.CreateFile(self.file_path, 585 contents='\n'.join(self.expected_file_lines)) 586 config = dependency_manager.BaseConfig(self.file_path, writable=True) 587 config._config_data = self.new_dependencies.copy() 588 config._is_dirty = True 589 config._pending_uploads = [self.new_pending_upload, 590 self.final_pending_upload] 591 self.assertEqual(self.new_dependencies, config._config_data) 592 self.assertTrue(config._is_dirty) 593 self.assertEqual(2, len(config._pending_uploads)) 594 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 595 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 596 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 597 expected_insert_calls = [] 598 expected_copy_calls = [] 599 expected_delete_calls = [] 600 601 self.assertRaises(cloud_storage.CloudStorageError, 602 config.ExecuteUpdateJobs) 603 self.assertTrue(config._is_dirty) 604 self.assertEqual(2, len(config._pending_uploads)) 605 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 606 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 607 self.assertEqual(self.new_dependencies, config._config_data) 608 file_module = fake_filesystem.FakeFileOpen(self.fs) 609 expected_file_lines = list(self.expected_file_lines) 610 for line in file_module(self.file_path): 611 self.assertEqual(expected_file_lines.pop(0), line.strip()) 612 self.fs.CloseOpenFile(file_module(self.file_path)) 613 self.assertEqual(expected_insert_calls, 614 uploader_cs_mock.Insert.call_args_list) 615 self.assertEqual(expected_exists_calls, 616 uploader_cs_mock.Exists.call_args_list) 617 self.assertEqual(expected_copy_calls, 618 uploader_cs_mock.Copy.call_args_list) 619 self.assertEqual(expected_delete_calls, 620 uploader_cs_mock.Delete.call_args_list) 621 622 @mock.patch('dependency_manager.uploader.cloud_storage') 623 def testExecuteUpdateJobsFailureOnSecondCopyCSCollision( 624 self, uploader_cs_mock): 625 uploader_cs_mock.Exists.return_value = True 626 uploader_cs_mock.Insert.return_value = True 627 uploader_cs_mock.Copy.side_effect = [ 628 True, cloud_storage.CloudStorageError, True] 629 self.fs.CreateFile(self.file_path, 630 contents='\n'.join(self.expected_file_lines)) 631 config = dependency_manager.BaseConfig(self.file_path, writable=True) 632 config._config_data = self.new_dependencies.copy() 633 config._is_dirty = True 634 config._pending_uploads = [self.new_pending_upload, 635 self.final_pending_upload] 636 self.assertEqual(self.new_dependencies, config._config_data) 637 self.assertTrue(config._is_dirty) 638 self.assertEqual(2, len(config._pending_uploads)) 639 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 640 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 641 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path), 642 mock.call(self.final_bucket, 643 self.final_remote_path)] 644 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 645 self.new_dep_path)] 646 expected_copy_calls = [mock.call(self.new_bucket, self.new_bucket, 647 self.new_remote_path, 648 self.expected_new_backup_path), 649 mock.call(self.final_bucket, self.final_bucket, 650 self.final_remote_path, 651 self.expected_final_backup_path), 652 mock.call(self.new_bucket, self.new_bucket, 653 self.expected_new_backup_path, 654 self.new_remote_path)] 655 expected_delete_calls = [] 656 657 self.assertRaises(cloud_storage.CloudStorageError, 658 config.ExecuteUpdateJobs, force=True) 659 self.assertTrue(config._is_dirty) 660 self.assertEqual(2, len(config._pending_uploads)) 661 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 662 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 663 self.assertEqual(self.new_dependencies, config._config_data) 664 file_module = fake_filesystem.FakeFileOpen(self.fs) 665 expected_file_lines = list(self.expected_file_lines) 666 for line in file_module(self.file_path): 667 self.assertEqual(expected_file_lines.pop(0), line.strip()) 668 self.fs.CloseOpenFile(file_module(self.file_path)) 669 self.assertEqual(expected_insert_calls, 670 uploader_cs_mock.Insert.call_args_list) 671 self.assertEqual(expected_exists_calls, 672 uploader_cs_mock.Exists.call_args_list) 673 self.assertEqual(expected_copy_calls, 674 uploader_cs_mock.Copy.call_args_list) 675 self.assertEqual(expected_delete_calls, 676 uploader_cs_mock.Delete.call_args_list) 677 678 @mock.patch('dependency_manager.uploader.cloud_storage') 679 def testExecuteUpdateJobsFailureOnSecondCopyNoCSCollisionForce( 680 self, uploader_cs_mock): 681 uploader_cs_mock.Exists.side_effect = [False, True, False] 682 uploader_cs_mock.Copy.side_effect = cloud_storage.CloudStorageError 683 self.fs.CreateFile(self.file_path, 684 contents='\n'.join(self.expected_file_lines)) 685 config = dependency_manager.BaseConfig(self.file_path, writable=True) 686 config._config_data = self.new_dependencies.copy() 687 config._is_dirty = True 688 config._pending_uploads = [self.new_pending_upload, 689 self.final_pending_upload] 690 self.assertEqual(self.new_dependencies, config._config_data) 691 self.assertTrue(config._is_dirty) 692 self.assertEqual(2, len(config._pending_uploads)) 693 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 694 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 695 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path), 696 mock.call(self.final_bucket, 697 self.final_remote_path)] 698 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 699 self.new_dep_path)] 700 expected_copy_calls = [mock.call(self.final_bucket, self.final_bucket, 701 self.final_remote_path, 702 self.expected_final_backup_path)] 703 expected_delete_calls = [mock.call(self.new_bucket, self.new_remote_path)] 704 705 self.assertRaises(cloud_storage.CloudStorageError, 706 config.ExecuteUpdateJobs, force=True) 707 self.assertTrue(config._is_dirty) 708 self.assertEqual(2, len(config._pending_uploads)) 709 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 710 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 711 self.assertEqual(self.new_dependencies, config._config_data) 712 file_module = fake_filesystem.FakeFileOpen(self.fs) 713 expected_file_lines = list(self.expected_file_lines) 714 for line in file_module(self.file_path): 715 self.assertEqual(expected_file_lines.pop(0), line.strip()) 716 self.fs.CloseOpenFile(file_module(self.file_path)) 717 self.assertEqual(expected_insert_calls, 718 uploader_cs_mock.Insert.call_args_list) 719 self.assertEqual(expected_exists_calls, 720 uploader_cs_mock.Exists.call_args_list) 721 self.assertEqual(expected_copy_calls, 722 uploader_cs_mock.Copy.call_args_list) 723 self.assertEqual(expected_delete_calls, 724 uploader_cs_mock.Delete.call_args_list) 725 726 @mock.patch('dependency_manager.uploader.cloud_storage') 727 def testExecuteUpdateJobsFailureOnSecondCopyNoCSCollisionNoForce( 728 self, uploader_cs_mock): 729 uploader_cs_mock.Exists.side_effect = [False, True, False] 730 uploader_cs_mock.Copy.side_effect = cloud_storage.CloudStorageError 731 self.fs.CreateFile(self.file_path, 732 contents='\n'.join(self.expected_file_lines)) 733 config = dependency_manager.BaseConfig(self.file_path, writable=True) 734 config._config_data = self.new_dependencies.copy() 735 config._is_dirty = True 736 config._pending_uploads = [self.new_pending_upload, 737 self.final_pending_upload] 738 self.assertEqual(self.new_dependencies, config._config_data) 739 self.assertTrue(config._is_dirty) 740 self.assertEqual(2, len(config._pending_uploads)) 741 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 742 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 743 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path), 744 mock.call(self.final_bucket, 745 self.final_remote_path)] 746 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 747 self.new_dep_path)] 748 expected_copy_calls = [] 749 expected_delete_calls = [mock.call(self.new_bucket, self.new_remote_path)] 750 751 self.assertRaises(cloud_storage.CloudStorageError, 752 config.ExecuteUpdateJobs) 753 self.assertTrue(config._is_dirty) 754 self.assertEqual(2, len(config._pending_uploads)) 755 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 756 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 757 self.assertEqual(self.new_dependencies, config._config_data) 758 file_module = fake_filesystem.FakeFileOpen(self.fs) 759 expected_file_lines = list(self.expected_file_lines) 760 for line in file_module(self.file_path): 761 self.assertEqual(expected_file_lines.pop(0), line.strip()) 762 self.fs.CloseOpenFile(file_module(self.file_path)) 763 self.assertEqual(expected_insert_calls, 764 uploader_cs_mock.Insert.call_args_list) 765 self.assertEqual(expected_exists_calls, 766 uploader_cs_mock.Exists.call_args_list) 767 self.assertEqual(expected_copy_calls, 768 uploader_cs_mock.Copy.call_args_list) 769 self.assertEqual(expected_delete_calls, 770 uploader_cs_mock.Delete.call_args_list) 771 772 @mock.patch('dependency_manager.uploader.cloud_storage') 773 def testExecuteUpdateJobsSuccessOnePendingDepNoCloudStorageCollision( 774 self, uploader_cs_mock): 775 uploader_cs_mock.Exists.return_value = False 776 self.fs.CreateFile(self.file_path, 777 contents='\n'.join(self.expected_file_lines)) 778 config = dependency_manager.BaseConfig(self.file_path, writable=True) 779 config._config_data = self.new_dependencies.copy() 780 config._pending_uploads = [self.new_pending_upload] 781 self.assertEqual(self.new_dependencies, config._config_data) 782 self.assertTrue(config._IsDirty()) 783 self.assertEqual(1, len(config._pending_uploads)) 784 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 785 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 786 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 787 self.new_dep_path)] 788 expected_copy_calls = [] 789 expected_delete_calls = [] 790 791 self.assertTrue(config.ExecuteUpdateJobs()) 792 self.assertFalse(config._IsDirty()) 793 self.assertFalse(config._pending_uploads) 794 self.assertEqual(self.new_dependencies, config._config_data) 795 file_module = fake_filesystem.FakeFileOpen(self.fs) 796 expected_file_lines = list(self.new_expected_file_lines) 797 for line in file_module(self.file_path): 798 self.assertEqual(expected_file_lines.pop(0), line.strip()) 799 self.fs.CloseOpenFile(file_module(self.file_path)) 800 self.assertFalse(config._pending_uploads) 801 self.assertEqual(expected_insert_calls, 802 uploader_cs_mock.Insert.call_args_list) 803 self.assertEqual(expected_exists_calls, 804 uploader_cs_mock.Exists.call_args_list) 805 self.assertEqual(expected_copy_calls, 806 uploader_cs_mock.Copy.call_args_list) 807 self.assertEqual(expected_delete_calls, 808 uploader_cs_mock.Delete.call_args_list) 809 810 @mock.patch('dependency_manager.uploader.cloud_storage') 811 def testExecuteUpdateJobsSuccessOnePendingDepCloudStorageCollision( 812 self, uploader_cs_mock): 813 uploader_cs_mock.Exists.return_value = True 814 self.fs.CreateFile(self.file_path, 815 contents='\n'.join(self.expected_file_lines)) 816 config = dependency_manager.BaseConfig(self.file_path, writable=True) 817 config._config_data = self.new_dependencies.copy() 818 config._pending_uploads = [self.new_pending_upload] 819 self.assertEqual(self.new_dependencies, config._config_data) 820 self.assertTrue(config._IsDirty()) 821 self.assertEqual(1, len(config._pending_uploads)) 822 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 823 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 824 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 825 self.new_dep_path)] 826 expected_copy_calls = [mock.call(self.new_bucket, self.new_bucket, 827 self.new_remote_path, 828 self.expected_new_backup_path)] 829 830 self.assertTrue(config.ExecuteUpdateJobs(force=True)) 831 self.assertFalse(config._IsDirty()) 832 self.assertFalse(config._pending_uploads) 833 self.assertEqual(self.new_dependencies, config._config_data) 834 file_module = fake_filesystem.FakeFileOpen(self.fs) 835 expected_file_lines = list(self.new_expected_file_lines) 836 for line in file_module(self.file_path): 837 self.assertEqual(expected_file_lines.pop(0), line.strip()) 838 self.fs.CloseOpenFile(file_module(self.file_path)) 839 self.assertFalse(config._pending_uploads) 840 self.assertEqual(expected_insert_calls, 841 uploader_cs_mock.Insert.call_args_list) 842 self.assertEqual(expected_exists_calls, 843 uploader_cs_mock.Exists.call_args_list) 844 self.assertEqual(expected_copy_calls, 845 uploader_cs_mock.Copy.call_args_list) 846 847 @mock.patch('dependency_manager.uploader.cloud_storage') 848 def testExecuteUpdateJobsErrorOnePendingDepCloudStorageCollisionNoForce( 849 self, uploader_cs_mock): 850 uploader_cs_mock.Exists.return_value = True 851 self.fs.CreateFile(self.file_path, 852 contents='\n'.join(self.expected_file_lines)) 853 config = dependency_manager.BaseConfig(self.file_path, writable=True) 854 config._config_data = self.new_dependencies.copy() 855 config._is_dirty = True 856 config._pending_uploads = [self.new_pending_upload] 857 self.assertEqual(self.new_dependencies, config._config_data) 858 self.assertTrue(config._is_dirty) 859 self.assertEqual(1, len(config._pending_uploads)) 860 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 861 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path)] 862 expected_insert_calls = [] 863 expected_copy_calls = [] 864 865 self.assertRaises(dependency_manager.CloudStorageUploadConflictError, 866 config.ExecuteUpdateJobs) 867 self.assertTrue(config._is_dirty) 868 self.assertTrue(config._pending_uploads) 869 self.assertEqual(self.new_dependencies, config._config_data) 870 self.assertEqual(1, len(config._pending_uploads)) 871 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 872 file_module = fake_filesystem.FakeFileOpen(self.fs) 873 expected_file_lines = list(self.expected_file_lines) 874 for line in file_module(self.file_path): 875 self.assertEqual(expected_file_lines.pop(0), line.strip()) 876 self.fs.CloseOpenFile(file_module(self.file_path)) 877 self.assertEqual(expected_insert_calls, 878 uploader_cs_mock.Insert.call_args_list) 879 self.assertEqual(expected_exists_calls, 880 uploader_cs_mock.Exists.call_args_list) 881 self.assertEqual(expected_copy_calls, 882 uploader_cs_mock.Copy.call_args_list) 883 884 @mock.patch('dependency_manager.uploader.cloud_storage') 885 def testExecuteUpdateJobsSuccessMultiplePendingDepsOneCloudStorageCollision( 886 self, uploader_cs_mock): 887 uploader_cs_mock.Exists.side_effect = [False, True] 888 self.fs.CreateFile(self.file_path, 889 contents='\n'.join(self.expected_file_lines)) 890 config = dependency_manager.BaseConfig(self.file_path, writable=True) 891 config._config_data = self.final_dependencies.copy() 892 config._pending_uploads = [self.new_pending_upload, 893 self.final_pending_upload] 894 self.assertEqual(self.final_dependencies, config._config_data) 895 self.assertTrue(config._IsDirty()) 896 self.assertEqual(2, len(config._pending_uploads)) 897 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 898 self.assertEqual(self.final_pending_upload, config._pending_uploads[1]) 899 900 expected_exists_calls = [mock.call(self.new_bucket, self.new_remote_path), 901 mock.call(self.final_bucket, 902 self.final_remote_path)] 903 expected_insert_calls = [mock.call(self.new_bucket, self.new_remote_path, 904 self.new_dep_path), 905 mock.call(self.final_bucket, 906 self.final_remote_path, 907 self.final_dep_path)] 908 expected_copy_calls = [mock.call(self.final_bucket, self.final_bucket, 909 self.final_remote_path, 910 self.expected_final_backup_path)] 911 912 self.assertTrue(config.ExecuteUpdateJobs(force=True)) 913 self.assertFalse(config._IsDirty()) 914 self.assertFalse(config._pending_uploads) 915 self.assertEqual(self.final_dependencies, config._config_data) 916 file_module = fake_filesystem.FakeFileOpen(self.fs) 917 expected_file_lines = list(self.final_expected_file_lines) 918 for line in file_module(self.file_path): 919 self.assertEqual(expected_file_lines.pop(0), line.strip()) 920 self.fs.CloseOpenFile(file_module(self.file_path)) 921 self.assertFalse(config._pending_uploads) 922 self.assertEqual(expected_insert_calls, 923 uploader_cs_mock.Insert.call_args_list) 924 self.assertEqual(expected_exists_calls, 925 uploader_cs_mock.Exists.call_args_list) 926 self.assertEqual(expected_copy_calls, 927 uploader_cs_mock.Copy.call_args_list) 928 929 @mock.patch('dependency_manager.uploader.cloud_storage') 930 def testUpdateCloudStorageDependenciesReadOnlyConfig( 931 self, uploader_cs_mock): 932 self.fs.CreateFile(self.file_path, 933 contents='\n'.join(self.expected_file_lines)) 934 config = dependency_manager.BaseConfig(self.file_path) 935 with self.assertRaises(dependency_manager.ReadWriteError): 936 config.AddCloudStorageDependencyUpdateJob( 937 'dep', 'plat', 'path') 938 with self.assertRaises(dependency_manager.ReadWriteError): 939 config.AddCloudStorageDependencyUpdateJob( 940 'dep', 'plat', 'path', version='1.2.3') 941 with self.assertRaises(dependency_manager.ReadWriteError): 942 config.AddCloudStorageDependencyUpdateJob( 943 'dep', 'plat', 'path', execute_job=False) 944 with self.assertRaises(dependency_manager.ReadWriteError): 945 config.AddCloudStorageDependencyUpdateJob( 946 'dep', 'plat', 'path', version='1.2.3', execute_job=False) 947 948 @mock.patch('dependency_manager.uploader.cloud_storage') 949 def testUpdateCloudStorageDependenciesMissingDependency( 950 self, uploader_cs_mock): 951 self.fs.CreateFile(self.file_path, 952 contents='\n'.join(self.expected_file_lines)) 953 config = dependency_manager.BaseConfig(self.file_path, writable=True) 954 self.assertRaises(ValueError, config.AddCloudStorageDependencyUpdateJob, 955 'dep', 'plat', 'path') 956 self.assertRaises(ValueError, config.AddCloudStorageDependencyUpdateJob, 957 'dep', 'plat', 'path', version='1.2.3') 958 self.assertRaises(ValueError, config.AddCloudStorageDependencyUpdateJob, 959 'dep', 'plat', 'path', execute_job=False) 960 self.assertRaises(ValueError, config.AddCloudStorageDependencyUpdateJob, 961 'dep', 'plat', 'path', version='1.2.3', execute_job=False) 962 963 @mock.patch('dependency_manager.uploader.cloud_storage') 964 @mock.patch('dependency_manager.base_config.cloud_storage') 965 def testUpdateCloudStorageDependenciesWrite( 966 self, base_config_cs_mock, uploader_cs_mock): 967 expected_dependencies = self.dependencies 968 self.fs.CreateFile(self.file_path, 969 contents='\n'.join(self.expected_file_lines)) 970 config = dependency_manager.BaseConfig(self.file_path, writable=True) 971 self.assertFalse(config._IsDirty()) 972 self.assertEqual(expected_dependencies, config._config_data) 973 974 base_config_cs_mock.CalculateHash.return_value = self.new_dep_hash 975 uploader_cs_mock.Exists.return_value = False 976 expected_dependencies = self.new_dependencies 977 config.AddCloudStorageDependencyUpdateJob( 978 'dep1', 'plat2', self.new_dep_path, execute_job=True) 979 self.assertFalse(config._IsDirty()) 980 self.assertFalse(config._pending_uploads) 981 self.assertEqual(expected_dependencies, config._config_data) 982 # check that file contents has been updated 983 file_module = fake_filesystem.FakeFileOpen(self.fs) 984 expected_file_lines = list(self.new_expected_file_lines) 985 for line in file_module(self.file_path): 986 self.assertEqual(expected_file_lines.pop(0), line.strip()) 987 self.fs.CloseOpenFile(file_module(self.file_path)) 988 989 expected_dependencies = self.final_dependencies 990 base_config_cs_mock.CalculateHash.return_value = self.final_dep_hash 991 config.AddCloudStorageDependencyUpdateJob( 992 'dep2', 'plat1', self.final_dep_path, execute_job=True) 993 self.assertFalse(config._IsDirty()) 994 self.assertFalse(config._pending_uploads) 995 self.assertEqual(expected_dependencies, config._config_data) 996 # check that file contents has been updated 997 expected_file_lines = list(self.final_expected_file_lines) 998 file_module = fake_filesystem.FakeFileOpen(self.fs) 999 for line in file_module(self.file_path): 1000 self.assertEqual(expected_file_lines.pop(0), line.strip()) 1001 self.fs.CloseOpenFile(file_module(self.file_path)) 1002 1003 @mock.patch('dependency_manager.uploader.cloud_storage') 1004 @mock.patch('dependency_manager.base_config.cloud_storage') 1005 def testUpdateCloudStorageDependenciesNoWrite( 1006 self, base_config_cs_mock, uploader_cs_mock): 1007 self.fs.CreateFile(self.file_path, 1008 contents='\n'.join(self.expected_file_lines)) 1009 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1010 1011 self.assertRaises(ValueError, config.AddCloudStorageDependencyUpdateJob, 1012 'dep', 'plat', 'path') 1013 self.assertRaises(ValueError, config.AddCloudStorageDependencyUpdateJob, 1014 'dep', 'plat', 'path', version='1.2.3') 1015 1016 expected_dependencies = self.dependencies 1017 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1018 self.assertFalse(config._IsDirty()) 1019 self.assertFalse(config._pending_uploads) 1020 self.assertEqual(expected_dependencies, config._config_data) 1021 1022 base_config_cs_mock.CalculateHash.return_value = self.new_dep_hash 1023 uploader_cs_mock.Exists.return_value = False 1024 expected_dependencies = self.new_dependencies 1025 config.AddCloudStorageDependencyUpdateJob( 1026 'dep1', 'plat2', self.new_dep_path, execute_job=False) 1027 self.assertTrue(config._IsDirty()) 1028 self.assertEqual(1, len(config._pending_uploads)) 1029 self.assertEqual(self.new_pending_upload, config._pending_uploads[0]) 1030 self.assertEqual(expected_dependencies, config._config_data) 1031 # check that file contents have not been updated. 1032 expected_file_lines = list(self.expected_file_lines) 1033 file_module = fake_filesystem.FakeFileOpen(self.fs) 1034 for line in file_module(self.file_path): 1035 self.assertEqual(expected_file_lines.pop(0), line.strip()) 1036 self.fs.CloseOpenFile(file_module(self.file_path)) 1037 1038 expected_dependencies = self.final_dependencies 1039 base_config_cs_mock.CalculateHash.return_value = self.final_dep_hash 1040 config.AddCloudStorageDependencyUpdateJob( 1041 'dep2', 'plat1', self.final_dep_path, execute_job=False) 1042 self.assertTrue(config._IsDirty()) 1043 self.assertEqual(expected_dependencies, config._config_data) 1044 # check that file contents have not been updated. 1045 expected_file_lines = list(self.expected_file_lines) 1046 file_module = fake_filesystem.FakeFileOpen(self.fs) 1047 for line in file_module(self.file_path): 1048 self.assertEqual(expected_file_lines.pop(0), line.strip()) 1049 self.fs.CloseOpenFile(file_module(self.file_path)) 1050 1051 1052 class BaseConfigDataManipulationUnittests(fake_filesystem_unittest.TestCase): 1053 def setUp(self): 1054 self.addTypeEqualityFunc(uploader.CloudStorageUploader, 1055 uploader.CloudStorageUploader.__eq__) 1056 self.setUpPyfakefs() 1057 1058 self.cs_bucket = 'bucket1' 1059 self.cs_base_folder = 'dependencies_folder' 1060 self.cs_hash = 'hash12' 1061 self.download_path = '../../relative/dep1/path2' 1062 self.local_paths = ['../../../relative/local/path21', 1063 '../../../relative/local/path22'] 1064 self.platform_dict = {'cloud_storage_hash': self.cs_hash, 1065 'download_path': self.download_path, 1066 'local_paths': self.local_paths} 1067 self.dependencies = { 1068 'dep1': { 1069 'cloud_storage_bucket': self.cs_bucket, 1070 'cloud_storage_base_folder': self.cs_base_folder, 1071 'file_info': { 1072 'plat1': { 1073 'cloud_storage_hash': 'hash11', 1074 'download_path': '../../relative/dep1/path1', 1075 'local_paths': ['../../../relative/local/path11', 1076 '../../../relative/local/path12']}, 1077 'plat2': self.platform_dict 1078 } 1079 }, 1080 'dep2': { 1081 'cloud_storage_bucket': 'bucket2', 1082 'file_info': { 1083 'plat1': { 1084 'cloud_storage_hash': 'hash21', 1085 'download_path': '../../relative/dep2/path1', 1086 'local_paths': ['../../../relative/local/path31', 1087 '../../../relative/local/path32']}, 1088 'plat2': { 1089 'cloud_storage_hash': 'hash22', 1090 'download_path': '../../relative/dep2/path2'}}}} 1091 1092 self.file_path = os.path.abspath(os.path.join( 1093 'path', 'to', 'config', 'file')) 1094 1095 1096 self.expected_file_lines = [ 1097 # pylint: disable=bad-continuation 1098 '{', '"config_type": "BaseConfig",', '"dependencies": {', 1099 '"dep1": {', '"cloud_storage_base_folder": "dependencies_folder",', 1100 '"cloud_storage_bucket": "bucket1",', '"file_info": {', 1101 '"plat1": {', '"cloud_storage_hash": "hash11",', 1102 '"download_path": "../../relative/dep1/path1",', 1103 '"local_paths": [', '"../../../relative/local/path11",', 1104 '"../../../relative/local/path12"', ']', '},', 1105 '"plat2": {', '"cloud_storage_hash": "hash12",', 1106 '"download_path": "../../relative/dep1/path2",', 1107 '"local_paths": [', '"../../../relative/local/path21",', 1108 '"../../../relative/local/path22"', ']', 1109 '}', '}', '},', 1110 '"dep2": {', '"cloud_storage_bucket": "bucket2",', '"file_info": {', 1111 '"plat1": {', '"cloud_storage_hash": "hash21",', 1112 '"download_path": "../../relative/dep2/path1",', 1113 '"local_paths": [', '"../../../relative/local/path31",', 1114 '"../../../relative/local/path32"', ']', '},', 1115 '"plat2": {', '"cloud_storage_hash": "hash22",', 1116 '"download_path": "../../relative/dep2/path2"', '}', '}', '}', 1117 '}', '}'] 1118 self.fs.CreateFile(self.file_path, 1119 contents='\n'.join(self.expected_file_lines)) 1120 1121 1122 def testSetPlatformDataFailureNotWritable(self): 1123 config = dependency_manager.BaseConfig(self.file_path) 1124 self.assertRaises( 1125 dependency_manager.ReadWriteError, config._SetPlatformData, 1126 'dep1', 'plat1', 'cloud_storage_bucket', 'new_bucket') 1127 self.assertEqual(self.dependencies, config._config_data) 1128 1129 def testSetPlatformDataFailure(self): 1130 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1131 self.assertRaises(ValueError, config._SetPlatformData, 'missing_dep', 1132 'plat2', 'cloud_storage_bucket', 'new_bucket') 1133 self.assertEqual(self.dependencies, config._config_data) 1134 self.assertRaises(ValueError, config._SetPlatformData, 'dep1', 1135 'missing_plat', 'cloud_storage_bucket', 'new_bucket') 1136 self.assertEqual(self.dependencies, config._config_data) 1137 1138 1139 def testSetPlatformDataCloudStorageBucketSuccess(self): 1140 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1141 updated_cs_dependencies = { 1142 'dep1': {'cloud_storage_bucket': 'new_bucket', 1143 'cloud_storage_base_folder': 'dependencies_folder', 1144 'file_info': { 1145 'plat1': { 1146 'cloud_storage_hash': 'hash11', 1147 'download_path': '../../relative/dep1/path1', 1148 'local_paths': ['../../../relative/local/path11', 1149 '../../../relative/local/path12']}, 1150 'plat2': { 1151 'cloud_storage_hash': 'hash12', 1152 'download_path': '../../relative/dep1/path2', 1153 'local_paths': ['../../../relative/local/path21', 1154 '../../../relative/local/path22']}}}, 1155 'dep2': {'cloud_storage_bucket': 'bucket2', 1156 'file_info': { 1157 'plat1': { 1158 'cloud_storage_hash': 'hash21', 1159 'download_path': '../../relative/dep2/path1', 1160 'local_paths': ['../../../relative/local/path31', 1161 '../../../relative/local/path32']}, 1162 'plat2': { 1163 'cloud_storage_hash': 'hash22', 1164 'download_path': '../../relative/dep2/path2'}}}} 1165 config._SetPlatformData('dep1', 'plat2', 'cloud_storage_bucket', 1166 'new_bucket') 1167 self.assertEqual(updated_cs_dependencies, config._config_data) 1168 1169 def testSetPlatformDataCloudStorageBaseFolderSuccess(self): 1170 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1171 updated_cs_dependencies = { 1172 'dep1': {'cloud_storage_bucket': 'bucket1', 1173 'cloud_storage_base_folder': 'new_dependencies_folder', 1174 'file_info': { 1175 'plat1': { 1176 'cloud_storage_hash': 'hash11', 1177 'download_path': '../../relative/dep1/path1', 1178 'local_paths': ['../../../relative/local/path11', 1179 '../../../relative/local/path12']}, 1180 'plat2': { 1181 'cloud_storage_hash': 'hash12', 1182 'download_path': '../../relative/dep1/path2', 1183 'local_paths': ['../../../relative/local/path21', 1184 '../../../relative/local/path22']}}}, 1185 'dep2': {'cloud_storage_bucket': 'bucket2', 1186 'file_info': { 1187 'plat1': { 1188 'cloud_storage_hash': 'hash21', 1189 'download_path': '../../relative/dep2/path1', 1190 'local_paths': ['../../../relative/local/path31', 1191 '../../../relative/local/path32']}, 1192 'plat2': { 1193 'cloud_storage_hash': 'hash22', 1194 'download_path': '../../relative/dep2/path2'}}}} 1195 config._SetPlatformData('dep1', 'plat2', 'cloud_storage_base_folder', 1196 'new_dependencies_folder') 1197 self.assertEqual(updated_cs_dependencies, config._config_data) 1198 1199 def testSetPlatformDataHashSuccess(self): 1200 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1201 updated_cs_dependencies = { 1202 'dep1': {'cloud_storage_bucket': 'bucket1', 1203 'cloud_storage_base_folder': 'dependencies_folder', 1204 'file_info': { 1205 'plat1': { 1206 'cloud_storage_hash': 'hash11', 1207 'download_path': '../../relative/dep1/path1', 1208 'local_paths': ['../../../relative/local/path11', 1209 '../../../relative/local/path12']}, 1210 'plat2': { 1211 'cloud_storage_hash': 'new_hash', 1212 'download_path': '../../relative/dep1/path2', 1213 'local_paths': ['../../../relative/local/path21', 1214 '../../../relative/local/path22']}}}, 1215 'dep2': {'cloud_storage_bucket': 'bucket2', 1216 'file_info': { 1217 'plat1': { 1218 'cloud_storage_hash': 'hash21', 1219 'download_path': '../../relative/dep2/path1', 1220 'local_paths': ['../../../relative/local/path31', 1221 '../../../relative/local/path32']}, 1222 'plat2': { 1223 'cloud_storage_hash': 'hash22', 1224 'download_path': '../../relative/dep2/path2'}}}} 1225 config._SetPlatformData('dep1', 'plat2', 'cloud_storage_hash', 1226 'new_hash') 1227 self.assertEqual(updated_cs_dependencies, config._config_data) 1228 1229 def testSetPlatformDataDownloadPathSuccess(self): 1230 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1231 updated_cs_dependencies = { 1232 'dep1': {'cloud_storage_bucket': 'bucket1', 1233 'cloud_storage_base_folder': 'dependencies_folder', 1234 'file_info': { 1235 'plat1': { 1236 'cloud_storage_hash': 'hash11', 1237 'download_path': '../../relative/dep1/path1', 1238 'local_paths': ['../../../relative/local/path11', 1239 '../../../relative/local/path12']}, 1240 'plat2': { 1241 'cloud_storage_hash': 'hash12', 1242 'download_path': '../../new/dep1/path2', 1243 'local_paths': ['../../../relative/local/path21', 1244 '../../../relative/local/path22']}}}, 1245 'dep2': {'cloud_storage_bucket': 'bucket2', 1246 'file_info': { 1247 'plat1': { 1248 'cloud_storage_hash': 'hash21', 1249 'download_path': '../../relative/dep2/path1', 1250 'local_paths': ['../../../relative/local/path31', 1251 '../../../relative/local/path32']}, 1252 'plat2': { 1253 'cloud_storage_hash': 'hash22', 1254 'download_path': '../../relative/dep2/path2'}}}} 1255 config._SetPlatformData('dep1', 'plat2', 'download_path', 1256 '../../new/dep1/path2') 1257 self.assertEqual(updated_cs_dependencies, config._config_data) 1258 1259 def testSetPlatformDataLocalPathSuccess(self): 1260 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1261 updated_cs_dependencies = { 1262 'dep1': {'cloud_storage_bucket': 'bucket1', 1263 'cloud_storage_base_folder': 'dependencies_folder', 1264 'file_info': { 1265 'plat1': { 1266 'cloud_storage_hash': 'hash11', 1267 'download_path': '../../relative/dep1/path1', 1268 'local_paths': ['../../../relative/local/path11', 1269 '../../../relative/local/path12']}, 1270 'plat2': { 1271 'cloud_storage_hash': 'hash12', 1272 'download_path': '../../relative/dep1/path2', 1273 'local_paths': ['../../new/relative/local/path21', 1274 '../../new/relative/local/path22']}}}, 1275 'dep2': {'cloud_storage_bucket': 'bucket2', 1276 'file_info': { 1277 'plat1': { 1278 'cloud_storage_hash': 'hash21', 1279 'download_path': '../../relative/dep2/path1', 1280 'local_paths': ['../../../relative/local/path31', 1281 '../../../relative/local/path32']}, 1282 'plat2': { 1283 'cloud_storage_hash': 'hash22', 1284 'download_path': '../../relative/dep2/path2'}}}} 1285 config._SetPlatformData('dep1', 'plat2', 'local_paths', 1286 ['../../new/relative/local/path21', 1287 '../../new/relative/local/path22']) 1288 self.assertEqual(updated_cs_dependencies, config._config_data) 1289 1290 def testGetPlatformDataFailure(self): 1291 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1292 self.assertRaises(ValueError, config._GetPlatformData, 'missing_dep', 1293 'plat2', 'cloud_storage_bucket') 1294 self.assertEqual(self.dependencies, config._config_data) 1295 self.assertRaises(ValueError, config._GetPlatformData, 'dep1', 1296 'missing_plat', 'cloud_storage_bucket') 1297 self.assertEqual(self.dependencies, config._config_data) 1298 1299 def testGetPlatformDataDictSuccess(self): 1300 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1301 self.assertEqual(self.platform_dict, 1302 config._GetPlatformData('dep1', 'plat2')) 1303 self.assertEqual(self.dependencies, config._config_data) 1304 1305 def testGetPlatformDataCloudStorageBucketSuccess(self): 1306 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1307 self.assertEqual(self.cs_bucket, config._GetPlatformData( 1308 'dep1', 'plat2', 'cloud_storage_bucket')) 1309 self.assertEqual(self.dependencies, config._config_data) 1310 1311 def testGetPlatformDataCloudStorageBaseFolderSuccess(self): 1312 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1313 self.assertEqual(self.cs_base_folder, config._GetPlatformData( 1314 'dep1', 'plat2', 'cloud_storage_base_folder')) 1315 self.assertEqual(self.dependencies, config._config_data) 1316 1317 def testGetPlatformDataHashSuccess(self): 1318 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1319 self.assertEqual(self.cs_hash, config._GetPlatformData( 1320 'dep1', 'plat2', 'cloud_storage_hash')) 1321 self.assertEqual(self.dependencies, config._config_data) 1322 1323 def testGetPlatformDataDownloadPathSuccess(self): 1324 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1325 self.assertEqual(self.download_path, config._GetPlatformData( 1326 'dep1', 'plat2', 'download_path')) 1327 self.assertEqual(self.dependencies, config._config_data) 1328 1329 def testGetPlatformDataLocalPathSuccess(self): 1330 config = dependency_manager.BaseConfig(self.file_path, writable=True) 1331 self.assertEqual(self.local_paths, config._GetPlatformData( 1332 'dep1', 'plat2', 'local_paths')) 1333 self.assertEqual(self.dependencies, config._config_data) 1334 1335 class BaseConfigTest(unittest.TestCase): 1336 """ Subclassable unittests for BaseConfig. 1337 For subclasses: override setUp, GetConfigDataFromDict, 1338 and EndToEndExpectedConfigData as needed. 1339 1340 setUp must set the following properties: 1341 self.config_type: String returnedd from GetConfigType in config subclass. 1342 self.config_class: the class for the config subclass. 1343 self.config_module: importable module for the config subclass. 1344 self.empty_dict: expected dictionary for an empty config, as it would be 1345 stored in a json file. 1346 self.one_dep_dict: example dictionary for a config with one dependency, 1347 as it would be stored in a json file. 1348 """ 1349 def setUp(self): 1350 self.config_type = 'BaseConfig' 1351 self.config_class = dependency_manager.BaseConfig 1352 self.config_module = 'dependency_manager.base_config' 1353 1354 self.empty_dict = {'config_type': self.config_type, 1355 'dependencies': {}} 1356 1357 dependency_dict = { 1358 'dep': { 1359 'cloud_storage_base_folder': 'cs_base_folder1', 1360 'cloud_storage_bucket': 'bucket1', 1361 'file_info': { 1362 'plat1_arch1': { 1363 'cloud_storage_hash': 'hash111', 1364 'download_path': 'download_path111', 1365 'cs_remote_path': 'cs_path111', 1366 'version_in_cs': 'version_111', 1367 'local_paths': ['local_path1110', 'local_path1111'] 1368 }, 1369 'plat1_arch2': { 1370 'cloud_storage_hash': 'hash112', 1371 'download_path': 'download_path112', 1372 'cs_remote_path': 'cs_path112', 1373 'local_paths': ['local_path1120', 'local_path1121'] 1374 }, 1375 'win_arch1': { 1376 'cloud_storage_hash': 'hash1w1', 1377 'download_path': 'download\\path\\1w1', 1378 'cs_remote_path': 'cs_path1w1', 1379 'local_paths': ['local\\path\\1w10', 'local\\path\\1w11'] 1380 }, 1381 'all_the_variables': { 1382 'cloud_storage_hash': 'hash111', 1383 'download_path': 'download_path111', 1384 'cs_remote_path': 'cs_path111', 1385 'version_in_cs': 'version_111', 1386 'path_in_archive': 'path/in/archive', 1387 'local_paths': ['local_path1110', 'local_path1111'] 1388 } 1389 } 1390 } 1391 } 1392 self.one_dep_dict = {'config_type': self.config_type, 1393 'dependencies': dependency_dict} 1394 1395 def GetConfigDataFromDict(self, config_dict): 1396 return config_dict.get('dependencies', {}) 1397 1398 @mock.patch('os.path') 1399 @mock.patch('__builtin__.open') 1400 def testInitBaseProperties(self, open_mock, path_mock): 1401 # Init is not meant to be overridden, so we should be mocking the 1402 # base_config's json module, even in subclasses. 1403 json_module = 'dependency_manager.base_config.json' 1404 with mock.patch(json_module) as json_mock: 1405 json_mock.load.return_value = self.empty_dict.copy() 1406 config = self.config_class('file_path') 1407 self.assertEqual('file_path', config._config_path) 1408 self.assertEqual(self.config_type, config.GetConfigType()) 1409 self.assertEqual(self.GetConfigDataFromDict(self.empty_dict), 1410 config._config_data) 1411 1412 1413 @mock.patch('dependency_manager.dependency_info.DependencyInfo') 1414 @mock.patch('os.path') 1415 @mock.patch('__builtin__.open') 1416 def testInitWithDependencies(self, open_mock, path_mock, dep_info_mock): 1417 # Init is not meant to be overridden, so we should be mocking the 1418 # base_config's json module, even in subclasses. 1419 json_module = 'dependency_manager.base_config.json' 1420 with mock.patch(json_module) as json_mock: 1421 json_mock.load.return_value = self.one_dep_dict 1422 config = self.config_class('file_path') 1423 self.assertEqual('file_path', config._config_path) 1424 self.assertEqual(self.config_type, config.GetConfigType()) 1425 self.assertEqual(self.GetConfigDataFromDict(self.one_dep_dict), 1426 config._config_data) 1427 1428 def testFormatPath(self): 1429 self.assertEqual(None, self.config_class._FormatPath(None)) 1430 self.assertEqual('', self.config_class._FormatPath('')) 1431 self.assertEqual('some_string', 1432 self.config_class._FormatPath('some_string')) 1433 1434 expected_path = os.path.join('some', 'file', 'path') 1435 self.assertEqual(expected_path, 1436 self.config_class._FormatPath('some/file/path')) 1437 self.assertEqual(expected_path, 1438 self.config_class._FormatPath('some\\file\\path')) 1439 1440 @mock.patch('dependency_manager.base_config.json') 1441 @mock.patch('dependency_manager.dependency_info.DependencyInfo') 1442 @mock.patch('os.path.exists') 1443 @mock.patch('__builtin__.open') 1444 def testIterDependenciesError( 1445 self, open_mock, exists_mock, dep_info_mock, json_mock): 1446 # Init is not meant to be overridden, so we should be mocking the 1447 # base_config's json module, even in subclasses. 1448 json_mock.load.return_value = self.one_dep_dict 1449 config = self.config_class('file_path', writable=True) 1450 self.assertEqual(self.GetConfigDataFromDict(self.one_dep_dict), 1451 config._config_data) 1452 self.assertTrue(config._writable) 1453 with self.assertRaises(dependency_manager.ReadWriteError): 1454 for _ in config.IterDependencyInfo(): 1455 pass 1456 1457 @mock.patch('dependency_manager.base_config.json') 1458 @mock.patch('dependency_manager.dependency_info.DependencyInfo') 1459 @mock.patch('os.path.exists') 1460 @mock.patch('__builtin__.open') 1461 def testIterDependencies( 1462 self, open_mock, exists_mock, dep_info_mock, json_mock): 1463 json_mock.load.return_value = self.one_dep_dict 1464 config = self.config_class('file_path') 1465 self.assertEqual(self.GetConfigDataFromDict(self.one_dep_dict), 1466 config._config_data) 1467 expected_dep_info = ['dep_info0', 'dep_info1', 'dep_info2'] 1468 dep_info_mock.side_effect = expected_dep_info 1469 expected_calls = [ 1470 mock.call('dep', 'plat1_arch1', 'file_path', cs_bucket='bucket1', 1471 cs_hash='hash111', download_path='download_path111', 1472 cs_remote_path='cs_path111', 1473 local_paths=['local_path1110', 'local_path1111']), 1474 mock.call('dep', 'plat1_arch1', 'file_path', cs_bucket='bucket1', 1475 cs_hash='hash112', download_path='download_path112', 1476 cs_remote_path='cs_path112', 1477 local_paths=['local_path1120', 'local_path1121']), 1478 mock.call('dep', 'win_arch1', 'file_path', cs_bucket='bucket1', 1479 cs_hash='hash1w1', 1480 download_path=os.path.join('download', 'path', '1w1'), 1481 cs_remote_path='cs_path1w1', 1482 local_paths=[os.path.join('download', 'path', '1w10'), 1483 os.path.join('download', 'path', '1w11')])] 1484 deps_seen = [] 1485 for dep_info in config.IterDependencyInfo(): 1486 deps_seen.append(dep_info) 1487 dep_info_mock.assert_call_args(expected_calls) 1488 self.assertItemsEqual(expected_dep_info, deps_seen) 1489