|
2 | 2 |
|
3 | 3 | import asyncio |
4 | 4 | from pathlib import Path, PurePath |
| 5 | +from shutil import copy |
5 | 6 | from typing import Any |
6 | 7 | from unittest.mock import ANY, AsyncMock, PropertyMock, patch |
7 | 8 |
|
|
19 | 20 | from supervisor.mounts.mount import Mount |
20 | 21 | from supervisor.supervisor import Supervisor |
21 | 22 |
|
| 23 | +from tests.common import get_fixture_path |
| 24 | +from tests.const import TEST_ADDON_SLUG |
| 25 | + |
22 | 26 |
|
23 | 27 | async def test_info(api_client, coresys: CoreSys, mock_full_backup: Backup): |
24 | 28 | """Test info endpoint.""" |
@@ -467,3 +471,120 @@ async def test_restore_immediate_errors( |
467 | 471 | ) |
468 | 472 | assert resp.status == 400 |
469 | 473 | assert "No Home Assistant" in (await resp.json())["message"] |
| 474 | + |
| 475 | + |
| 476 | +@pytest.mark.parametrize( |
| 477 | + ("folder", "location"), [("backup", None), ("core/backup", ".cloud_backup")] |
| 478 | +) |
| 479 | +async def test_reload( |
| 480 | + request: pytest.FixtureRequest, |
| 481 | + api_client: TestClient, |
| 482 | + coresys: CoreSys, |
| 483 | + tmp_supervisor_data: Path, |
| 484 | + folder: str, |
| 485 | + location: str | None, |
| 486 | +): |
| 487 | + """Test backups reload.""" |
| 488 | + assert not coresys.backups.list_backups |
| 489 | + |
| 490 | + backup_file = get_fixture_path("backup_example.tar") |
| 491 | + copy(backup_file, tmp_supervisor_data / folder) |
| 492 | + |
| 493 | + resp = await api_client.post("/backups/reload") |
| 494 | + assert resp.status == 200 |
| 495 | + |
| 496 | + assert len(coresys.backups.list_backups) == 1 |
| 497 | + assert (backup := coresys.backups.get("7fed74c8")) |
| 498 | + assert backup.location == location |
| 499 | + assert backup.locations == [location] |
| 500 | + |
| 501 | + |
| 502 | +@pytest.mark.parametrize( |
| 503 | + ("folder", "location"), [("backup", None), ("core/backup", ".cloud_backup")] |
| 504 | +) |
| 505 | +async def test_partial_reload( |
| 506 | + request: pytest.FixtureRequest, |
| 507 | + api_client: TestClient, |
| 508 | + coresys: CoreSys, |
| 509 | + tmp_supervisor_data: Path, |
| 510 | + folder: str, |
| 511 | + location: str | None, |
| 512 | +): |
| 513 | + """Test partial backups reload.""" |
| 514 | + assert not coresys.backups.list_backups |
| 515 | + |
| 516 | + backup_file = get_fixture_path("backup_example.tar") |
| 517 | + copy(backup_file, tmp_supervisor_data / folder) |
| 518 | + |
| 519 | + resp = await api_client.post( |
| 520 | + "/backups/reload", json={"location": location, "filename": "backup_example.tar"} |
| 521 | + ) |
| 522 | + assert resp.status == 200 |
| 523 | + |
| 524 | + assert len(coresys.backups.list_backups) == 1 |
| 525 | + assert (backup := coresys.backups.get("7fed74c8")) |
| 526 | + assert backup.location == location |
| 527 | + assert backup.locations == [location] |
| 528 | + |
| 529 | + |
| 530 | +async def test_invalid_reload(api_client: TestClient): |
| 531 | + """Test invalid reload.""" |
| 532 | + resp = await api_client.post("/backups/reload", json={"location": "no_filename"}) |
| 533 | + assert resp.status == 400 |
| 534 | + |
| 535 | + resp = await api_client.post( |
| 536 | + "/backups/reload", json={"filename": "no_location.tar"} |
| 537 | + ) |
| 538 | + assert resp.status == 400 |
| 539 | + |
| 540 | + resp = await api_client.post( |
| 541 | + "/backups/reload", json={"location": None, "filename": "no/sub/paths.tar"} |
| 542 | + ) |
| 543 | + assert resp.status == 400 |
| 544 | + |
| 545 | + resp = await api_client.post( |
| 546 | + "/backups/reload", json={"location": None, "filename": "not_tar.tar.gz"} |
| 547 | + ) |
| 548 | + assert resp.status == 400 |
| 549 | + |
| 550 | + |
| 551 | +@pytest.mark.usefixtures("install_addon_ssh") |
| 552 | +@pytest.mark.parametrize("api_client", TEST_ADDON_SLUG, indirect=True) |
| 553 | +async def test_cloud_backup_core_only(api_client: TestClient, mock_full_backup: Backup): |
| 554 | + """Test only core can access cloud backup location.""" |
| 555 | + resp = await api_client.post( |
| 556 | + "/backups/reload", |
| 557 | + json={"location": ".cloud_backup", "filename": "caller_not_core.tar"}, |
| 558 | + ) |
| 559 | + assert resp.status == 403 |
| 560 | + |
| 561 | + resp = await api_client.post( |
| 562 | + "/backups/new/full", |
| 563 | + json={ |
| 564 | + "name": "Mount test", |
| 565 | + "location": ".cloud_backup", |
| 566 | + }, |
| 567 | + ) |
| 568 | + assert resp.status == 403 |
| 569 | + |
| 570 | + resp = await api_client.post( |
| 571 | + "/backups/new/partial", |
| 572 | + json={"name": "Test", "homeassistant": True, "location": ".cloud_backup"}, |
| 573 | + ) |
| 574 | + assert resp.status == 403 |
| 575 | + |
| 576 | + # pylint: disable-next=protected-access |
| 577 | + mock_full_backup._locations = {".cloud_backup": None} |
| 578 | + assert mock_full_backup.location == ".cloud_backup" |
| 579 | + |
| 580 | + resp = await api_client.post(f"/backups/{mock_full_backup.slug}/restore/full") |
| 581 | + assert resp.status == 403 |
| 582 | + |
| 583 | + resp = await api_client.post( |
| 584 | + f"/backups/{mock_full_backup.slug}/restore/partial", |
| 585 | + json={"homeassistant": True}, |
| 586 | + ) |
| 587 | + assert resp.status == 403 |
| 588 | + |
| 589 | + resp = await api_client.delete(f"/backups/{mock_full_backup.slug}") |
| 590 | + assert resp.status == 403 |
0 commit comments