DevPlace CI / test (push) Failing after 44m45s
Continuous Delivery could never be turned off once a crop was planted. Add a one-shot per-plot "stop after harvest" flag (POST /game/plot/stop, Devii tool game_plot_stop, game_plots.stop_after_harvest), cleared by the next plant, autoreplant claim or Refactor. Autoreplant now also respects crop locks through the shared _crop_lock predicate. Plan and measurements in happyplanting.md. Also includes the pending community sync, node network and related work in the tree; the full suite passed (4999) with all of it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
100 lines
4.1 KiB
Python
100 lines
4.1 KiB
Python
# retoor <retoor@molodetz.nl>
|
|
|
|
import pytest
|
|
|
|
from devplacepy.database import get_table, init_db
|
|
from devplacepy.database.sync import claim_identity, claim_link
|
|
from devplacepy.services.sync.healing import AliasHealer
|
|
from devplacepy.services.sync.processors import UserProcessor
|
|
from devplacepy.utils import generate_uid
|
|
|
|
ORIGIN = "heal.example.org"
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def clean(local_db):
|
|
init_db()
|
|
for table in ("sync_identities", "sync_links"):
|
|
get_table(table).delete(origin=ORIGIN)
|
|
yield
|
|
for table in ("sync_identities", "sync_links"):
|
|
get_table(table).delete(origin=ORIGIN)
|
|
|
|
|
|
def clone(source="alice", alias="Mira"):
|
|
suffix = generate_uid()[-6:]
|
|
alias = f"{alias}{suffix}"
|
|
processor = UserProcessor(ORIGIN)
|
|
result = processor.process(0, {"origin_uid": source, "username": alias, "created_at": "2026-01-01T00:00:00Z"})
|
|
claim_identity(ORIGIN, source.capitalize(), source, alias, "style", False)
|
|
return result.local_uid, alias
|
|
|
|
|
|
def synced_text(origin_uid, table, text, kind):
|
|
uid = generate_uid()
|
|
get_table(table).insert(
|
|
{"uid": uid, "user_uid": "u", "title": None, "content": text, "created_at": "2026-01-01T00:00:00+00:00", "target_uid": "x", "target_type": "post", "deleted_at": None, "deleted_by": None}
|
|
)
|
|
claim_link(ORIGIN, kind, origin_uid, uid, "fp", "2026-01-01T00:00:00+00:00")
|
|
return uid
|
|
|
|
|
|
def test_nothing_changes_when_the_clone_still_has_the_alias():
|
|
clone()
|
|
report = AliasHealer(ORIGIN).heal()
|
|
assert not report.renamed and not report.conflicts and report.rewritten == 0
|
|
|
|
|
|
def test_an_administrator_rename_moves_the_identity_and_the_stored_mentions():
|
|
uid, alias = clone()
|
|
post = synced_text("p1", "posts", f"thanks @{alias} and {alias} again, @{alias}x stays", "posts")
|
|
comment = synced_text("c1", "comments", f"@{alias.lower()} agreed", "comments")
|
|
other = synced_text("p2", "posts", "unrelated text", "posts")
|
|
renamed = f"Renamed{generate_uid()[-6:]}"
|
|
get_table("users").update({"uid": uid, "username": renamed}, ["uid"])
|
|
report = AliasHealer(ORIGIN).heal()
|
|
assert report.renamed == {alias: renamed} and report.rewritten == 2
|
|
row = get_table("sync_identities").find_one(origin=ORIGIN, source_key="alice")
|
|
assert row["our_name"] == renamed and row["our_key"] == renamed.lower()
|
|
assert get_table("posts").find_one(uid=post)["content"] == f"thanks @{renamed} and {renamed} again, @{alias}x stays"
|
|
assert get_table("comments").find_one(uid=comment)["content"] == f"@{renamed} agreed"
|
|
assert get_table("posts").find_one(uid=other)["content"] == "unrelated text"
|
|
assert not AliasHealer(ORIGIN).heal().renamed
|
|
|
|
|
|
def test_a_suffixed_clone_name_is_adopted(local_db):
|
|
uid, alias = clone("bob", "Taken")
|
|
suffixed = f"{alias}-heal"
|
|
get_table("users").update({"uid": uid, "username": suffixed}, ["uid"])
|
|
assert AliasHealer(ORIGIN).heal().renamed == {alias: suffixed}
|
|
assert get_table("sync_identities").find_one(origin=ORIGIN, source_key="bob")["our_name"] == suffixed
|
|
|
|
|
|
def test_a_name_that_belongs_to_another_identity_is_a_conflict_not_a_steal():
|
|
first_uid, first_alias = clone("alice", "Una")
|
|
_, second_alias = clone("carol", "Duo")
|
|
get_table("users").update({"uid": first_uid, "username": second_alias}, ["uid"])
|
|
report = AliasHealer(ORIGIN).heal()
|
|
assert report.conflicts == ["alice"] and not report.renamed
|
|
assert get_table("sync_identities").find_one(origin=ORIGIN, source_key="alice")["our_name"] == first_alias
|
|
|
|
|
|
def test_a_purged_clone_is_ignored():
|
|
uid, _ = clone()
|
|
get_table("users").delete(uid=uid)
|
|
assert AliasHealer(ORIGIN).heal().renamed == {}
|
|
|
|
|
|
def test_the_rewrite_work_per_run_is_bounded(monkeypatch):
|
|
from dataclasses import replace
|
|
|
|
from devplacepy.services.sync import healing
|
|
from devplacepy.services.sync.spec import ALIAS
|
|
|
|
uid, alias = clone()
|
|
for index in range(5):
|
|
synced_text(f"p{index}", "posts", f"hello @{alias}", "posts")
|
|
monkeypatch.setattr(healing, "ALIAS", replace(ALIAS, heal_rewrites_per_run=2))
|
|
get_table("users").update({"uid": uid, "username": f"Bounded{generate_uid()[-6:]}"}, ["uid"])
|
|
assert AliasHealer(ORIGIN).heal().rewritten == 2
|