Exemplo n.º 1
0
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"}
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
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
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
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
Exemplo n.º 13
0
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"
Exemplo n.º 15
0
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"}
Exemplo n.º 17
0
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
Exemplo n.º 25
0
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())
Exemplo n.º 27
0
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 == []
Exemplo n.º 28
0
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