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>
71 lines
2.9 KiB
Python
71 lines
2.9 KiB
Python
# retoor <retoor@molodetz.nl>
|
|
|
|
import json
|
|
|
|
from devplacepy.services.nodes.shape import INCONCLUSIVE, MATCH, MISMATCH, compare, shape_of
|
|
|
|
JSON = {"content-type": "application/json; charset=utf-8"}
|
|
HTML = {"content-type": "text/html"}
|
|
|
|
|
|
def listing(children):
|
|
return json.dumps({"kind": "Listing", "data": {"after": None, "children": children}}).encode()
|
|
|
|
|
|
def test_two_listings_with_different_content_match():
|
|
first = shape_of(200, JSON, listing([{"id": 1}]))
|
|
second = shape_of(200, JSON, listing([{"id": 2}, {"id": 3}]))
|
|
assert compare(first, second) == MATCH
|
|
|
|
|
|
def test_a_forged_json_shape_mismatches():
|
|
first = shape_of(200, JSON, listing([]))
|
|
forged = shape_of(200, JSON, json.dumps({"message": "buy now"}).encode())
|
|
assert compare(first, forged) == MISMATCH
|
|
|
|
|
|
def test_html_titles_decide():
|
|
page = b"<html><head><title> Python : r/python </title></head><body>" + b"x" * 600 + b"</body></html>"
|
|
same = b"<html><head><title>Python : r/python</title></head><body>" + b"y" * 700 + b"</body></html>"
|
|
other = b"<html><head><title>Totally different</title></head><body>" + b"x" * 600 + b"</body></html>"
|
|
assert compare(shape_of(200, HTML, page), shape_of(200, HTML, same)) == MATCH
|
|
assert compare(shape_of(200, HTML, page), shape_of(200, HTML, other)) == MISMATCH
|
|
|
|
|
|
def test_html_without_a_title_falls_back_to_the_first_heading():
|
|
first = shape_of(200, HTML, b"<h1>Hello <b>world</b></h1>")
|
|
second = shape_of(200, HTML, b"<h1>Hello world</h1>")
|
|
assert first.signature == "Hello world" and compare(first, second) == MATCH
|
|
|
|
|
|
def test_a_kind_change_mismatches_even_with_the_same_status():
|
|
assert compare(shape_of(200, JSON, listing([])), shape_of(200, HTML, b"<title>x</title>")) == MISMATCH
|
|
|
|
|
|
def test_blocked_or_error_responses_are_never_conclusive():
|
|
ok = shape_of(200, JSON, listing([]))
|
|
for status in (403, 429, 500, 404):
|
|
assert compare(ok, shape_of(status, HTML, b"<title>blocked</title>")) == INCONCLUSIVE
|
|
assert compare(shape_of(status, HTML, b""), ok) == INCONCLUSIVE
|
|
|
|
|
|
def test_a_wild_size_difference_mismatches_only_for_real_bodies():
|
|
big = shape_of(200, HTML, b"<title>t</title>" + b"a" * 5000)
|
|
small = shape_of(200, HTML, b"<title>t</title>" + b"a" * 600)
|
|
tiny = shape_of(200, HTML, b"<title>t</title>")
|
|
assert compare(big, small) == MISMATCH
|
|
assert compare(big, tiny) == MATCH
|
|
|
|
|
|
def test_invalid_json_is_its_own_kind():
|
|
broken = shape_of(200, JSON, b"{not json")
|
|
assert broken.kind == "json-invalid"
|
|
assert compare(broken, shape_of(200, JSON, listing([]))) == MISMATCH
|
|
|
|
|
|
def test_nested_key_sets_are_bounded_and_unknown_types_compare_by_type():
|
|
deep = {"a": {"b": {"c": {"d": 1}}}}
|
|
assert "a.b" in shape_of(200, JSON, json.dumps(deep).encode()).signature
|
|
assert "a.b.c.d" not in shape_of(200, JSON, json.dumps(deep).encode()).signature
|
|
assert compare(shape_of(200, {"content-type": "image/png"}, b"1"), shape_of(200, {"content-type": "image/png"}, b"2")) == MATCH
|