tinymux/testcases/lambda_fn.mux
Stephen Dennis 66f5255433 tests: convert lambda and command-test hash pins to semantic assertions (#755)
41 more pins gone across seven files. Every preimage was recovered and
verified by hashing the candidate locally before substituting:

- lambda_fn: all values derivable from the lambda semantics
  (map +1 over 1..5 is "2 3 4 5 6", fold add is 15, ulambda mul(6,7)
  and u(#apply/inc,41) are both sha1("42"), the empty-lambda result is
  the sha1 of the empty string - now asserted via strlen)
- if/switch/wait/trigger/dolist_cmd: the pinned tcNNN_result values
  were the strings the tests themselves set ("true", "matched",
  "untouched", "AB" from @switch's match-all default, "Hello World"
  from #$ substitution, "alpha bravo charlie" from %0 %1 %2 and ##)
- oemit_fn: both pins were sha1("") - oemit returns nothing - now
  asserted via strlen

Failure messages echo the actual value instead of %q0's hash.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:54:19 -06:00

200 lines
5.5 KiB
Text

#
# lambda_fn.mux - Test Cases for #lambda and #apply.
#
@create test_lambda_fn
-
@set test_lambda_fn=INHERIT QUIET
-
#
# Beginning of Test Cases
#
&tr.tc000 test_lambda_fn=
@log smoke=Beginning lambda test cases.
-
#
# Test Case #1 - map with #lambda.
# map(#lambda/add(\%0,1), 1 2 3 4 5) => 2 3 4 5 6
#
&tr.tc001 test_lambda_fn=
@if strmatch([map(#lambda/add(\%0,1), 1 2 3 4 5)], 2 3 4 5 6)=
{
@log smoke=TC001: map with lambda. Succeeded.
},
{
@log smoke=TC001: map with lambda. Failed (actual=.[map(#lambda/add(\%0,1), 1 2 3 4 5)].).
}
-
#
# Test Case #2 - filter with #lambda.
# filter(#lambda/gt(\%0,3), 1 2 3 4 5) => 4 5
#
&tr.tc002 test_lambda_fn=
@if strmatch([filter(#lambda/gt(\%0,3), 1 2 3 4 5)], 4 5)=
{
@log smoke=TC002: filter with lambda. Succeeded.
},
{
@log smoke=TC002: filter with lambda. Failed (actual=.[filter(#lambda/gt(\%0,3), 1 2 3 4 5)].).
}
-
#
# Test Case #3 - fold with #lambda.
# fold(#lambda/add(\%0,\%1), 1 2 3 4 5) => 15
#
&tr.tc003 test_lambda_fn=
@if strmatch([fold(#lambda/add(\%0,\%1), 1 2 3 4 5)], 15)=
{
@log smoke=TC003: fold with lambda. Succeeded.
},
{
@log smoke=TC003: fold with lambda. Failed (actual=.[fold(#lambda/add(\%0,\%1), 1 2 3 4 5)].).
}
-
#
# Test Case #4 - ulambda with #lambda.
# ulambda(#lambda/mul(\%0,\%1), 6, 7) => 42
#
&tr.tc004 test_lambda_fn=
@if strmatch([ulambda(#lambda/mul(\%0,\%1), 6, 7)], 42)=
{
@log smoke=TC004: ulambda with lambda. Succeeded.
},
{
@log smoke=TC004: ulambda with lambda. Failed (actual=.[ulambda(#lambda/mul(\%0,\%1), 6, 7)].).
}
-
#
# Test Case #5 - #apply/funcname (single arg).
# map(#apply/strlen, foo bar quux) => 3 3 4
#
&tr.tc005 test_lambda_fn=
@if strmatch([map(#apply/strlen, foo bar quux)], 3 3 4)=
{
@log smoke=TC005: apply with map. Succeeded.
},
{
@log smoke=TC005: apply with map. Failed (actual=.[map(#apply/strlen, foo bar quux)].).
}
-
#
# Test Case #6 - #apply2/funcname (two args).
# mix(#apply2/add, 1 2 3, 4 5 6) => 5 7 9
#
&tr.tc006 test_lambda_fn=
@if strmatch([mix(#apply2/add, 1 2 3, 4 5 6)], 5 7 9)=
{
@log smoke=TC006: apply2 with mix. Succeeded.
},
{
@log smoke=TC006: apply2 with mix. Failed (actual=.[map(#apply/strlen, foo bar quux)].).
}
-
#
# Test Case #7 - Case insensitivity.
# map(#LAMBDA/add(\%0,10), 1 2 3) => 11 12 13
#
&tr.tc007 test_lambda_fn=
@if strmatch([map(#LAMBDA/add(\%0,10), 1 2 3)], 11 12 13)=
{
@log smoke=TC007: lambda case insensitivity. Succeeded.
},
{
@log smoke=TC007: lambda case insensitivity. Failed (actual=.[map(#apply/strlen, foo bar quux)].).
}
-
#
# Test Case #8 - sortby with #lambda.
# sortby(#lambda/sub(\%1,\%0), 5 3 1 4 2) => 1 2 3 4 5
#
&tr.tc008 test_lambda_fn=
@if strmatch([sortby(#lambda/sub(\%1,\%0), 5 3 1 4 2)], 5 4 3 2 1)=
{
@log smoke=TC008: sortby with lambda. Succeeded.
},
{
@log smoke=TC008: sortby with lambda. Failed (actual=.[map(#apply/strlen, foo bar quux)].).
}
-
#
# Test Case #9 - #apply with no digit defaults to 1 arg.
# u(#apply/inc, 41) => 42
#
&tr.tc009 test_lambda_fn=
@if strmatch([u(#apply/inc, 41)], 42)=
{
@log smoke=TC009: apply with u. Succeeded.
},
{
@log smoke=TC009: apply with u. Failed (actual=.[u(#apply/inc, 41)].).
}
-
#
# Test Case #10 - #lambda with empty body.
# u(#lambda/, 5) => (empty)
#
&tr.tc010 test_lambda_fn=
@if eq(strlen(u(#lambda/, 5)), 0)=
{
@log smoke=TC010: lambda empty body. Succeeded.
},
{
@log smoke=TC010: lambda empty body. Failed (actual=.[u(#lambda/, 5)].).
}
-
#
# Test Case #11 - ulambda bodies JIT-compile via mux_exec (#718), including
# the runtime-arg float paths through the tier2 blob (#778). ulambda() is
# now routed through mux_exec instead of ast_exec, so cargs (%0,%1,...) feed
# the JIT-compiled body. Semantic checks cover int, float (sub/fdiv/sqrt),
# and a nested body so a regression in either the route flip or the blob
# float intrinsics shows up as a wrong value, not an opaque hash.
#
&tr.tc011 test_lambda_fn=
@if cand(
strmatch(ulambda(#lambda/mul(\%0,\%1),6,7),42),
strmatch(ulambda(#lambda/sub(\%0,\%1),3.5,1.25),2.25),
strmatch(ulambda(#lambda/fdiv(\%0,\%1),20,8),2.5),
strmatch(ulambda(#lambda/sqrt(\%0),16),4),
strmatch(ulambda(#lambda/mul(add(\%0,\%1),\%2),2,3,4),20)
)=
{
@log smoke=TC011: ulambda JIT cargs float math. Succeeded.;
},
{
@log smoke=TC011: ulambda JIT cargs float math. Failed (mul=[ulambda(#lambda/mul(\%0,\%1),6,7)] sub=[ulambda(#lambda/sub(\%0,\%1),3.5,1.25)] fdiv=[ulambda(#lambda/fdiv(\%0,\%1),20,8)] sqrt=[ulambda(#lambda/sqrt(\%0),16)] nest=[ulambda(#lambda/mul(add(\%0,\%1),\%2),2,3,4)]).;
}
-
#
# Test Case #12 - ulambda() honors AF_NOEVAL, mirroring u() (#786).
# A no_eval attribute is returned literally, not evaluated; a plain
# attribute still evaluates. ulambda's output must equal u()'s.
#
&fn.noev test_lambda_fn=add(%0,%1)
-
@set test_lambda_fn/fn.noev=no_eval
-
&tr.tc012 test_lambda_fn=
@if cand(
strmatch(u(me/fn.noev,2,3), add\(*\)),
strmatch(ulambda(me/fn.noev,2,3), add\(*\)),
strmatch(ulambda(me/fn.noev,2,3), u(me/fn.noev,2,3)),
strmatch(ulambda(#lambda/add(\%0,\%1),2,3), 5)
)=
{
@log smoke=TC012: ulambda AF_NOEVAL parity. Succeeded.;
@trig me/tr.done
},
{
@log smoke=TC012: ulambda AF_NOEVAL parity. Failed (u=[u(me/fn.noev,2,3)] ulambda=[ulambda(me/fn.noev,2,3)] plain=[ulambda(#lambda/add(\%0,\%1),2,3)]).;
@trig me/tr.done
}
-
&tr.done test_lambda_fn=
@log smoke=End lambda test cases.;
@notify smoke
-
drop test_lambda_fn
-
#
# End of Test Cases
#