async def test_cant_reach_refresh_server(drive: DriveSource, server: SimulationServer, config: Config, time): config.override(Setting.TOKEN_SERVER_HOSTS, "http://lkasdpoiwehjhcty.com") drive.drivebackend.creds._secret = None time.advanceDay() with pytest.raises(CredRefreshMyError) as error: await drive.get() assert error.value.data() == {"reason": "Couldn't communicate with lkasdpoiwehjhcty.com"}
def test_send_error_reports(): assert Config().validate({Setting.SEND_ERROR_REPORTS: False}) == defaultAnd( {Setting.SEND_ERROR_REPORTS: False}) assert Config().validate({Setting.SEND_ERROR_REPORTS: True}) == defaultAnd( {Setting.SEND_ERROR_REPORTS: True}) assert Config().validate( {Setting.SEND_ERROR_REPORTS: None}) == defaultAnd()
def test_validate_regex(): assert Config().validate({Setting.DRIVE_IPV4: "192.168.1.1"}) == defaultAnd( {Setting.DRIVE_IPV4: "192.168.1.1"}) with raises(InvalidConfigurationValue): Config().validate({Setting.DRIVE_IPV4: -1}) with raises(InvalidConfigurationValue): Config().validate({Setting.DRIVE_IPV4: "192.168.1"})
async def test_update_ignore(reader: ReaderHelper, time: FakeTime, coord: Coordinator, config: Config, supervisor: SimulatedSupervisor, ha: HaSource, drive: DriveSource): config.override(Setting.IGNORE_UPGRADE_SNAPSHOTS, True) config.override(Setting.DAYS_BETWEEN_SNAPSHOTS, 0) # make an ignored_snapshot slug = await supervisor.createSnapshot( { 'name': "Ignore_me", 'folders': ['homeassistant'], 'addons': [] }, date=time.now()) await coord.sync() assert len(await drive.get()) == 0 assert len(await ha.get()) == 1 assert len(coord.snapshots()) == 1 # Disable Drive Upload update = { "ignore": False, "slug": slug, } await reader.postjson("ignore", json=update) await coord.waitForSyncToFinish() assert len(coord.snapshots()) == 1 assert len(await drive.get()) == 1 assert len(await ha.get()) == 1
async def test_update_disable_drive(reader: ReaderHelper, server, coord: Coordinator, config: Config, drive_requests: DriveRequests): # Disable drive drive_requests.creds = None os.remove(config.get(Setting.CREDENTIALS_FILE_PATH)) assert not coord.enabled() await coord.sync() assert len(coord.snapshots()) == 0 # Disable Drive Upload update = { "config": { Setting.ENABLE_DRIVE_UPLOAD.value: False }, "snapshot_folder": "" } assert await reader.postjson("saveconfig", json=update) == { 'message': 'Settings saved', "reload_page": True } assert config.get(Setting.ENABLE_DRIVE_UPLOAD) is False # Verify the app is working fine. assert coord.enabled() await coord.waitForSyncToFinish() assert len(coord.snapshots()) == 1
async def test_update_non_ui_setting(reader: ReaderHelper, server, session, coord: Coordinator, folder_finder: FolderFinder, config: Config): await coord.sync() # Change some config update = { "config": { "new_snapshot_timeout_seconds": 10 }, "snapshot_folder": "" } assert await reader.postjson("saveconfig", json=update) == { 'message': 'Settings saved', "reload_page": False } assert config.get(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS) == 10 update = {"config": {"max_snapshots_in_hassio": 1}, "snapshot_folder": ""} assert await reader.postjson("saveconfig", json=update) == { 'message': 'Settings saved', "reload_page": False } assert config.get(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS) == 10
async def test_start_on_boot(ha: HaSource, time, interceptor: RequestInterceptor, config: Config, supervisor: SimulatedSupervisor) -> None: boot_slug = "boot_slug" supervisor.installAddon(boot_slug, "Start on boot", boot=True, started=False) no_boot_slug = "no_boot_slug" supervisor.installAddon(no_boot_slug, "Don't start on boot", boot=False, started=False) config.override(Setting.STOP_ADDONS, ",".join([boot_slug, no_boot_slug])) config.override(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS, 0.001) assert supervisor.addon(boot_slug)["state"] == "stopped" assert supervisor.addon(no_boot_slug)["state"] == "stopped" async with supervisor._snapshot_inner_lock: await ha.create(CreateOptions(time.now(), "Test Name")) assert supervisor.addon(boot_slug)["state"] == "stopped" assert supervisor.addon(no_boot_slug)["state"] == "stopped" await ha._pending_snapshot_task assert supervisor.addon(boot_slug)["state"] == "started" assert supervisor.addon(no_boot_slug)["state"] == "stopped" assert len(await ha.get()) == 1 assert not interceptor.urlWasCalled(URL_MATCH_START_ADDON) assert not interceptor.urlWasCalled(URL_MATCH_STOP_ADDON)
async def test_manual_creds(reader: ReaderHelper, ui_server: UiServer, config: Config, server, session, drive: DriveSource): # get the auth url req_path = "manualauth?client_id={}&client_secret={}".format(config.get( Setting.DEFAULT_DRIVE_CLIENT_ID), config.get(Setting.DEFAULT_DRIVE_CLIENT_SECRET)) data = await reader.getjson(req_path) assert "auth_url" in data # request the auth code from "google" async with session.get(data["auth_url"], allow_redirects=False) as resp: code = (await resp.json())["code"] drive.saveCreds(None) assert not drive.enabled() # Pass the auth code to generate creds req_path = "manualauth?code={}".format(code) assert await reader.getjson(req_path) == { 'auth_url': "index?fresh=true" } # verify creds are saved and drive is enabled assert drive.enabled() # Now verify that bad creds fail predictably req_path = "manualauth?code=bad_code" assert await reader.getjson(req_path) == { 'error': 'Your Google Drive credentials have expired. Please reauthorize with Google Drive through the Web UI.' }
async def test_update_non_ui_setting(reader: ReaderHelper, server, session, coord: Coordinator, folder_finder: FolderFinder, config: Config): await coord.sync() # Change some config update = { "config": { Setting.NEW_BACKUP_TIMEOUT_SECONDS.value: 10 }, "backup_folder": "" } assert await reader.postjson("saveconfig", json=update) == { 'message': 'Settings saved', "reload_page": False } assert config.get(Setting.NEW_BACKUP_TIMEOUT_SECONDS) == 10 update = { "config": { Setting.MAX_BACKUPS_IN_HA.value: 1 }, "backup_folder": "" } assert await reader.postjson("saveconfig", json=update) == { 'message': 'Settings saved', "reload_page": False } assert config.get(Setting.NEW_BACKUP_TIMEOUT_SECONDS) == 10
async def test_failed_snapshot_retry(ha: HaSource, time: FakeTime, config: Config, supervisor: SimulatedSupervisor, interceptor: RequestInterceptor): # create a blocking snapshot interceptor.setError(URL_MATCH_SNAPSHOT_FULL, 524) config.override(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS, 0) await supervisor.toggleBlockSnapshot() snapshot_immediate = await ha.create(CreateOptions(time.now(), "Some Name")) assert isinstance(snapshot_immediate, PendingSnapshot) assert snapshot_immediate.name() == "Some Name" assert not ha.check() assert not snapshot_immediate.isFailed() await supervisor.toggleBlockSnapshot() # let the snapshot attempt to complete await asyncio.wait({ha._pending_snapshot_task}) # verify it failed with the expected http error assert snapshot_immediate.isFailed() assert snapshot_immediate._exception.status == 524 assert ha.check() assert not ha.check() time.advance(seconds=config.get(Setting.FAILED_SNAPSHOT_TIMEOUT_SECONDS)) # should trigger a sync after the failed snapshot timeout assert ha.check() await ha.get() assert not ha.check()
async def test_pending_snapshot_replaces_original( time, ha: HaSource, config: Config, supervisor: SimulatedSupervisor): # now configure a snapshto to start outside of the addon config.override(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS, 100) await supervisor.toggleBlockSnapshot() with pytest.raises(SnapshotInProgress): await ha.create(CreateOptions(time.now(), "Ignored")) snapshot_immediate = (await ha.get())['pending'] await supervisor.toggleBlockSnapshot() assert isinstance(snapshot_immediate, PendingSnapshot) assert snapshot_immediate.name() == "Pending Snapshot" assert ha.check() assert ha.pending_snapshot is snapshot_immediate assert await ha.get() == {snapshot_immediate.slug(): snapshot_immediate} # create a new snapshot behind the scenes, the pending snapshot should get replaced with the new one slug = (await ha.harequests.createSnapshot({ 'name': "Suddenly Appears", "hardlock": True }))['slug'] results = await ha.get() assert len(results) == 1 assert slug in results assert results[slug].name() == "Suddenly Appears" assert not results[slug].retained()
async def test_failed_snapshot(time, ha: HaSource, supervisor: SimulatedSupervisor, config: Config, interceptor: RequestInterceptor): # create a blocking snapshot interceptor.setError(URL_MATCH_SNAPSHOT_FULL, 524) config.override(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS, 0) await supervisor.toggleBlockSnapshot() snapshot_immediate = await ha.create(CreateOptions(time.now(), "Some Name")) assert isinstance(snapshot_immediate, PendingSnapshot) assert snapshot_immediate.name() == "Some Name" assert not ha.check() assert not snapshot_immediate.isFailed() await supervisor.toggleBlockSnapshot() # let the snapshot attempt to complete await asyncio.wait({ha._pending_snapshot_task}) # verify it failed with the expected http error assert snapshot_immediate.isFailed() assert snapshot_immediate._exception.status == 524 snapshots = list((await ha.get()).values()) assert len(snapshots) == 1 assert snapshots[0] is snapshot_immediate # verify we can create a new snapshot immediately interceptor.clear() await ha.create(CreateOptions(time.now(), "Some Name")) assert len(await ha.get()) == 1
async def test_cred_refresh_upgrade_default_client(drive: DriveSource, server: SimulationServer, time: FakeTime, config: Config): return # TODO: Enable this when we start removing the default client_secret config.override(Setting.DEFAULT_DRIVE_CLIENT_ID, server.getSetting("drive_client_id")) creds = server.getCurrentCreds() creds_with_secret = server.getCurrentCreds() creds_with_secret._secret = server.getSetting("drive_client_secret") with open(config.get(Setting.CREDENTIALS_FILE_PATH), "w") as f: json.dump(creds_with_secret.serialize(), f) # reload the creds drive.drivebackend.tryLoadCredentials() # Verify the "client secret" was removed with open(config.get(Setting.CREDENTIALS_FILE_PATH)) as f: saved_creds = json.load(f) assert saved_creds == creds.serialize() await drive.get() old_creds = drive.drivebackend.cred_bearer await drive.get() assert old_creds == drive.drivebackend.cred_bearer time.advanceDay() await drive.get() assert old_creds != drive.drivebackend.cred_bearer
async def test_partial_snapshot(ha, time, server, config: Config): config.override(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS, 100) for folder in all_folders: config.override(Setting.EXCLUDE_FOLDERS, folder) snapshot: HASnapshot = await ha.create( CreateOptions(time.now(), "Test Name")) assert snapshot.snapshotType() == "partial" for search in all_folders: if search == folder: assert search not in snapshot.details()['folders'] else: assert search in snapshot.details()['folders'] for addon in all_addons: config.override(Setting.EXCLUDE_ADDONS, addon['slug']) snapshot: HASnapshot = await ha.create( CreateOptions(time.now(), "Test Name")) assert snapshot.snapshotType() == "partial" list_of_addons = [] for included in snapshot.details()['addons']: list_of_addons.append(included['slug']) for search in list_of_addons: if search == addon: assert search not in list_of_addons else: assert search in list_of_addons # excluding addon/folders that don't exist should actually make a full snapshot config.override(Setting.EXCLUDE_ADDONS, "none,of.these,are.addons") config.override(Setting.EXCLUDE_FOLDERS, "not,folders,either") snapshot: HASnapshot = await ha.create( CreateOptions(time.now(), "Test Name")) assert snapshot.snapshotType() == "full"
async def test_getstatus_sync(reader, config: Config, snapshot: Snapshot, time: FakeTime): data = await reader.getjson("getstatus") assert data['firstSync'] is False assert data['folder_id'] is not None assert data['last_error'] is None assert data['last_snapshot_text'] != "Never" assert data['next_snapshot_text'] != "right now" assert len(data['snapshots']) == 1 assert data['sources'][SOURCE_GOOGLE_DRIVE] == { 'deletable': 1, 'name': SOURCE_GOOGLE_DRIVE, 'retained': 0, 'snapshots': 1, 'latest': time.asRfc3339String(time.now()), 'size': data['sources'][SOURCE_GOOGLE_DRIVE]['size'], 'enabled': True, 'max': config.get(Setting.MAX_SNAPSHOTS_IN_GOOGLE_DRIVE), 'title': "Google Drive" } assert data['sources'][SOURCE_HA] == { 'deletable': 1, 'name': SOURCE_HA, 'retained': 0, 'snapshots': 1, 'latest': time.asRfc3339String(time.now()), 'size': data['sources'][SOURCE_HA]['size'], 'enabled': True, 'max': config.get(Setting.MAX_SNAPSHOTS_IN_HASSIO), 'title': "Home Assistant", 'free_space': "0.0 B" } assert len(data['sources']) == 2
async def test_cant_reach_refresh_server(drive: DriveSource, server: SimulationServer, config: Config, time): config.override(Setting.REFRESH_URL, "http://lkasdpoiwehjhcty.com") drive.drivebackend.creds._secret = None time.advanceDay() with pytest.raises(CredRefreshMyError) as error: await drive.get() assert error.value.data() == {"reason": "Unable to connect to https://habackup.io"}
async def test_update_error_reports_false(reader, ui_server, config: Config, supervisor: SimulatedSupervisor): assert config.get(Setting.SEND_ERROR_REPORTS) is False assert not config.isExplicit(Setting.SEND_ERROR_REPORTS) assert await reader.getjson("errorreports?send=false") == {'message': 'Configuration updated'} assert config.get(Setting.SEND_ERROR_REPORTS) is False assert config.isExplicit(Setting.SEND_ERROR_REPORTS) assert supervisor._options["send_error_reports"] is False
async def test_only_send_duplicates(time, debug_worker: DebugWorker, config: Config, global_info: GlobalInfo, server, error_store: ErrorStore): config.override(Setting.SEND_ERROR_REPORTS, True) config.override(Setting.DRIVE_HOST_NAME, "localhost") global_info.failed(Exception("boom1")) firstExceptionTime = time.now() await debug_worker.doWork() report = error_store.last_error assert report['report']["error"] == getLogger("test").formatException( Exception("boom1")) assert report['report']["time"] == firstExceptionTime.isoformat() # Same exception shouldn't cause us to send the error report again time.advance(days=1) global_info.failed(Exception("boom1")) await debug_worker.doWork() report = error_store.last_error assert report['report']["error"] == getLogger("test").formatException( Exception("boom1")) assert report['report']["time"] == firstExceptionTime.isoformat() # Btu a new one will send a new report global_info.failed(Exception("boom2")) await debug_worker.doWork() report = error_store.last_error assert report['report']["error"] == getLogger("test").formatException( Exception("boom2")) assert report['report']["time"] == time.now().isoformat()
async def test_update_sync_interval(reader, ui_server, config: Config, supervisor: SimulatedSupervisor): # Make sure the default saves nothing update = { "config": { "max_sync_interval_seconds": '1 hour', }, "snapshot_folder": "unused" } assert await reader.postjson("saveconfig", json=update) == { 'message': 'Settings saved' } assert config.get(Setting.MAX_SYNC_INTERVAL_SECONDS) == 60 * 60 assert "max_sync_interval_seconds" not in supervisor._options # Update custom update = { "config": { "max_sync_interval_seconds": '2 hours', }, "snapshot_folder": "unused" } assert await reader.postjson("saveconfig", json=update) == { 'message': 'Settings saved' } assert config.get(Setting.MAX_SYNC_INTERVAL_SECONDS) == 60 * 60 * 2 assert supervisor._options["max_sync_interval_seconds"] == 60 * 60 * 2
async def test_snapshot_to_backup_upgrade_use_old_values( reader: ReaderHelper, time: FakeTime, coord: Coordinator, config: Config, supervisor: SimulatedSupervisor, ha: HaSource, drive: DriveSource, data_cache: DataCache, updater: HaUpdater): """ Test the path where a user upgrades from the addon before the backup rename and then chooses to use the old names""" status = await reader.getjson("getstatus") assert not status["warn_backup_upgrade"] # simulate upgrading config supervisor._options = {Setting.DEPRECTAED_MAX_BACKUPS_IN_HA.value: 7} await coord.sync() assert Setting.CALL_BACKUP_SNAPSHOT.value in supervisor._options assert config.get(Setting.CALL_BACKUP_SNAPSHOT) status = await reader.getjson("getstatus") assert status["warn_backup_upgrade"] assert not data_cache.checkFlag(UpgradeFlags.NOTIFIED_ABOUT_BACKUP_RENAME) assert not updater._trigger_once # simulate user clicking the button to use new names assert await reader.getjson("callbackupsnapshot?switch=false") == { 'message': 'Configuration updated' } assert data_cache.checkFlag(UpgradeFlags.NOTIFIED_ABOUT_BACKUP_RENAME) status = await reader.getjson("getstatus") assert not status["warn_backup_upgrade"] assert config.get(Setting.CALL_BACKUP_SNAPSHOT)
def test_GenerationalConfig() -> None: assert Config().getGenerationalConfig() is None assert Config().override(Setting.GENERATIONAL_DAYS, 5).getGenerationalConfig() == GenConfig(days=5) assert Config().override(Setting.GENERATIONAL_WEEKS, 3).getGenerationalConfig() == GenConfig(days=1, weeks=3) assert Config().override(Setting.GENERATIONAL_MONTHS, 3).getGenerationalConfig() == GenConfig(days=1, months=3) assert Config().override(Setting.GENERATIONAL_YEARS, 3).getGenerationalConfig() == GenConfig(days=1, years=3) assert Config().override(Setting.GENERATIONAL_DELETE_EARLY, True).override( Setting.GENERATIONAL_DAYS, 2).getGenerationalConfig() == GenConfig(days=2, aggressive=True) assert Config().override(Setting.GENERATIONAL_DAYS, 1).override( Setting.GENERATIONAL_DAY_OF_YEAR, 3).getGenerationalConfig() == GenConfig(days=1, day_of_year=3) assert Config().override(Setting.GENERATIONAL_DAYS, 1).override( Setting.GENERATIONAL_DAY_OF_MONTH, 3).getGenerationalConfig() == GenConfig(days=1, day_of_month=3) assert Config().override(Setting.GENERATIONAL_DAYS, 1).override( Setting.GENERATIONAL_DAY_OF_WEEK, "tue").getGenerationalConfig() == GenConfig(days=1, day_of_week="tue") assert Config().override(Setting.GENERATIONAL_DAY_OF_MONTH, 3).override( Setting.GENERATIONAL_DAY_OF_WEEK, "tue").override( Setting.GENERATIONAL_DAY_OF_YEAR, "4").getGenerationalConfig() is None
async def test_dont_purge_pending_backup(ha: HaSource, time, config: Config, supervisor: SimulatedSupervisor, model: Model, interceptor): config.override(Setting.MAX_BACKUPS_IN_HA, 4) await ha.create(CreateOptions(time.now(), "Test Name 1")) await ha.create(CreateOptions(time.now(), "Test Name 2")) await ha.create(CreateOptions(time.now(), "Test Name 3")) await ha.create(CreateOptions(time.now(), "Test Name 4")) await model.sync(time.now()) config.override(Setting.NEW_BACKUP_TIMEOUT_SECONDS, 0.1) interceptor.setSleep(URL_MATCH_BACKUP_FULL, sleep=2) await ha.create(CreateOptions(time.now(), "Test Name")) backups = list((await ha.get()).values()) assert len(backups) == 5 backup = backups[4] assert isinstance(backup, PendingBackup) # no backup should get purged yet because the ending backup isn't considered for purging. await model.sync(time.now()) backups = list((await ha.get()).values()) assert len(backups) == 5 # Wait for the backup to finish, then verify one gets purged. await ha._pending_backup_task await model.sync(time.now()) backups = list((await ha.get()).values()) assert len(backups) == 4
async def test_failed_backup(time, ha: HaSource, supervisor: SimulatedSupervisor, config: Config, interceptor: RequestInterceptor): # create a blocking backup interceptor.setError(URL_MATCH_BACKUP_FULL, 524) config.override(Setting.NEW_BACKUP_TIMEOUT_SECONDS, 0) await supervisor.toggleBlockBackup() backup_immediate = await ha.create(CreateOptions(time.now(), "Some Name")) assert isinstance(backup_immediate, PendingBackup) assert backup_immediate.name() == "Some Name" assert not ha.check() assert not backup_immediate.isFailed() await supervisor.toggleBlockBackup() # let the backup attempt to complete await asyncio.wait({ha._pending_backup_task}) # verify it failed with the expected http error assert backup_immediate.isFailed() assert backup_immediate._exception.status == 524 backups = list((await ha.get()).values()) assert len(backups) == 1 assert backups[0] is backup_immediate # verify we can create a new backup immediately interceptor.clear() await ha.create(CreateOptions(time.now(), "Some Name")) assert len(await ha.get()) == 1
async def test_dont_purge_pending_snapshot(ha: HaSource, time, config: Config, supervisor: SimulatedSupervisor, model: Model, interceptor): config.override(Setting.MAX_SNAPSHOTS_IN_HASSIO, 4) await ha.create(CreateOptions(time.now(), "Test Name 1")) await ha.create(CreateOptions(time.now(), "Test Name 2")) await ha.create(CreateOptions(time.now(), "Test Name 3")) await ha.create(CreateOptions(time.now(), "Test Name 4")) await model.sync(time.now()) config.override(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS, 0.1) interceptor.setSleep(URL_MATCH_SNAPSHOT_FULL, sleep=2) await ha.create(CreateOptions(time.now(), "Test Name")) snapshots = list((await ha.get()).values()) assert len(snapshots) == 5 snapshot = snapshots[4] assert isinstance(snapshot, PendingSnapshot) # no snapshot should get purged yet because the ending snapshot isn't considered for purging. await model.sync(time.now()) snapshots = list((await ha.get()).values()) assert len(snapshots) == 5 # Wait for the snapshot to finish, then verify one gets purged. await ha._pending_snapshot_task await model.sync(time.now()) snapshots = list((await ha.get()).values()) assert len(snapshots) == 4
async def test_update_backups_old_names(updater: HaUpdater, server, backup: Backup, time: FakeTime, supervisor: SimulatedSupervisor, config: Config): config.override(Setting.CALL_BACKUP_SNAPSHOT, True) await updater.update() assert not updater._stale() assert updater._state() == "backed_up" verifyEntity(supervisor, "binary_sensor.snapshots_stale", "off", {"friendly_name": "Snapshots Stale", "device_class": "problem"}) date = '1985-12-06T05:00:00+00:00' verifyEntity(supervisor, "sensor.snapshot_backup", "backed_up", { 'friendly_name': 'Snapshot State', 'last_snapshot': date, 'snapshots': [{ 'date': date, 'name': backup.name(), 'size': backup.sizeString(), 'state': backup.status(), 'slug': backup.slug() } ], 'snapshots_in_google_drive': 1, 'snapshots_in_home_assistant': 1, 'snapshots_in_hassio': 1, 'size_in_home_assistant': Estimator.asSizeString(backup.size()), 'size_in_google_drive': Estimator.asSizeString(backup.size()) })
async def test_delayed_start_give_up(supervisor: SimulatedSupervisor, addon_stopper: AddonStopper, config: Config, interceptor: RequestInterceptor, time: FakeTime) -> None: slug1 = "test_slug_1" supervisor.installAddon(slug1, "Test decription") config.override(Setting.STOP_ADDONS, ",".join([slug1])) addon_stopper.allowRun() addon_stopper.must_start = set() assert supervisor.addon(slug1)["state"] == "started" await addon_stopper.stopAddons("ignore") assert supervisor.addon(slug1)["state"] == "stopped" assert getSaved(config) == ({slug1}, set()) # start the addon again, which simluates the supervisor's tendency to report an addon as started right after stopping it. supervisor.addon(slug1)["state"] = "started" await addon_stopper.check() await addon_stopper.startAddons() assert getSaved(config) == ({slug1}, set()) time.advance(seconds=30) await addon_stopper.check() assert getSaved(config) == ({slug1}, set()) time.advance(seconds=30) await addon_stopper.check() assert getSaved(config) == ({slug1}, set()) # Should clear saved state after this, since it stops checking after 2 minutes. time.advance(seconds=100) await addon_stopper.check() assert getSaved(config) == (set(), set())
async def test_drive_dns_resolution_error(drive: DriveSource, config: Config, time): config.override(Setting.DRIVE_URL, "http://fsdfsdasdasdf.saasdsdfsdfsd.com:2567") with pytest.raises(GoogleCantConnect): await drive.get() assert time.sleeps == []
async def test_purge_before_upload(source: HelperTestSource, dest: HelperTestSource, time: FakeTime, model: Model, data_cache: DataCache, simple_config: Config): source.setMax(2) dest.setMax(2) older = source.insert("older", time.now() - timedelta(days=7), slug="older") oldest = source.insert("oldest", time.now() - timedelta(days=14), slug="oldest") await model.sync(time.now() - timedelta(days=7)) source.allow_create = False dest.allow_save = False dest.reset() source.reset() # trying to sync now should do nothing. with pytest.raises(IntentionalFailure): await model.sync(time.now()) source.assertThat(current=2) dest.assertThat(current=2) simple_config.override(Setting.DELETE_BEFORE_NEW_BACKUP, True) # Trying to sync should delete the backup before syncing and then fail to create a new one. with pytest.raises(IntentionalFailure): await model.sync(time.now()) source.assertThat(deleted=1, current=1) assert oldest.slug() not in (await source.get()).keys() dest.assertThat(current=2) # Trying to do it again should do nothing (eg not delete another backup) with pytest.raises(IntentionalFailure): await model.sync(time.now()) source.assertThat(deleted=1, current=1) dest.assertThat(current=2) # let the new source backup get created, which then deletes the destination but fails to save source.allow_create = True with pytest.raises(IntentionalFailure): await model.sync(time.now()) source.assertThat(deleted=1, current=2, created=1) dest.assertThat(current=1, deleted=1) assert oldest.slug() not in (await dest.get()).keys() # now let the new backup get saved. dest.allow_save = True await model.sync(time.now()) source.assertThat(deleted=1, current=2, created=1) dest.assertThat(current=2, deleted=1, saved=1) assert oldest.slug() not in (await source.get()).keys() assert older.slug() in (await source.get()).keys() assert oldest.slug() not in (await dest.get()).keys() assert older.slug() in (await dest.get()).keys()
async def test_bad_host(debug_worker: DebugWorker, config: Config): skipForWindows() config.override(Setting.DRIVE_HOST_NAME, "dasdfdfgvxcvvsoejbr.com") await debug_worker.doWork() assert debug_worker.dns_info == { 'dasdfdfgvxcvvsoejbr.com': { 'dasdfdfgvxcvvsoejbr.com': "Name or service not known" } }
async def test_dont_send_error_report(time, debug_worker: DebugWorker, config: Config, global_info: GlobalInfo, server: SimulationServer, error_store: ErrorStore): config.override(Setting.SEND_ERROR_REPORTS, False) config.override(Setting.DRIVE_HOST_NAME, "localhost") global_info.failed(Exception()) await debug_worker.doWork() assert error_store.last_error is None