@@ -392,6 +392,86 @@ def test_fetch_datafile(self, _):
392392 )
393393 self .assertEqual (test_headers ['Last-Modified' ], project_config_manager .last_modified )
394394 self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
395+ self .assertTrue (project_config_manager .is_running )
396+
397+ def test_fetch_datafile__status_exception_raised (self , _ ):
398+ """ Test that config_manager keeps running if status code exception is raised when fetching datafile. """
399+ class MockExceptionResponse (object ):
400+ def raise_for_status (self ):
401+ raise requests .exceptions .RequestException ('Error Error !!' )
402+
403+ sdk_key = 'some_key'
404+ mock_logger = mock .Mock ()
405+ with mock .patch ('optimizely.config_manager.PollingConfigManager.fetch_datafile' ):
406+ project_config_manager = config_manager .PollingConfigManager (sdk_key = sdk_key , logger = mock_logger )
407+ expected_datafile_url = enums .ConfigManager .DATAFILE_URL_TEMPLATE .format (sdk_key = sdk_key )
408+ test_headers = {'Last-Modified' : 'New Time' }
409+ test_datafile = json .dumps (self .config_dict_with_features )
410+ test_response = requests .Response ()
411+ test_response .status_code = 200
412+ test_response .headers = test_headers
413+ test_response ._content = test_datafile
414+ with mock .patch ('requests.get' , return_value = test_response ):
415+ project_config_manager .fetch_datafile ()
416+
417+ self .assertEqual (test_headers ['Last-Modified' ], project_config_manager .last_modified )
418+ self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
419+
420+ # Call fetch_datafile again, but raise exception this time
421+ with mock .patch ('requests.get' , return_value = MockExceptionResponse ()) as mock_requests :
422+ project_config_manager .fetch_datafile ()
423+
424+ mock_requests .assert_called_once_with (
425+ expected_datafile_url ,
426+ headers = {'If-Modified-Since' : test_headers ['Last-Modified' ]},
427+ timeout = enums .ConfigManager .REQUEST_TIMEOUT ,
428+ )
429+ mock_logger .error .assert_called_once_with ('Fetching datafile from {} failed. Error: Error Error !!' .format (
430+ expected_datafile_url
431+ ))
432+ self .assertEqual (test_headers ['Last-Modified' ], project_config_manager .last_modified )
433+ self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
434+ # Confirm that config manager keeps running
435+ self .assertTrue (project_config_manager .is_running )
436+
437+ def test_fetch_datafile__request_exception_raised (self , _ ):
438+ """ Test that config_manager keeps running if a request exception is raised when fetching datafile. """
439+ sdk_key = 'some_key'
440+ mock_logger = mock .Mock ()
441+ with mock .patch ('optimizely.config_manager.PollingConfigManager.fetch_datafile' ):
442+ project_config_manager = config_manager .PollingConfigManager (sdk_key = sdk_key , logger = mock_logger )
443+ expected_datafile_url = enums .ConfigManager .DATAFILE_URL_TEMPLATE .format (sdk_key = sdk_key )
444+ test_headers = {'Last-Modified' : 'New Time' }
445+ test_datafile = json .dumps (self .config_dict_with_features )
446+ test_response = requests .Response ()
447+ test_response .status_code = 200
448+ test_response .headers = test_headers
449+ test_response ._content = test_datafile
450+ with mock .patch ('requests.get' , return_value = test_response ):
451+ project_config_manager .fetch_datafile ()
452+
453+ self .assertEqual (test_headers ['Last-Modified' ], project_config_manager .last_modified )
454+ self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
455+
456+ # Call fetch_datafile again, but raise exception this time
457+ with mock .patch (
458+ 'requests.get' ,
459+ side_effect = requests .exceptions .RequestException ('Error Error !!' ),
460+ ) as mock_requests :
461+ project_config_manager .fetch_datafile ()
462+
463+ mock_requests .assert_called_once_with (
464+ expected_datafile_url ,
465+ headers = {'If-Modified-Since' : test_headers ['Last-Modified' ]},
466+ timeout = enums .ConfigManager .REQUEST_TIMEOUT ,
467+ )
468+ mock_logger .error .assert_called_once_with ('Fetching datafile from {} failed. Error: Error Error !!' .format (
469+ expected_datafile_url
470+ ))
471+ self .assertEqual (test_headers ['Last-Modified' ], project_config_manager .last_modified )
472+ self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
473+ # Confirm that config manager keeps running
474+ self .assertTrue (project_config_manager .is_running )
395475
396476 def test_is_running (self , _ ):
397477 """ Test that polling thread is running after instance of PollingConfigManager is created. """
@@ -451,3 +531,58 @@ def test_fetch_datafile(self, _):
451531 )
452532
453533 self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
534+
535+ def test_fetch_datafile__request_exception_raised (self , _ ):
536+ """ Test that config_manager keeps running if a request exception is raised when fetching datafile. """
537+ datafile_access_token = 'some_token'
538+ sdk_key = 'some_key'
539+ mock_logger = mock .Mock ()
540+
541+ with mock .patch ('optimizely.config_manager.AuthDatafilePollingConfigManager.fetch_datafile' ):
542+ project_config_manager = config_manager .AuthDatafilePollingConfigManager (
543+ datafile_access_token = datafile_access_token , sdk_key = sdk_key , logger = mock_logger )
544+ expected_datafile_url = enums .ConfigManager .AUTHENTICATED_DATAFILE_URL_TEMPLATE .format (sdk_key = sdk_key )
545+ test_headers = {'Last-Modified' : 'New Time' }
546+ test_datafile = json .dumps (self .config_dict_with_features )
547+ test_response = requests .Response ()
548+ test_response .status_code = 200
549+ test_response .headers = test_headers
550+ test_response ._content = test_datafile
551+
552+ # Call fetch_datafile and assert that request was sent with correct authorization header
553+ with mock .patch ('requests.get' ,
554+ return_value = test_response ) as mock_request :
555+ project_config_manager .fetch_datafile ()
556+
557+ mock_request .assert_called_once_with (
558+ expected_datafile_url ,
559+ headers = {'Authorization' : 'Bearer {datafile_access_token}' .format (
560+ datafile_access_token = datafile_access_token )},
561+ timeout = enums .ConfigManager .REQUEST_TIMEOUT ,
562+ )
563+
564+ self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
565+
566+ # Call fetch_datafile again, but raise exception this time
567+ with mock .patch (
568+ 'requests.get' ,
569+ side_effect = requests .exceptions .RequestException ('Error Error !!' ),
570+ ) as mock_requests :
571+ project_config_manager .fetch_datafile ()
572+
573+ mock_requests .assert_called_once_with (
574+ expected_datafile_url ,
575+ headers = {
576+ 'If-Modified-Since' : test_headers ['Last-Modified' ],
577+ 'Authorization' : 'Bearer {datafile_access_token}' .format (
578+ datafile_access_token = datafile_access_token ),
579+ },
580+ timeout = enums .ConfigManager .REQUEST_TIMEOUT ,
581+ )
582+ mock_logger .error .assert_called_once_with ('Fetching datafile from {} failed. Error: Error Error !!' .format (
583+ expected_datafile_url
584+ ))
585+ self .assertEqual (test_headers ['Last-Modified' ], project_config_manager .last_modified )
586+ self .assertIsInstance (project_config_manager .get_config (), project_config .ProjectConfig )
587+ # Confirm that config manager keeps running
588+ self .assertTrue (project_config_manager .is_running )
0 commit comments