async def test_check_size_sync(coord: Coordinator, source: HelperTestSource, dest: HelperTestSource, time, fs: FsFaker, global_info: GlobalInfo): skipForWindows() fs.setFreeBytes(0) await coord.sync() assert len(coord.snapshots()) == 0 assert global_info._last_error is not None await coord.sync() assert len(coord.snapshots()) == 0 assert global_info._last_error is not None # Verify it resets the global size skip check, but gets through once global_info.setSkipSpaceCheckOnce(True) await coord.sync() assert len(coord.snapshots()) == 1 assert global_info._last_error is None assert not global_info.isSkipSpaceCheckOnce() # Next attempt to snapshot shoudl fail again. time.advance(days=7) await coord.sync() assert len(coord.snapshots()) == 1 assert global_info._last_error is not None
async def test_ignore_startup_delay(time: FakeTime, model: Model, dest: HelperTestSource, source: HelperTestSource, global_info: GlobalInfo): time.setNow(time.local(2019, 5, 10)) global_info.triggerSnapshotCooldown(timedelta(minutes=10)) model.ignore_startup_delay = True assert model.nextSnapshot(time.now()) == time.now() - timedelta(minutes=1) assert not model.waiting_for_startup
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
async def test_wait_for_startup_no_snapshot(time: FakeTime, model: Model, dest: HelperTestSource, source: HelperTestSource, global_info: GlobalInfo): time.setNow(time.local(2019, 5, 10)) global_info.triggerSnapshotCooldown(timedelta(minutes=10)) assert model.nextSnapshot(time.now()) == time.now() + timedelta(minutes=10) assert model.nextSnapshot(time.now()) == global_info.snapshotCooldownTime() assert model.waiting_for_startup time.advance(minutes=10) assert model.nextSnapshot(time.now()) == time.now() - timedelta(minutes=1) assert not model.waiting_for_startup
async def test_send_clear(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") # Simulate failure global_info.failed(Exception("boom")) await debug_worker.doWork() # And then success global_info.success() time.advance(days=1) await debug_worker.doWork() report = error_store.last_error assert report['report'] == {'duration': '1 day, 0:00:00'}
async def test_wait_for_startup_with_backup(time: FakeTime, model: Model, dest: HelperTestSource, source: HelperTestSource, global_info: GlobalInfo): time.setNow(time.local(2019, 5, 10)) global_info.triggerBackupCooldown(timedelta(minutes=10)) source.setMax(3) source.insert("old", time.now() - timedelta(days=7)) assert model.nextBackup(time.now()) == time.now() + timedelta(minutes=10) assert model.nextBackup(time.now()) == global_info.backupCooldownTime() assert model.waiting_for_startup time.advance(minutes=10) assert model.nextBackup(time.now()) == time.now() - timedelta(minutes=1) assert not model.waiting_for_startup
def test_timeOfDay(estimator) -> None: time: FakeTime = FakeTime() info = GlobalInfo(time) config: Config = Config() model: Model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config = Config().override(Setting.SNAPSHOT_TIME_OF_DAY, '00:00') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() == (0, 0) config.override(Setting.SNAPSHOT_TIME_OF_DAY, '23:59') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() == (23, 59) config.override(Setting.SNAPSHOT_TIME_OF_DAY, '24:59') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config.override(Setting.SNAPSHOT_TIME_OF_DAY, '24:60') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config.override(Setting.SNAPSHOT_TIME_OF_DAY, '-1:60') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config.override(Setting.SNAPSHOT_TIME_OF_DAY, '24:-1') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config.override(Setting.SNAPSHOT_TIME_OF_DAY, 'boop:60') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config.override(Setting.SNAPSHOT_TIME_OF_DAY, '24:boop') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config.override(Setting.SNAPSHOT_TIME_OF_DAY, '24:10:22') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None config.override(Setting.SNAPSHOT_TIME_OF_DAY, '10') model = Model(config, time, default_source, default_source, info, estimator) assert model.getTimeOfDay() is None
async def test_init_failure(updater: HaUpdater, global_info: GlobalInfo, time: FakeTime, server, supervisor: SimulatedSupervisor): await updater.update() assert not updater._stale() assert updater._state() == "waiting" global_info.failed(Exception()) assert not updater._stale() assert updater._state() == "backed_up" assert supervisor.getNotification() is None time.advanceDay() assert updater._stale() assert updater._state() == "error" await updater.update() assert supervisor.getNotification() == { 'message': 'The add-on is having trouble making backups and needs attention. Please visit the add-on status page for details.', 'title': 'Home Assistant Google Drive Backup is Having Trouble', 'notification_id': 'backup_broken' }
def test_next_time_of_day(estimator, data_cache): time: FakeTime = FakeTime() now: datetime = datetime(1985, 12, 6, 1, 0, 0).astimezone(timezone.utc) time.setNow(now) info = GlobalInfo(time) config: Config = createConfig().override(Setting.DAYS_BETWEEN_BACKUPS, 1).override( Setting.BACKUP_TIME_OF_DAY, '08:00') model: Model = Model(config, time, default_source, default_source, info, estimator, data_cache) assert model._nextBackup(now=now, last_backup=None) == now - timedelta(minutes=1) assert model._nextBackup(now=now, last_backup=now - timedelta(days=1)) == datetime(1985, 12, 5, 8, 0, tzinfo=test_tz) assert model._nextBackup(now=now, last_backup=now) == datetime(1985, 12, 6, 8, 0, tzinfo=test_tz) assert model._nextBackup(now=now, last_backup=datetime(1985, 12, 6, 8, 0, tzinfo=test_tz)) == datetime( 1985, 12, 7, 8, 0, tzinfo=test_tz) assert model._nextBackup(now=datetime(1985, 12, 6, 8, 0, tzinfo=test_tz), last_backup=datetime(1985, 12, 6, 8, 0, tzinfo=test_tz)) == datetime( 1985, 12, 7, 8, 0, tzinfo=test_tz)
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()
def test_next_time_of_day_drift(estimator): time: FakeTime = FakeTime() info = GlobalInfo(time) now: datetime = datetime(1985, 12, 6, 1, 0, 0).astimezone(timezone.utc) config: Config = Config().override(Setting.DAYS_BETWEEN_SNAPSHOTS, 1).override( Setting.SNAPSHOT_TIME_OF_DAY, '08:00') model: Model = Model(config, time, default_source, default_source, info, estimator) assert model._nextSnapshot( now=now, last_snapshot=None) == now - timedelta(minutes=1) assert model._nextSnapshot( now=now, last_snapshot=now - timedelta(days=1) + timedelta(minutes=1)) == now
async def test_publish_for_failure(updater: HaUpdater, server, time: FakeTime, global_info: GlobalInfo, supervisor: SimulatedSupervisor): global_info.success() await updater.update() assert supervisor.getNotification() is None time.advanceDay() global_info.failed(Exception()) await updater.update() assert supervisor.getNotification() is not None time.advanceDay() global_info.failed(Exception()) await updater.update() assert supervisor.getNotification() is not None global_info.success() await updater.update() assert supervisor.getNotification() is None
def test_next_time(estimator, data_cache): time: FakeTime = FakeTime() now: datetime = datetime(1985, 12, 6, 1, 0, 0).astimezone(timezone.utc) time.setNow(now) info = GlobalInfo(time) config: Config = createConfig().override(Setting.DAYS_BETWEEN_SNAPSHOTS, 0) model: Model = Model(config, time, default_source, default_source, info, estimator, data_cache) assert model._nextSnapshot(now=now, last_snapshot=None) is None assert model._nextSnapshot(now=now, last_snapshot=now) is None config: Config = createConfig().override(Setting.DAYS_BETWEEN_SNAPSHOTS, 1) model: Model = Model(config, time, default_source, default_source, info, estimator, data_cache) assert model._nextSnapshot( now=now, last_snapshot=None) == now - timedelta(minutes=1) assert model._nextSnapshot(now=now, last_snapshot=now) == now + timedelta(days=1) assert model._nextSnapshot(now=now, last_snapshot=now - timedelta(days=1)) == now assert model._nextSnapshot(now=now, last_snapshot=now + timedelta(days=1)) == now + timedelta(days=2)
async def test_send_error_report(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.sync() global_info.success() global_info.sync() global_info.success() global_info.sync() global_info.failed(Exception()) await debug_worker.doWork() report = error_store.last_error assert report['report']['sync_success_count'] == 2 assert report['report']['sync_count'] == 3 assert report['report']['failure_count'] == 1 assert report['report']['sync_last_start'] == time.now().isoformat() assert report['report']['failure_time'] == time.now().isoformat() assert report['report']['error'] == getLogger("test").formatException( Exception())