|
15 | 15 | from borgstore.backends.rest import get_rest_backend |
16 | 16 | from borgstore.backends.posixfs import get_file_backend |
17 | 17 | from borgstore.backends.errors import ObjectNotFound, BackendAlreadyExists, QuotaExceeded |
18 | | -from borgstore.store import get_backend |
| 18 | +from borgstore.store import get_backend, Store |
19 | 19 |
|
20 | 20 |
|
21 | 21 | def start_server(backend_url, address, port, username=None, password=None, permissions=None, quota=None): |
@@ -76,7 +76,9 @@ def test_rest_server_basic_ops(rest_server_with_auth): |
76 | 76 | be.delete("test/item1") |
77 | 77 | with pytest.raises(ObjectNotFound): |
78 | 78 | be.load("test/item1") |
79 | | - assert not be.info("test/item1").exists |
| 79 | + info = be.info("test/item1") |
| 80 | + assert not info.exists |
| 81 | + assert info.size == 0 |
80 | 82 |
|
81 | 83 | finally: |
82 | 84 | be.close() |
@@ -613,29 +615,82 @@ def do_request(method, path, body=b""): |
613 | 615 |
|
614 | 616 | # Read body |
615 | 617 | resp_body = b"" |
616 | | - if "Content-Length" in resp_headers: |
| 618 | + if method.upper() != "HEAD" and "Content-Length" in resp_headers: |
617 | 619 | resp_body = proc.stdout.read(int(resp_headers["Content-Length"])) |
618 | | - return status, resp_body |
| 620 | + return status, resp_body, resp_headers |
619 | 621 |
|
620 | 622 | try: |
621 | 623 | # 1. Create store |
622 | | - status, body = do_request("POST", "/?cmd=create") |
| 624 | + status, body, headers = do_request("POST", "/?cmd=create") |
623 | 625 | assert status == 200 |
624 | 626 |
|
625 | 627 | # 2. Store something |
626 | 628 | item_data = b"stdio data" |
627 | | - status, body = do_request("POST", "/item1", body=item_data) |
| 629 | + status, body, headers = do_request("POST", "/item1", body=item_data) |
628 | 630 | assert status == 200 |
629 | 631 |
|
630 | 632 | # 3. List the store |
631 | | - status, body = do_request("GET", "/") |
| 633 | + status, body, headers = do_request("GET", "/") |
632 | 634 | assert status == 200 |
633 | 635 | items = json.loads(body.decode("utf-8")) |
634 | | - assert any(item["name"] == "item1" for item in items) |
| 636 | + assert any(item["name"] == "item1" and item.get("atime", 0) > 0 for item in items) |
| 637 | + |
| 638 | + # 4. Info (HEAD) |
| 639 | + status, body, headers = do_request("HEAD", "/item1") |
| 640 | + assert status == 200 |
| 641 | + assert body == b"" |
| 642 | + assert float(headers.get("X-BorgStore-Atime", 0)) > 0 |
| 643 | + |
| 644 | + # 5. Info for nonexistent (HEAD) |
| 645 | + status, body, headers = do_request("HEAD", "/nonexistent") |
| 646 | + assert status == 404 |
| 647 | + assert body == b"" |
635 | 648 |
|
636 | 649 | finally: |
637 | 650 | proc.stdin.close() |
638 | 651 | try: |
639 | 652 | proc.wait(timeout=2) |
640 | 653 | except subprocess.TimeoutExpired: |
641 | 654 | proc.kill() |
| 655 | + |
| 656 | + |
| 657 | +def test_rest_url(tmp_path): |
| 658 | + repo_path = tmp_path / "repo" |
| 659 | + # Use rest: URL with stdio backend (empty host) |
| 660 | + url = f"rest:///{repo_path}" |
| 661 | + |
| 662 | + # Use levels=0 to avoid root nesting issues if they arise |
| 663 | + config = {"": {"levels": [0]}} |
| 664 | + store = Store(url, config=config) |
| 665 | + store.create() |
| 666 | + |
| 667 | + with store: |
| 668 | + item_name = "test-item" |
| 669 | + item_data = b"some data" |
| 670 | + store.store(item_name, item_data) |
| 671 | + |
| 672 | + # Test Store.info which calls Backend.info (HEAD) |
| 673 | + # This used to hang. |
| 674 | + info = store.info(item_name) |
| 675 | + assert info.exists |
| 676 | + assert info.size == len(item_data) |
| 677 | + assert info.atime > 0 |
| 678 | + |
| 679 | + # Test listing |
| 680 | + items = list(store.list("")) |
| 681 | + assert len(items) == 1 |
| 682 | + assert items[0].name == item_name |
| 683 | + assert items[0].atime > 0 |
| 684 | + |
| 685 | + # Test nonexistent item |
| 686 | + # This also used to hang if it returned a 404 with a body. |
| 687 | + info_none = store.info("nonexistent") |
| 688 | + assert not info_none.exists |
| 689 | + assert info_none.size == 0 |
| 690 | + |
| 691 | + # Test directory info (root) |
| 692 | + info_root = store.info("") |
| 693 | + assert info_root.exists |
| 694 | + assert info_root.directory |
| 695 | + |
| 696 | + store.destroy() |
0 commit comments