packages feed

keiro-dsl-0.21.0.0: test/mapped-register-construction-mutation-test.sh

#!/usr/bin/env bash
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"

fixture="keiro-dsl/test/fixtures/mapped-register-construction.keiro"
transducer="keiro-dsl/test/conformance-mapped-register-construction/Generated/MappedRegisterConstruction/Lifecycle/Transducer.hs"
lift="keiro-dsl/test/conformance-mapped-register-construction/Conformance/MappedRegisterConstruction/Lift.hs"
backup_dir="$(mktemp -d "${TMPDIR:-/tmp}/keiro-mapped-register-mutation.XXXXXX")"
case "$backup_dir" in *keiro-mapped-register-mutation.*) ;; *) exit 1 ;; esac
cp "$fixture" "$backup_dir/fixture"
cp "$transducer" "$backup_dir/transducer"
cp "$lift" "$backup_dir/lift"
restore() {
  cp "$backup_dir/fixture" "$fixture"
  cp "$backup_dir/transducer" "$transducer"
  cp "$backup_dir/lift" "$lift"
}
cleanup() {
  restore
  rm -f "$backup_dir/fixture" "$backup_dir/transducer" "$backup_dir/lift" "$backup_dir/red.log"
  rmdir "$backup_dir"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
baseline_digest="$(shasum -a 256 "$fixture" "$transducer" "$lift")"

run_green() {
  cabal test -v0 keiro-dsl-conformance-mapped-register-construction --test-show-details=direct
}
run_check() {
  cabal run -v0 keiro-dsl -- check "$fixture"
}
expect_red() {
  local label="$1" expected="$2"
  shift 2
  set +e
  "$@" >"$backup_dir/red.log" 2>&1
  local status=$?
  set -e
  if [[ "$status" -eq 0 ]] || ! rg -F "$expected" "$backup_dir/red.log" >/dev/null; then
    cat "$backup_dir/red.log"
    echo "FAIL: mutation did not fail its named gate: $label ($expected)"
    exit 1
  fi
  echo "PASS: mutation fails its named gate: $label"
  restore
}
mutate() {
  python3 - "$1" "$fixture" "$transducer" "$lift" <<'PY'
import pathlib, re, sys
mode, fixture, transducer, lift = sys.argv[1:]
p = pathlib.Path(lift if mode == 'body' else fixture if mode in ['projection', 'arithmetic-projection', 'ownership'] else transducer)
s = p.read_text()
if mode == 'body':
    s = s.replace('atTime value = MaybeTime (Just value)', 'atTime _value = MaybeTime Nothing')
elif mode == 'identity':
    s, count = re.subn(r'lifecycleFoldFingerprint = "[0-9a-f]{32}"', 'lifecycleFoldFingerprint = "omitted-lift-provenance"', s)
    assert count == 1
elif mode == 'recovery':
    s = s.replace('{ markedAt = d.markedAt', '{ markedAt = K.opaqueLit (read "1970-01-01 00:00:00 UTC")', 1)
elif mode == 'guard':
    s = s.replace('        B.requireGuard $\n          B.reg @"automatic" .== K.lit True\n', '', 1)
elif mode == 'slot':
    s = s.replace('K.TApp1 Lift.atTime (d.markedAt)', 'K.opaqueLit Bindings.noTime', 1)
elif mode == 'output':
    s = s.replace('{ markedAt = d.markedAt', '{ markedAt = K.TApp1 id (d.markedAt)', 1)
elif mode == 'ownership':
    s = s.replace('write dormantSince := mapped(cmd.markedAt)', 'implementation hole\n    write dormantSince := mapped(cmd.markedAt)', 1)
else:
    declaration = '''mapped structural record ScalarCarrier {
  haskell package=keiro-dsl module=Conformance.MappedRegisterConstruction.Domain type=ScalarCarrier
  binding = "Conformance.MappedRegisterConstruction.Bindings.scalarBinding"
  binding-version = "1"
  canonical-type = "conformance.ScalarCarrier.v1"
  fixtures = "Conformance.MappedRegisterConstruction.Bindings.scalarCases"
  initial = "Conformance.MappedRegisterConstruction.Bindings.scalarInitial"
  wire object constructor=ScalarCarrier unknown-fields=reject {
    observed as "observed" : Time required
    count as "count" : Integer required
  }
}

'''
    s = s.replace('aggregate Lifecycle', declaration + 'aggregate Lifecycle')
    s = s.replace('    automatic Bool = False', '    automatic Bool = False\n    carrier ScalarCarrier = initial')
    if mode == 'projection':
        s = s.replace('mapped(cmd.markedAt)', 'mapped(reg.carrier.observed)')
    else:
        s = s.replace('write-lift from Time', 'write-lift from Integer')
        s = s.replace('mapped(cmd.markedAt)', 'mapped(reg.carrier.count + 1)')
assert s != p.read_text(), mode
p.write_text(s)
PY
}

run_green
mutate body
expect_red "lift contradicts declared cases" "FAIL  structural/write-lift case: MaybeTime/epoch" run_green
mutate identity
expect_red "lift provenance omitted from generated identity" "FAIL  lift version participates in fold and snapshot identity" run_green
mutate recovery
expect_red "head event no longer recovers the command" "FAIL  validateTransducer is empty" run_green
mutate guard
expect_red "generated sibling guard bypassed" "FAIL  complementary guard verification remains disjoint" run_green
mutate slot
expect_red "generated mapped slot bypassed" "FAIL  generated mapped lift writes the command timestamp" run_green
mutate output
expect_red "lift moved into event output" "FAIL  mapped lift occurs only inside declared register slots" run_green
mutate projection
expect_red "mapped projection wrapped inside a lift" "AggregateExpressionMappedLiftProjectionUnsupported" run_check
mutate arithmetic-projection
expect_red "projection hidden under arithmetic" "AggregateExpressionMappedLiftProjectionUnsupported" run_check
mutate ownership
expect_red "Hole combined with a declared write" "AggregateTransitionOwnershipConflict" run_check
[[ "$(shasum -a 256 "$fixture" "$transducer" "$lift")" == "$baseline_digest" ]]
run_green
cabal test -v0 keiro-dsl-test --test-options='--match "mapped register construction"' --test-show-details=direct