audit: recall matches the whole line; races answered honestly
- recall searched only the text, so a date or an id found nothing; it now matches the rendered line '#id date text' - a wake refusal read pending twice, so a nap paid in parallel between the reads printed a literal None; the nap itself now decides - a session resubmitting a block another session settled was told 'Wrong block' (rc 1) for doing what its prompt ordered; it now hears 'already settled' (rc 0), and the tree_put race message no longer claims 'written' when the block may have been forgotten
This commit is contained in:
parent
a6abc264c5
commit
58019db0db
2 changed files with 33 additions and 13 deletions
23
memo
23
memo
|
|
@ -343,11 +343,12 @@ def cmd_wake(d, args):
|
||||||
% (T, plural(now, "entry")))
|
% (T, plural(now, "entry")))
|
||||||
# A part is rendered as of T, so a note landing between two parts cannot
|
# A part is rendered as of T, so a note landing between two parts cannot
|
||||||
# shift a boundary and drop a line.
|
# shift a boundary and drop a line.
|
||||||
n = pending_count(d, T)
|
nap = next_nap(d, T)
|
||||||
if n:
|
if nap:
|
||||||
|
n = max(1, pending_count(d, T))
|
||||||
print("Cannot wake: %s pending. Do %s, then run memo wake again.\n"
|
print("Cannot wake: %s pending. Do %s, then run memo wake again.\n"
|
||||||
% (plural(n, "compression"), "it" if n == 1 else "them"))
|
% (plural(n, "compression"), "it" if n == 1 else "them"))
|
||||||
print(next_nap(d, T))
|
print(nap)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if not T:
|
if not T:
|
||||||
print("No memories yet. Record the first with: memo note \"<one line>\"")
|
print("No memories yet. Record the first with: memo note \"<one line>\"")
|
||||||
|
|
@ -403,11 +404,14 @@ def cmd_sleep(d, args):
|
||||||
print("Nothing left to compress.")
|
print("Nothing left to compress.")
|
||||||
return
|
return
|
||||||
if (lo, hi) != todo[0]:
|
if (lo, hi) != todo[0]:
|
||||||
die("Wrong block: %s. Blocks are built in order; the next is "
|
if tree_get(d, lo, hi) is not None:
|
||||||
"%d-%d. Run: memo sleep"
|
print("%d-%d is already settled." % (lo, hi - 1))
|
||||||
% (args[0], todo[0][0], todo[0][1] - 1))
|
else:
|
||||||
if not tree_put(d, lo, hi, check(args[1])):
|
die("Wrong block: %s. Blocks are built in order; the next is "
|
||||||
print("Another session already wrote %d-%d." % (lo, hi - 1))
|
"%d-%d. Run: memo sleep"
|
||||||
|
% (args[0], todo[0][0], todo[0][1] - 1))
|
||||||
|
elif not tree_put(d, lo, hi, check(args[1])):
|
||||||
|
print("%d-%d was settled or forgotten meanwhile." % (lo, hi - 1))
|
||||||
else:
|
else:
|
||||||
print("%d-%d saved." % (lo, hi - 1))
|
print("%d-%d saved." % (lo, hi - 1))
|
||||||
nap = next_nap(d, T)
|
nap = next_nap(d, T)
|
||||||
|
|
@ -445,7 +449,8 @@ def cmd_recall(d, args):
|
||||||
pat = re.compile(args[0], re.I)
|
pat = re.compile(args[0], re.I)
|
||||||
except re.error as e:
|
except re.error as e:
|
||||||
die("bad regex: %s" % e)
|
die("bad regex: %s" % e)
|
||||||
hits = [e for e in log_slice(d, 0, log_len(d)) if pat.search(e[2])]
|
hits = [e for e in log_slice(d, 0, log_len(d))
|
||||||
|
if pat.search("#%d %s %s" % e)]
|
||||||
if not hits:
|
if not hits:
|
||||||
print("No match.")
|
print("No match.")
|
||||||
return
|
return
|
||||||
|
|
|
||||||
23
test.py
23
test.py
|
|
@ -167,6 +167,7 @@ check(r.returncode == 1 and "Cannot wake" in r.stdout,
|
||||||
"wake must refuse while work is pending")
|
"wake must refuse while work is pending")
|
||||||
check("run memo wake again" in r.stdout,
|
check("run memo wake again" in r.stdout,
|
||||||
"the refusal must order the agent back to wake")
|
"the refusal must order the agent back to wake")
|
||||||
|
check("None" not in r.stdout, "the refusal printed a Python None")
|
||||||
|
|
||||||
# sleep loop, with a fake compressor
|
# sleep loop, with a fake compressor
|
||||||
naps = 0
|
naps = 0
|
||||||
|
|
@ -229,10 +230,17 @@ r = run("sleep", "0-1", "attempted overwrite")
|
||||||
check(r.returncode == 0 and "Nothing left to compress" in r.stdout,
|
check(r.returncode == 0 and "Nothing left to compress" in r.stdout,
|
||||||
"sleep with nothing pending must say so and write nothing")
|
"sleep with nothing pending must say so and write nothing")
|
||||||
|
|
||||||
# recall reaches memories the summaries lost
|
# recall reaches memories the summaries lost, and matches the whole line:
|
||||||
|
# id and date included, not just the text
|
||||||
r = run("recall", "memory number 7,")
|
r = run("recall", "memory number 7,")
|
||||||
check(r.returncode == 0 and "#7 " in r.stdout, "recall missed a memory")
|
check(r.returncode == 0 and "#7 " in r.stdout, "recall missed a memory")
|
||||||
check("1 match." in r.stdout, "a single match is not `1 matches`: " + r.stdout)
|
check("1 match." in r.stdout, "a single match is not `1 matches`: " + r.stdout)
|
||||||
|
r = run("recall", "^#7 ")
|
||||||
|
check("memory number 7," in r.stdout, "recall cannot find a memory by id")
|
||||||
|
r = run("recall", "2020-01-02")
|
||||||
|
check("#7 " in r.stdout and "5 matches." in r.stdout,
|
||||||
|
"recall cannot find memories by date: " + r.stdout)
|
||||||
|
|
||||||
|
|
||||||
def treesize():
|
def treesize():
|
||||||
t = os.path.join(d, "TREE")
|
t = os.path.join(d, "TREE")
|
||||||
|
|
@ -244,11 +252,18 @@ check("16-31" in r.stdout, "forget did not report the block: " + r.stdout + r.st
|
||||||
check(treesize() < before, "forget did not shrink the tree")
|
check(treesize() < before, "forget did not shrink the tree")
|
||||||
check(os.path.getsize(os.path.join(d, "LOG.txt")) == logsize, "forget touched the log")
|
check(os.path.getsize(os.path.join(d, "LOG.txt")) == logsize, "forget touched the log")
|
||||||
check(run("wake").returncode == 1, "wake should refuse after a forget")
|
check(run("wake").returncode == 1, "wake should refuse after a forget")
|
||||||
# a block already settled cannot be rewritten: only the first pending block
|
# a settled block cannot be rewritten. Resubmitting one (two sessions paid
|
||||||
# is ever accepted
|
# the same nap) is not an error: say it is settled, write nothing
|
||||||
|
mid = treesize()
|
||||||
r = run("sleep", "0-1", "attempted overwrite")
|
r = run("sleep", "0-1", "attempted overwrite")
|
||||||
|
check(r.returncode == 0 and "already settled" in r.stdout,
|
||||||
|
"resubmitting a settled block was not reported as settled: " + r.stderr)
|
||||||
|
check(treesize() == mid, "resubmitting a settled block wrote something")
|
||||||
|
# a block that is neither settled nor next (here: a dropped ancestor,
|
||||||
|
# submitted before its half is rebuilt) is a real mistake
|
||||||
|
r = run("sleep", "0-31", "out of order")
|
||||||
check(r.returncode == 1 and "Wrong block" in r.stderr,
|
check(r.returncode == 1 and "Wrong block" in r.stderr,
|
||||||
"rewriting a settled block was allowed")
|
"an out-of-order block was accepted")
|
||||||
n = 0
|
n = 0
|
||||||
while True:
|
while True:
|
||||||
r = run("sleep")
|
r = run("sleep")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue