async def test_pending_snapshot_timeout(time: FakeTime, ha: HaSource, config: Config, interceptor: RequestInterceptor): interceptor.setSleep(URL_MATCH_SNAPSHOT_FULL, sleep=5) config.override(Setting.NEW_SNAPSHOT_TIMEOUT_SECONDS, 1) config.override(Setting.FAILED_SNAPSHOT_TIMEOUT_SECONDS, 1) config.override(Setting.PENDING_SNAPSHOT_TIMEOUT_SECONDS, 1) snapshot_immediate: PendingSnapshot = await ha.create( CreateOptions(time.now(), "Test Name")) assert isinstance(snapshot_immediate, PendingSnapshot) assert snapshot_immediate.name() == "Test Name" assert not ha.check() assert ha.pending_snapshot is snapshot_immediate await asyncio.wait({ha._pending_snapshot_task}) assert ha.pending_snapshot is snapshot_immediate assert ha.check() assert not ha.check() time.advance(minutes=1) assert ha.check() assert len(await ha.get()) == 0 assert not ha.check() assert ha.pending_snapshot is None assert snapshot_immediate.isStale()
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_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_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_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_pending_snapshot_timeout_external( time, config, ha: HaSource, 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 not ha.check() assert ha.pending_snapshot is snapshot_immediate # should clean up after a day, since we're still waiting on the snapshot thread. time.advanceDay() assert ha.check() assert len(await ha.get()) == 0
async def test_immediate_backup_failure(time: FakeTime, ha: HaSource, config: Config, interceptor: RequestInterceptor): interceptor.setError(URL_MATCH_BACKUP_FULL, 524) with pytest.raises(ClientResponseError) as thrown: await ha.create(CreateOptions(time.now(), "Some Name")) assert thrown.value.status == 524 assert ha.pending_backup is not None backups = list((await ha.get()).values()) assert len(backups) == 1 assert backups[0].isFailed() # Failed backup should go away after it times out assert ha.check() assert not ha.check() time.advance(seconds=config.get(Setting.FAILED_BACKUP_TIMEOUT_SECONDS) + 1) assert ha.check() assert len(await ha.get()) == 0 assert not ha.check()