Skip to content

tests/spa/orchestration/test_orchestration_freeze_handler.py

Source from this local checkout, regenerated when the reader rebuilds. Line links use #L<number>; a GitHub line range opens its first line.

1 # Copyright 2025 Softwell S.r.l.2 #3 # Licensed under the Apache License, Version 2.0 (the "License");4 # you may not use this file except in compliance with the License.5 # You may obtain a copy of the License at6 #7 #     https://www.apache.org/licenses/LICENSE-2.08 #9 # Unless required by applicable law or agreed to in writing, software10 # distributed under the License is distributed on an "AS IS" BASIS,11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12 # See the License for the specific language governing permissions and13 # limitations under the License.14 15 """FreezeHandler tests: the semaphore, the two item kinds, the empty folder.16 17 Everything here runs against a real directory in ``tmp_path``: the deposit is18 the one place that talks to the filesystem directly, so a fake filesystem would19 assert nothing. The protocol under test is always the same round — announce,20 take the lock, operate, release — and what the tests pin down is what happens21 at its edges: a second holder finding the lock taken, a folder left with the22 lock alone, a header travelling with a payload nobody reads it for.23 """24 25 from __future__ import annotations26 27 import os28 import time29 30 import pytest31 32 from genro_asgi_multiworker_spa.orchestration import FreezeHandler33 34 35 @pytest.fixture36 def deposit(tmp_path):37     return FreezeHandler(tmp_path / "freezed_users")38 39 40 def test_root_is_created_private(tmp_path):41     root = tmp_path / "deposit" / "freezed_users"42     FreezeHandler(root)43     assert root.is_dir()44     assert os.stat(root).st_mode & 0o777 == 0o70045 46 47 def test_lock_is_mutually_exclusive(deposit):48     assert deposit.take_lock("mario", "standard_0001") is True49     assert deposit.take_lock("mario", "standard_0002") is False50     assert deposit.lock_holder("mario") == "standard_0001"51 52     deposit.release_lock("mario", "standard_0001")53     assert deposit.lock_holder("mario") is None54     assert deposit.take_lock("mario", "standard_0002") is True55 56 57 def test_release_by_a_holder_that_does_not_hold_is_an_error(deposit):58     deposit.take_lock("mario", "standard_0001")59     with pytest.raises(RuntimeError, match="standard_0002"):60         deposit.release_lock("mario", "standard_0002")61     assert deposit.lock_holder("mario") == "standard_0001"62 63 64 def test_two_writers_share_one_folder_one_at_a_time(deposit):65     """The whole freeze writes the user store, a login writes one connection."""66     assert deposit.take_lock("mario", "standard_0001") is True67     deposit.write_user_register_item(68         "mario", {"store": "whole"}, writer="standard_0001", cause="freeze", group="standard"69     )70     assert deposit.take_lock("mario", "standard_0002") is False71     deposit.release_lock("mario", "standard_0001")72 73     assert deposit.take_lock("mario", "standard_0002") is True74     deposit.write_connection_register_item(75         "mario", "cid-a", {"pages": ["p1"]}, writer="standard_0002", cause="login", group="standard"76     )77     deposit.release_lock("mario", "standard_0002")78 79     assert deposit.read_user_register_item("mario") == {"store": "whole"}80     assert deposit.read_connection_register_item("mario", "cid-a") == {"pages": ["p1"]}81 82 83 def test_reading_what_was_never_written_gives_nothing(deposit):84     assert deposit.read_user_register_item("mario") is None85     assert deposit.read_connection_register_item("mario", "cid-a") is None86     assert deposit.get_item_header("mario") is None87 88 89 def test_the_header_travels_with_the_payload(deposit):90     before = time.time()91     deposit.take_lock("mario", "standard_0001")92     deposit.write_connection_register_item(93         "mario", "cid-a", {"pages": []}, writer="standard_0001", cause="freeze", group="standard"94     )95     deposit.release_lock("mario", "standard_0001")96 97     header = deposit.get_item_header("mario", "cid-a")98     assert header["writer"] == "standard_0001"99     assert header["cause"] == "freeze"100     assert header["group"] == "standard"101     assert header["ts"] >= before102 103 104 def test_the_release_takes_away_the_folder_left_with_the_lock_alone(deposit):105     deposit.take_lock("mario", "standard_0001")106     deposit.write_connection_register_item(107         "mario", "cid-a", {"pages": []}, writer="standard_0001", cause="freeze", group="standard"108     )109     deposit.write_user_register_item(110         "mario", {"store": {}}, writer="standard_0001", cause="freeze", group="standard"111     )112     assert deposit.user_folders == {deposit.user_to_userkey("mario")}113 114     deposit.drop_connection_register_item("mario", "cid-a")115     deposit.drop_user_register_item("mario")116     assert deposit.lock_holder("mario") == "standard_0001"117     assert deposit.user_folders == {deposit.user_to_userkey("mario")}118 119     deposit.release_lock("mario", "standard_0001")120     assert deposit.user_folders == set()121 122 123 def test_the_release_leaves_a_folder_that_still_has_items(deposit):124     deposit.take_lock("mario", "standard_0001")125     deposit.write_user_register_item(126         "mario", {"store": {}}, writer="standard_0001", cause="freeze", group="standard"127     )128     deposit.release_lock("mario", "standard_0001")129 130     assert deposit.user_folders == {deposit.user_to_userkey("mario")}131     assert deposit.read_user_register_item("mario") == {"store": {}}132 133 134 def test_the_whole_folder_goes_with_its_user(deposit):135     deposit.take_lock("mario", "standard_0001")136     deposit.write_user_register_item(137         "mario", {"store": {}}, writer="standard_0001", cause="freeze", group="standard"138     )139     deposit.write_connection_register_item(140         "mario", "cid-a", {"pages": []}, writer="standard_0001", cause="freeze", group="standard"141     )142 143     deposit.drop_user_folder("mario")144     assert deposit.user_folders == set()145     assert deposit.lock_holder("mario") is None146 147 148 def test_dropping_a_folder_nobody_wrote_is_no_work(deposit):149     deposit.drop_user_folder("mario")150     assert deposit.user_folders == set()151 152 153 def test_dropping_items_nobody_wrote_is_no_work(deposit):154     deposit.take_lock("mario", "standard_0001")155 156     deposit.drop_user_register_item("mario")157     deposit.drop_connection_register_item("mario", "cid-a")158 159     assert deposit.lock_holder("mario") == "standard_0001"160     deposit.release_lock("mario", "standard_0001")161     assert deposit.user_folders == set()162 163 164 def test_the_folders_of_every_user_come_as_one_set(deposit):165     for user in ("mario", "guest_abc", "anna@example.com"):166         deposit.take_lock(user, "standard_0001")167         deposit.write_user_register_item(168             user, {"store": {}}, writer="standard_0001", cause="freeze", group="standard"169         )170         deposit.release_lock(user, "standard_0001")171 172     assert deposit.user_folders == {173         deposit.user_to_userkey(user) for user in ("mario", "guest_abc", "anna@example.com")174     }175 176 177 def test_the_key_goes_one_way_only(deposit):178     assert deposit.user_to_userkey("anna@example.com") == "anna%40example.com"179     assert not hasattr(deposit, "userkey_to_user")180 181 182 def test_an_identity_carrying_separators_stays_in_its_folder(deposit):183     hostile = "../mario/../../etc"184     deposit.take_lock(hostile, "standard_0001")185     deposit.write_user_register_item(186         hostile, {"store": {}}, writer="standard_0001", cause="freeze", group="standard"187     )188     deposit.release_lock(hostile, "standard_0001")189 190     assert deposit.user_folders == {deposit.user_to_userkey(hostile)}191     assert "/" not in deposit.user_to_userkey(hostile)192 193 194 def test_two_connections_of_one_user_are_two_files(deposit):195     deposit.take_lock("mario", "standard_0001")196     deposit.write_connection_register_item(197         "mario", "cid-a", {"pages": ["a"]}, writer="standard_0001", cause="freeze", group="standard"198     )199     deposit.write_connection_register_item(200         "mario", "cid-b", {"pages": ["b"]}, writer="standard_0001", cause="freeze", group="standard"201     )202     deposit.release_lock("mario", "standard_0001")203 204     assert deposit.read_connection_register_item("mario", "cid-a") == {"pages": ["a"]}205     assert deposit.read_connection_register_item("mario", "cid-b") == {"pages": ["b"]}206 207     deposit.take_lock("mario", "standard_0001")208     deposit.drop_connection_register_item("mario", "cid-a")209     deposit.release_lock("mario", "standard_0001")210 211     assert deposit.read_connection_register_item("mario", "cid-a") is None212     assert deposit.read_connection_register_item("mario", "cid-b") == {"pages": ["b"]}