test system

This commit is contained in:
dzaima 2023-05-21 16:51:39 +03:00
parent d15d8febbe
commit e91f38a050
13 changed files with 1071 additions and 0 deletions

1
.gitignore vendored
View File

@ -31,6 +31,7 @@ cbqn-jit.bqn
/test/ffi/shared.got /test/ffi/shared.got
/test/ffi/sharedTest /test/ffi/sharedTest
/test/ffi/lib.so /test/ffi/lib.so
/test/testDir/
# other # other
/local/ /local/

View File

@ -6,6 +6,7 @@ Must be run from the projects root directory.
test/mainCfgs.sh path/to/mlochbaum/BQN // run the test suite for a couple primary configurations test/mainCfgs.sh path/to/mlochbaum/BQN // run the test suite for a couple primary configurations
test/x86Cfgs.sh path/to/mlochbaum/BQN // run the test suite for x86-64-specific configurations, including singeli; 32-bit build is "supposed" to fail one test involving ⋆⁼ test/x86Cfgs.sh path/to/mlochbaum/BQN // run the test suite for x86-64-specific configurations, including singeli; 32-bit build is "supposed" to fail one test involving ⋆⁼
test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations; requires dzaima/BQN to be accessible as dbqn test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations; requires dzaima/BQN to be accessible as dbqn
test/run.bqn // run tests in test/cases/
./BQN test/cmp.bqn // fuzz-test scalar comparison functions =≠<≤>≥ ./BQN test/cmp.bqn // fuzz-test scalar comparison functions =≠<≤>≥
./BQN test/equal.bqn // fuzz-test 𝕨≡𝕩 ./BQN test/equal.bqn // fuzz-test 𝕨≡𝕩
./BQN test/copy.bqn // fuzz-test creating new arrays with elements copied from another ./BQN test/copy.bqn // fuzz-test creating new arrays with elements copied from another
@ -23,4 +24,25 @@ make -C test/ffi // test FFI functionality; expects both regular and shared libr
legacy utilities: legacy utilities:
test/readTests.bqn // read mlochbaum/BQN tests in various formats test/readTests.bqn // read mlochbaum/BQN tests in various formats
test/precompiled.bqn // run a precompiled expression test/precompiled.bqn // run a precompiled expression
```
Format of tests in `test/cases/`:
```python
%DEF somename some code # add a definition to be used by later tests or other %DEFs
%USE somename # copy-paste in the code of the given definition to here
tests:
code that runs some !assertions # if there are no '!'s, 'lint' will complain
!"error message" % erroring code # can be written as "!% erroring code" at first, and let 'update-messages' insert the message
code %% expected value
(
multiline
code
running !assertions
# the '(' and ')' lines must have no other characters in them
)
# flags addable anywhere in code:
%SLOW # enable only if 'slow' argument present
%NDEBUG # disable if 'debug' argument present
%NHEAPVERIFY # disable if 'heapverify' argument present
``` ```

31
test/cases/cells.bqn Normal file
View File

@ -0,0 +1,31 @@
%DEF k _k {𝔽•internal.Keep}
%DEF tcc %USE k _tcc { ! ´ (<𝕨 𝔽_k˘'e' 𝕩) ¨ (𝕨 𝔽˘'e'•internal.Variation𝕩)¨ "i"•internal.ListVariations 𝕩}
•internal.Type¨ {𝕩-˜𝕩+23'¯'}¨ 0100100000 %% "c8arr""c16arr""c32arr" # assumed by test/cells.bqn
12 10 1 %% 11
1 10 12 %% 11
! 201200˘a20304024 ! 203040 a
! (2-1 {2-𝕩}1) 1010100
! (-21 {𝕩-2}1) 1010100
%USE k n1 {𝕊: (•Repr a) ! (n _kn)´ a((322'a'+26))¨ <˘ 2222•rand.Range 3}¨ 1000
%USE k n2 {𝕊: (•Repr a) ! (n _kn)´ a((322'a'+26))¨ <˘ 2222•rand.Range 3}¨ 1000
%USE k n3 {𝕊: (•Repr a) ! (n _kn)´ a((322'a'+26))¨ <˘ 2222•rand.Range 3}¨ 1000
{𝕊k: ! (3k {3𝕩}k) 222216}¨ ¯2+10
{𝕊k: ! (1k {1𝕩}k) 333381}¨ ¯2+10
!"˘: Result rank too large" % (02542)1˘ 021
!"⎉: Result rank too large" % (02542)1¯1 021
!"⎉: Result rank too large" % (1˜ 02042)50 1˜ 01002
!"⎉: Result rank too large (204 ≡ =𝕩, 200 ≡ =𝔽v)" % {𝕊:(2001)1}1 (2051)1
!"⎉: Argument frames don't agree (⟨3⟩ ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩, common frame of 1 axes)" % "abc" 0 "ab"
!"˘: Argument frames don't agree (⟨3⟩ ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩, common frame of 1 axes)" % "abc" ˘ "ab"
! ´{𝕊: ! ({𝕨𝕩}´) (<•rand.Range "ab",12,,0,"") ˜ (4•rand.Range) 1, {}, 'a', <'a', <{}, "ab", 0, ""}¨10000
%USE tcc 2, 20, ¯2, ¯20, 0 {𝕨 _tcc 𝕩 𝕨 _tcc 𝕩} <4, 5, 4520, 456120
%USE tcc <, , , {𝕎 _tcc 𝕩} <4, 5, 4520, 456120, 2345120
%USE tcc <, , {𝕎 _tcc 𝕩} <4, 5, 4520, 456120, 2345120
%USE tcc {𝕎 _tcc 𝕩} 4520, 456120, 2345120
%USE tcc _tcc 428 1_tcc 428 _tcc 42 1_tcc 42
%USE tcc _tcc 428 1_tcc 428 _tcc 42 1_tcc 42

20
test/cases/fills.bqn Normal file
View File

@ -0,0 +1,20 @@
%DEF fill Fill•internal.HasFill'e'{10𝕩}
%USE fill F 0,1,{},+,@,'𝕩' FillF , 00, 0, 020, "", 20"" %NHEAPVERIFY %% 24/['e',00,0,0,'e','e','e','e','e','e','e','e']
%USE fill F+ 0,1,{},+,@,'𝕩' FillF , 00, 0, 020, "", 20"" %NHEAPVERIFY %% 66'e',00,0,0,' ',' ','e',00,0,0,' ',' ','e','e','e','e','e','e','e','e','e','e','e','e','e'," ",' ',' ','e','e','e'," ",' ',' ','e','e'
%USE fill F- 0,1,{},+,@,'𝕩' FillF , 00, 0, 020, "", 20"" %NHEAPVERIFY %% 66'e',00,0,0,'e','e','e',00,0,0,'e','e','e','e','e','e','e','e','e','e','e','e','e','e','e'," ",' ',' ',0,0,'e'," ",' ',' ',0,0
%USE fill F-˜ 0,1,{},+,@,'𝕩' FillF , 00, 0, 020, "", 20"" %NHEAPVERIFY %% 66'e',00,0,0,' ',' ','e',00,0,0,' ',' ','e','e','e','e','e','e','e','e','e','e','e','e','e','e','e','e',0,0,'e','e','e','e',0,0
%USE fill (> !Fill )¨ 0, ""
%USE fill ,Fill,Fill Fill{𝕎𝕩}¨< 0012<2 %% ,,00
!¥internal.HasFill <"hello"+
%USE fill fa Fill¨ a0, 234, 204, 023, 2<0,'a',{},12 {𝕊f : fa {!𝕨Fill F 𝕩}¨ a}¨ , 0/, 0, 0, 0, fa %% 5/0,' ','e',00
%USE fill a10<12 { a𝕩@}¨100<<12 Fill a %% 00
%USE fill a10<12 {a0a a𝕩@}¨100<<12 Fill a %% 00
%USE fill {𝕊: a10<12 { a𝕩@}¨(𝕩<<12)<<123 a!'e'Fill a}¨ 100
%USE fill {𝕊: a10<12 {a0a a𝕩@}¨(𝕩<<12)<<123 a!'e'Fill a}¨ 100
# TODO:
# ⟨↑‿3⥊↕10 ⋄ ↑‿3⥊<¨↕10 ⋄ ↑‿3⥊<˘↕10⟩
# 5‿¯5↑⌜⟨↕2 ⋄ "ab" ⋄ <¨↕2 ⋄ <˘↕2⟩

13
test/cases/fuzz.bqn Normal file
View File

@ -0,0 +1,13 @@
(
# character 𝕨∊𝕩
VVariation,LVListVariations,CLClearRefs,EEEEqual•internal
R •rand.Range
_t{w F _𝕣 x: ´EE¨(LV 𝕨){(𝕨 V w) F 𝕩 V x}LV𝕩?CL@; •Show¨𝕗𝕨𝕩!0}
GS{𝕊: @+0(¯1+2R78151620) - R˜R 200}
{𝕊:(GS@) _t GS@}¨1000
)
(
# ∾𝕩 not getting garbage
{𝕊: ! ´1=1 1¨ (4•rand.Range 3) •rand.Range¨ 4}¨10000
)

46
test/cases/hash.bqn Normal file
View File

@ -0,0 +1,46 @@
# some checks for behavior around ¯0; not strictly necessary to stay, but other tests will probably become meaningless without these!
1641•bit._cast ˘ •ParseFloat¨ "1.2""-0" %% 631/01
! (40) ( (641•bit._cast)) 1¯1×π40
! ˝641•bit._cast ˘05(¯1×) (3)0÷0
# ¯0
! ´ {•Hash •ParseFloat¨ 𝕩"1.2"}¨ "0""-0"
! 10 {•ParseFloat¨ 𝕩"1.2"}¨ "0""-0"
a(•ParseFloat¨ "1.2""-0""0")-0÷0 1•Hash¨ a %% 11010
a(•ParseFloat¨ "1.2""-0""0")-0÷0 b0+--a ! a •internal.EEqual b ! a (3) b ! 0a •Cmp b ! a (1•Hash¨) b ! a (1•Hash) b
a(•ParseFloat¨ "1.2""-0""0")-0÷0 ! (0333a) •Hash (0444a)
# functions
, , +, +, +, , , +, 1+, 1+, 2+, 1+, 1×, +, , +, +˘, ע, +˘, +˝ %% , +, +, +, , +, 1+, 2+, 1+, 1×, +˘, ע, +˝
# various
[11, 01, 10, 00, 11, 00] [00, 01, 10] %% 011101
[[00, 01, 10, 11], [11, 01, 10, 00]] [00, 01, 10] %% 2411100111
[11, 01, 10, 00, 11, 00] (0) [00, 01, 10] %% 011101
[[00, 01, 10, 11], [11, 01, 10, 00]] (0) [00, 01, 10] %% 2411100111
˜˜"ihxtIddKLp"'r'÷"EXiRowcDXx"'a'"ZNtqFbDCYZ"0.053691254943265545 %% ˜10
01˜"ab","cd" %% 00
01 "ab","cd" %% 22
(<"ab")"ab""cd" %% <1
(<"cd")"ab""cd" %% <1
(<"ef")"ab""cd" %% <0
(127"abc")"abcd" %% 012127
(128"abc")"abcd" %% 012128
(32767"abc")"abcd" %% 01232767
(32768"abc")"abcd" %% 01232768
(127"abc")100"ababacadabacaba" %% (1000101020 1270102010)
(128"abc")100"ababacadabacaba" %% (1000101020 1280102010)
(32767"abc")100"ababacadabacaba" %% (1000101020327670102010)
(32768"abc")100"ababacadabacaba" %% (1000101020327680102010)
•internal.Variation(1)¨ "Ab""Ai8" %% 0
!¨ 0•Hash¨ 5 10.55 1'h'5
{b•internal.Unshare a"Ai8"•internal.Variation 160000000¯128, 80, 82 c864•bit._cast a ! 1001c •internal.Keep •Hash c ! ab} # make sure sign bit doesn't mutate away
# error messages
!"∊: 𝕩 cannot have rank 0" % 1230
!"⊐: 𝕨 cannot have rank 0" % 0123
!"⊒: 𝕨 cannot have rank 0" % 0123
!"∊: Rank of 𝕨 must be at least the cell rank of 𝕩 (⟨2⟩ ≡ ≢𝕨, 2‿2‿2 ≡ ≢𝕩)" % 1222212
!"⊐: Rank of 𝕩 must be at least the cell rank of 𝕨 (2‿2‿2 ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩)" % (22212)12
!"⊒: Rank of 𝕩 must be at least the cell rank of 𝕨 (2‿2‿2 ≡ ≢𝕨, ⟨2⟩ ≡ ≢𝕩)" % (22212)12

53
test/cases/patterns.bqn Normal file
View File

@ -0,0 +1,53 @@
%DEF k _k {𝔽•internal.Keep}
# weird "functions"
4 10´ %% 4
4 10˝ %% 4
4 10` %%
4 10´0 %% 4
4 10˝0 %% 4
4 10`0 %% 0
4 {˜}´0 %% 4
4 {˜}˝0 %% 4
4 {}`0 %% 0
{}¨0 %%
{˜}¨˜0 %%
!"Calling a modifier" % 4 {˜}´1
!"Calling a modifier" % 4 {˜}˝1
!"Calling a modifier" % 4 {}`1
!"Calling a modifier" % {}¨1
!"Cannot call a modifier" % {˜}¨˜1
4 {˜}˙´1 %% ˜
4 {˜}˙˝1 %% ˜
4 {}˙`1 %%
{}˙¨1 %%
{˜}˙¨˜1 %% ˜
4 "ab"`4 %% 4<"ab"
!"Calling a modifier" % {}˜ 10
{}˙˜ 10 %% 1010
"ab"` "hello" %% 'h'4<"ab"
# ˝ plus ˘
%USE k (+˝˘ ! +˝_k˘) 10000003•rand.Range 0
%USE k (-˜˝ ! -˜_k˝) 10 (•MakeRand 0).Range 1e5
%USE k (-˜˝˘ ! -˜_k˝˘) 310 (•MakeRand 0).Range 1e5
# +`
%USE k {𝕊: (+` ! +_k`) 1e3•rand.Range 0}¨1000
%USE k {𝕊: (•rand.Range 0) (+` ! +_k`) 1e3•rand.Range 0}¨1000
# <`
%USE k (<` ! <_k`)¨ (1000)¨ "Ab"•internal.Variation¨ "111000""1111000""0111000"-'0'
# ≠`
{𝕤b"Ab"•internal.Variation a"Ai32"•internal.Variation 1000 •rand.Range 2 ! (`a)`b}¨1000
{𝕤b"Ab"•internal.Variation a"Ai32"•internal.Variation 1000 •rand.Range 2 ! (0`a)0`b}¨1000
{𝕤b"Ab"•internal.Variation a"Ai32"•internal.Variation 1000 •rand.Range 2 ! (1`a)1`b}¨1000
# ´ & ∧´
{n𝕩 ! (1+n) +´¬{´(-𝕩)1n0}¨400}¨200 # ´ with a single 1; %SLOW
{n𝕩 ! (1+n) +´¬ {¬´¬(-𝕩)1n0}¨400}¨200 # ∧´ with a single 1; %SLOW
{!¬ ´𝕩0}¨1000 # ´ zeroes
{!¬ ´𝕩0}¨1+1000 # ∧´ zeroes
{! ´𝕩1}¨1+1000 # ´ ones
{! ´𝕩1}¨1000 # ∧´ ones

297
test/cases/prims.bqn Normal file

File diff suppressed because one or more lines are too long

54
test/cases/syntax.bqn Normal file
View File

@ -0,0 +1,54 @@
# body usage
a"zero""one" !aa{𝕩?1𝕨;0𝕨}¨01
!"No header matched argument" % { 𝕊ab: a+b ; d𝕊abc: a+b+c} 3
!"No header matched argument" % {d𝕊ab: a+b ; 𝕊abc: a+b+c} 2
{𝕊ab: a+b ; 𝕊abc: a+b+c} 2 %% 1
{𝕊ab: a+b ; 𝕊abc: a+b+c} 3 %% 3
{4=𝕩? "four" ; "idk: "𝕩}4+3 %% "four"
{4=𝕩? "four" ; "idk: "𝕩}3+3 %% "idk: "3,4,5
{𝕩+1 4=𝕩? 1𝕩 ; 2𝕩}3+3 %% 1,456
{𝕩+1 4=𝕩? 1𝕩 ; 2𝕩}4+3 %% 2,456
{𝕩𝕩+1 4=𝕩? 1𝕩 ; 2𝕩}3+3 %% 1,456
{𝕩𝕩+1 4=𝕩? 1𝕩 ; 2𝕩}4+3 %% 2,456
{1?"abc" ; "def"} %% "abc"
{0?"abc" ; "def"} %% "def"
{123456 1{2} 1 1{1+5}} %% 16
# forks with funky tines
{(𝕩 "ab" 9) {fgh𝕨 TF G H T𝕩 (𝕩𝕩)T𝕩} 3}¨ 222 %% 222012,012,12012,012,012,12012,012,012,012,"ab",12012,012,012,"ab","ab","ab","ab","ab","ab",012,"ab",12012,012,012,"ab","ab","ab","ab","ab","ab","ab","ab"
# body inverses
!"No monadic undo header found for this block" % {𝕩} 1
!"No dyadic F⁼ undo header found for this block" % 1 {𝕩} 1
!"No dyadic F˜⁼ undo header found for this block" % 1 {𝕩}˜ 1
!"No monadic undo header found for this 1-modifier block" % +{𝔽𝕩} 1
!"No dyadic F⁼ undo header found for this 1-modifier block" % 1 +{𝔽𝕩} 1
!"No dyadic F˜⁼ undo header found for this 1-modifier block" % 1 +{𝔽𝕩}˜ 1
!"No monadic undo header found for this 2-modifier block" % +{𝔽𝔾𝕩}+ 1
!"No dyadic F⁼ undo header found for this 2-modifier block" % 1 +{𝔽𝔾𝕩}+ 1
!"No dyadic F˜⁼ undo header found for this 2-modifier block" % 1 +{𝔽𝔾𝕩}+˜ 1
# assignment
!"Reading variable before its defined" % {a} a1
!"↩: Reading variable that hasn't been set" % {a10} a2
!"↩: Updating variable that hasn't been set" % {a10} a2
!"↩: Reading variable that hasn't been set" % {a (10)˙} a2
!"Assignment: Mismatched shape for spread assignment" % ab1
!"Assignment: Mismatched shape for spread assignment" % ab123
!"Assignment: Mismatched shape for spread assignment" % a<1
!"Assignment: Mismatched shape for spread assignment" % 1
!"Assignment: Mismatched shape for spread assignment" % 1
%%
# namespaces
a,b•BQN"{x⇐1‿2⋄a⇐3‿4⋄y←5‿6⋄b⇐7‿8}" ab %% 34 78
# immediate modifiers
!"No key found" % X12{a𝕗} bx
X12{a𝕗} ax +´a %% 3
X12{a𝕘-𝕗}34 ax +´a %% 4
a12{a𝕩+𝕗+𝕘}34 1 a %% 57
a12{a𝕩+𝕗} 1 a %% 23
# arguments
{x𝕩𝕩@𝕩x}-10 %% @-10

236
test/cases/system.bqn Normal file
View File

@ -0,0 +1,236 @@
# not tested here: •Out •Show •Exit •term •GetLine •Cmp •CurrentError •FFI •internal.HeapDump •file.MapBytes
%DEF var V•internal.Variation LV•internal.ListVariations
%DEF tvar %USE var _tvar {F _𝕣 x: {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (LV 𝕨) {(𝕨 V w) F 𝕩 V x} LV 𝕩}
# standard system values
# •BQN
%USE tvar !" "¨ •BQN _tvar "1↑"""""
•BQN "Ah"•internal.Variation"1↑""""" %% " "
# •ReBQN
f•ReBQN {system"all"} F "•internal.Type ↕10" %% "i8arr"
!"Unknown system function •internal" % f•ReBQN {system"none"} F "•internal.Type ↕10"
f•ReBQN {system"range" "add"+ "reverse"} F "•Reverse ¯5 •Add •Range 10" %% 4-10
f•ReBQN{} F "Ah"•internal.Variation"1↑""""" %% " "
# •primitives
!´2=•Type¨ ¨•primitives
!¨ (•Type¨1¨•primitives)345
# •state
6(1) •file.Name •state %% "testDir","system","arg0",1
# •args
•args %% "arg0",1
# •path & •file.path
•file.Name •path %% "testDir"
•file.Name •file.path %% "testDir"
# •name
6•name %% "system"
# •wdpath
! ´ 2=•Type¨ •wdpath
# •ns
{abc1 dÊF2}•ns.Get¨ "abc", "ABC", "abC", "abc___", "DêF", "__D__Ê__F__" %% 111122
!"No field named ""abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþabcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ𝕨𝕨⍉!0123456789"" found" % {abc1 dÊF2}•ns.Get "ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞabcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ𝕨𝕨⍉!0123456789_"
{abc1 dÊF2 n103}•ns.Has¨ "abc", "ABC", "abC", "abc___", "DêF", "__D__Ê__F__", "àbc", "def", "", 0, "𝕨", "012", "n10", "n1_0" %% 11111100000011
´{}•ns.Has¨"abc123AEWQE___àÀ𝕨𝕩" %% 0
!"•ns.Has: 𝕩 must be a string" % {}•ns.Has ""
!"•ns.Has: 𝕩 must be a string" % {}•ns.Has 12
!"•ns.Get: 𝕩 must be a string" % {}•ns.Get ""
!"•ns.Get: 𝕩 must be a string" % {}•ns.Get 12
{m𝕩 {𝕩 m•ns.Get 𝕩}¨ •ns.Keys m {m•ns.Has𝕩}¨ "abcABC"}¨ {a1b10} {a'a'b23cde𝕩}"abc" %% "a",1,"b",0123456789,110110,"a",'a',"cde","abc",100100
# files; tests are ordered!
{•file.Exists 𝕩? •SH"rmdir", •file.At 𝕩; 0} "testdirNested" %% 0
•file.Remove•file.Exists¨ "testfile.bqn""testfile2.bqn""testfile3B.bqn" 1 %% 1
•file.At "/a/b" %% "/a/b"
! (•file.At "a/b") •file.path •file.At "a/b"
"a/b" •file.At "c/d" %% "a/b/c/d"
"a/b/" •file.At "c/d" %% "a/b/c/d"
"a/b/" •file.At "c/d/" %% "a/b/c/d/"
"a/b/" •file.At "/c/d" %% "/c/d"
"a/b" •file.At "/c/d/" %% "/c/d/"
•file.Exists "/dev/file that doesn't exist" %% 0
!"Couldn't read file ""/dev/file that doesn't exist""" % •FChars "/dev/file that doesn't exist"
! (•path"/") •file.Parent •file.At "hi"
!"•file.Lines: 𝕩 must be a list" % "testfile.bqn" •FLines 22<"abcd"
!"•file.Lines: 𝕩 must be a list" % "testfile.bqn" •file.Lines <"abcd"
!"Expected character" % "testfile.bqn" •FChars "abcd"
!"•file.Chars: 𝕩 must be a list of characters" % "testfile.bqn" •FChars <'a'
!"Expected character" % "testfile.bqn" •FBytes "abcd"
!"•file.Bytes: 𝕩 must be a list" % "testfile.bqn" •file.Bytes <'a'
!"Path wasn't a list of characters" % 'a' •FChars "hi"
!"Path wasn't a list of characters" % (42"testfile.bqn") •file.Chars "hi"
! {𝕩•file.Name 𝕩 •FChars "abc"(@+10)"def𝕩"}"testfile.bqn"
! {𝕩•file.Name 𝕩 •FBytes •ToUTF8 "abc"(@+10)"def𝕩"}"testfile2.bqn"
! {𝕩•file.Name 𝕩 •FLines "abc""def𝕩"} "testfile3.bqn"
•file.Type "testfile.bqn" %% 'f'
•file.Type •file.path %% 'd'
!¨ 0{𝕏 "testfile.bqn"}¨ •file.Created•file.Accessed•file.Modified
•file.Size "testfile.bqn" %% 11
•FBytes¨ "testfile.bqn""testfile2.bqn""testfile3.bqn"
•FChars "testfile.bqn" %% "abc"(@+10)"def𝕩"
•FBytes "testfile.bqn" %% @+97989910100101102240157149169
•FLines "testfile.bqn" %% "abc""def𝕩"
"testfile3B.bqn" •file.Rename "testfile3.bqn"
•file.Exists¨ "testfile.bqn""nontestfile.bqn""testfile3.bqn""testfile3B.bqn" %% 1001
¯22•file.Createdir "testdirNested" %% "/testDir/testdirNested"
"testfile.bqn""testfile2.bqn""testfile3.bqn""testfile3B.bqn""testdirNested" •file.List "." %% 11011
"testfile.bqn""testfile2.bqn""testfile3.bqn""testfile3B.bqn""testdirNested" •file.List •file.path %% 11011
•file.Remove "testfile.bqn" %% 1
•file.Remove "testfile2.bqn" %% 1
•file.Remove "testfile3B.bqn" %% 1
"testfile.bqn""testfile2.bqn""testfile3B.bqn" •file.List "." %% 000
# •ParseFloat & •Repr
v1 ! •BQN•Repr +,12,+¨,(+V)(V+V),224
# v←1 ⋄ •BQN∘•Repr⊸≡ ⟨V V V, V V⟩ # TODO enable
641•bit._cast •ParseFloat¨ "123.456000000000000""123.45600000000002" %% "11101110011111011111100101011000111101001011101101111010000000100001111001111101111110010101100011110100101110110111101000000010"-'0'
! ´'e'=•ParseFloat'e'¨ "-""e2""-e2""."".e2""123e""123e-""123e+"
•ParseFloat "0."(n'0')"1234e"•Repr n1000000 %% 0.1234
•Repr•ParseFloat¨ "1.23516411460311636e-323", "1.23516411460311637e-323" %% "1e¯323","1.5e¯323"
•Repr•ParseFloat¨ "1.235164114603116360e-323", "1.235164114603116361e-323" %% "1e¯323","1e¯323"
•Repr•ParseFloat¨ "1.2351641146031163604e-323", "1.2351641146031163605e-323" %% "1e¯323","1e¯323"
# •Fmt
•Fmt 123 %% "123"
# •SH
•SH"true" %% 0
•SH"false" %% 1
{stdin"𝕩"@+256} •SH"cat" %% 0, "𝕩"@+256, ""
{stdin"𝕩"@+256 raw0} •SH"cat" %% 0, "𝕩"@+256, ""
{stdin@+256 raw1} •SH"cat" %% 0, @+256, ""
# •Type
•Type¨ "ab",'a'1,1,0÷0,'a',@+1114111,+,{𝕩},¨,{𝕗},,{𝔽𝕘},{},•rand %% 00112233445566
# •Glyph
•Glyph¨ +,¨, %% "+¨∘"
# •Decompose
{! 0𝕩 •Decompose 𝕩}¨ +, ¨, ˝
{! 1𝕩 •Decompose 𝕩}¨ {𝕩}, {𝔽𝕘}
{! ¯1𝕩 •Decompose 𝕩}¨ 1,'a',"ab"
•Decompose¨ +-×, -÷, +¨, 1+ %% 3,+,-,×,2,-,÷,4,+,¨,5,1,,+
# •UnixTime
•Type •UnixTime 10 %% 1
# •MonoTime
! ´•MonoTime¨2
# •Delay
t0•MonoTime@ ! 0.1•Delay 0.1 ! 0.1(•MonoTime@)-t0
# •_timed tested at perf.bqn
# •math
! ´0=|1e10×{(+´𝕩)-•math.Sum 𝕩}¨ 1000•rand.Range 0
!"•math.Sum: Argument must be a list (⟨⟩ ≡ ≢𝕩)" % •math.Sum 2
!"•math.Sum: Argument must be a list (2‿2 ≡ ≢𝕩)" % •math.Sum 221
!"•math.Sum: Argument elements must be numbers" % •math.Sum 1'a'
! {(𝕩 •math.Atan2 0) 𝕩 •math.Atan2 •ParseFloat"-0"} (-) ˜3
! {(0 •math.Atan2 𝕩) (•ParseFloat"-0") •math.Atan2 𝕩} (-) ˜3
E•internal.EEqual a(¯1×) (3)0÷0 {𝕩!(a 𝕏 0)E a 𝕏 •ParseFloat"-0" 𝕩!(0 𝕏 a)E(•ParseFloat"-0") 𝕏 a}¨ ({𝕏¨}¨) +,-,×,÷,,,,,|,¬,,,<,>,,=,,, •math.Atan2,•math.Comb,•math.Hypot
E•internal.EEqual {! (𝕏 40) E 𝕏 1¯1×π40}¨ ({𝕏¨}¨) +,-,×,÷,,,,,|,¬, •math.Sin,•math.Cos,•math.Tan,•math.Asin,•math.Acos,•math.Atan,•math.Sinh,•math.Cosh,•math.Tanh,•math.Asinh,•math.Acosh,•math.Atanh,•math.Cbrt,•math.Log2,•math.Log10,•math.Log1p,•math.Expm1,•math.Fact,•math.LogFact,•math.Erf,•math.ErfC
{15 𝕏 10}¨ •math.GCD,•math.LCM %% 530
1e5×{0.1 𝕏 0.2}¨ •math.Atan2,•math.Comb,•math.Hypot %% 1107149695922360
1e5×{=˜99¨ 𝕏 0.13}¨ •math.Acos,•math.Acosh,•math.Asin,•math.Asinh,•math.Atan,•math.Atanh,•math.Cbrt,•math.Cos,•math.Cosh,•math.Erf,•math.ErfC,•math.Expm1,•math.Fact,•math.Log10,•math.Log1p,•math.Log2,•math.LogFact,•math.Sin,•math.Sinh,•math.Tan,•math.Tanh %% 1470629900000,9900000176274,100169900000,9983181844,9966124904,100339900000,46415144224,99500¯99000,1005001006766,1124699997,887532,105171908553,95135600000,¯10000047712,9531138629,¯332193158496,¯4988179175,998314112,100161001787,10033¯14255,996699505
# •rand / •MakeRand
0 (•MakeRand 0).Range¨2 %%
00 (•MakeRand 0).Range¨2 %%
(•MakeRand 0).Deal 0 %%
0 (•MakeRand 0).Subset 0 %%
{!(•rand.Deal 𝕩)𝕩}¨ ¯101+222 # %SLOW
!"(rand).Range: Result rank too large (256≡≢𝕨)" % (2561) •rand.Range 0
! ˝ a{r•MakeRand 𝕩 r.Range 1e9, 100 r.Range 1e9, r.Deal 100, 100 r.Deal 200, 100 r.Deal 200}¨ 222 !¨´ a
# •bit
!"•bit._cast: 𝕩 must have rank at least 1" % 81 •bit._cast 123
(10) {! (𝕨¯1) 1𝕩•bit._cast (𝕨×𝕩)1} 81632
%USE var {t𝕩18163264 !¨ r{t•bit._cast 𝕩 V a}¨ LV a 128 r}¨ 44
%USE var {t𝕩18163264 !¨ r{t•bit._cast 𝕩 V a}¨ LV a4=128 r}¨ 44
! 101 816•bit._cast c02'a'+11 •rand.Range 26 ! 102 c
! 101 816•bit._cast c 2'a'+11 •rand.Range 26 ! 102 c
# CBQN-specific extensions
# •_while_
1+•_while_{𝕊: ´𝕩20} 10 %% 12+10
(101) +•_while_{𝕊: ´𝕩20} 10 %% 12+10
# •Hash
! ´ •Hash¨ 2<10,"ab"
! ´1 •Hash¨ 2<10,"ab"
# •ToUTF8
@-˜•ToUTF8 "𝕩⍉hello" %% 240157149169226141137104101108108111
# •FromUTF8
! •FromUTF8•ToUTF8 "𝕩⍉hello"
# •internal.GC
•internal.GC 10 %% 1
# •internal.Type & •internal.Variation & •internal.ElType & •internal.ListVariations
(
raw {("a"¨ 𝕩)"s"¨ 1𝕩} "b","i8","i16","i32","f64","c8","c16","c32","h","f"
var {ae: a-32, e}¨ raw
ty { {"a":"arr";"slice"}{"b":"bit"; "f":"fill"; 𝕩} {𝕎𝕩}¨ 𝕩}¨ raw
ty {"type"𝕨𝕩 ! 𝕨 •internal.Type 𝕩 •internal.Variation }¨ var
! 0123456788123456788 {•internal.ElType 𝕩 •internal.Variation }¨ var
# TODO test •internal.ListVariations
)
# •internal.Keep
•internal.Keep 10 %% 10
!"This function can't be called dyadically" % 1 •internal.Keep 1
# •internal.Refc
•internal.Refc •internal.Unshare 10 %% 1
a•internal.Unshare 10 b10<a ! 11 •internal.Refc a •internal.Keep b
# •internal.IsPure
! 1 •internal.IsPure +
! 1 •internal.IsPure +¨++
! 1 •internal.IsPure 123+¨++
! 1 •internal.IsPure -
! 0 •internal.IsPure {𝕩}-
! 0 •internal.IsPure 12{𝕩}+¨++ # could be 1
! 0 •internal.IsPure •show
! 0 •internal.IsPure •file.chars
# •internal.Info
•internal.Info 1 %% "3ff0000000000000: not heap-allocated"
33•internal.Info •internal.Unshare 10 %% "fff7: refc:1 type:23=i8arr alloc:"
# •internal.HasFill
•internal.HasFill¨ 0, 10, , 'a'1, "" %% 11001
# •internal.Squeeze
a"Ai32"•internal.Variation 10 •internal.Type •internal.Squeeze a %% "i8arr"
# •internal.DeepSqueeze
a"Ai32"•internal.Variation 10 •internal.Type •internal.DeepSqueeze a %% "i8arr"
# •internal.ClearRefs
•internal.ClearRefs@ •internal.Variation(10)¨ 10<"Ai32Inc" •internal.ClearRefs "foo" %% 10
# •internal.Unshare
•internal.Refc•internal.Unshare¨ 0, "", , 10 %% 1111
# •internal.EEqual
a10÷0,-0÷0•ParseFloat¨"0""1.2""-0" a •internal.EEqual a %% 1

View File

@ -0,0 +1,5 @@
(091,10 ¯5¯31 ¯5¯3¯4¯4¯4¯4¯4{¯2,𝕩-3,1,¯2+𝕩}¨1+100) {expa𝕊𝕩: exp (!) •internal.Temp 𝕩•internal.Variation a} "Ai8""Ai16""Ai32""Af64"
T ! ·•internal.Temp "Ab"•internal.Variation {𝕊n: 111 T 𝕩1 001 T 𝕩0 01 {011 T (¬𝕨)(𝕩) n𝕨}¨(n>1) 2•rand.Range n}¨1+500
{! 02•internal.Temp (263)(𝕩) 100}¨ 10
263, 1.5, 0÷0 {! 02•internal.Temp 𝕨(𝕩) 200} 20
{! 001 •internal.Temp 𝕩(𝕩0)100÷0}¨ 1+10

93
test/cases/under.bqn Normal file
View File

@ -0,0 +1,93 @@
# ¨ & ˘
# !% ⊢⌾(⊢¨) 4 # TODO enable
# !% ⊢⌾(⊢˘) 4 # TODO enable
# ⊏ & ⊑
!"𝔽⌾(a⊸⊑): Incompatible result elements" % 1020(12,12) 459
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 1020(33) 10
!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 102030(23) 10
!"𝔽⌾(a⊸⊏)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 1(23) 10
!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 102030(12,21) 4416
!"𝔽⌾(a⊸⊑)𝕩: 𝔽 must return an array with the same shape as its input (expected ⟨2⟩, got ⟨3⟩)" % 1(12,21) 4416
# ⊑
!"𝔽⌾(n⊸⊑)𝕩: reading out-of-bounds (n≡¯10, 3≡≠𝕩)" % 1+(¯10) 3
!"⊑: 𝕨 contained list with mixed-type elements" % 'a'(1'a') 459
!"⊑: Indexing out-of-bounds (index 1‿5 in array of shape 4‿5)" % 'a'(15) 459
10,2030(12,13,21) 459 %% 4501234561020013034567801
!"⊑: Picking item at wrong rank (index 1‿1‿1 in array of shape 10‿10)" % 1¨(111) 10101
!"⊑: Picking item at wrong rank (index ⟨1⟩ in array of shape 10‿10)" % 1¨(1) 10101
a1010101000 ! a a((a)) a
{𝕊: a(1+•rand.Range 200)•rand.Range 2 i•rand.Rangea ! a (ia)(i) 2(i) a}¨10000
100+(5) 44 %% (100×5=16) + 44
100+(¯5) 44 %% (100×11=16) + 44
100+ 44 %% (100×161) + 44
1+(¯2) 4 %% 0133
1+(¯2) 0.5+4 %% 0.51.53.53.5
# !% ⊢⌾⊑ 4 # TODO enable
# !% ⊢⌾(⊑⊑) 4 # TODO enable
# ⊏
n500 an i(-n)+2×n r(2×n)a ! (a) r(i) a
!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (¯11∊a, ⟨10⟩≡≢𝕩)" % 12(5¯11) 10
!"𝔽⌾(a⊸⊏)𝕩: Indexing out-of-bounds (10∊a, ⟨10⟩≡≢𝕩)" % 12(910) 10
100+(124) <¨10 %% <¨ 0101102310456789
100+(124) <¨10 %% <¨ 0101102310456789
100+(124) 10 %% 0101102310456789
100+¨(124) 10 %% 0101102310456789
100+(12¯4) <¨10 %% <¨ 0101102345106789
100+(12¯4) 10 %% 0101102345106789
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 34(11) 10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 34(1¯9) 10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 345(112) 10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 345(112) <¨10
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 345(112) a<¨10 •internal.Keep a
!"𝔽⌾(a⊸⊏): Incompatible result elements" % 34(("Ah"•internal.Variation 11)) <¨10
2020(11) 10 %% 0202+8
100+(12¯1) 5 %% 01011023104
100+(12¯1) <¨5 %% <¨ 01011023104
1+(((10010)10/10)) 10 %% 1+10
# ⥊
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (16 ≡ ≢⥊𝕩, ⟨17⟩ ≡ shape of result of 𝔽)" % 1 4416
1+ 5 %% (<6)
1+ <5 %% (<6)
1+ 5 %% (6)
1+ 2 %% 12
1+ 236 %% (1+236)
236 %% (236)
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨2⟩ ≡ shape of result of 𝔽)" % 1 4
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨2⟩ ≡ shape of result of 𝔽)" % 1 <4
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨2⟩ ≡ shape of result of 𝔽)" % 1 4
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (2 ≡ ≢⥊𝕩, ⟨3⟩ ≡ shape of result of 𝔽)" % 1 12
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (6 ≡ ≢⥊𝕩, ⟨7⟩ ≡ shape of result of 𝔽)" % 1 236
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨⟩ ≡ shape of result of 𝔽)" % 4
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨⟩ ≡ shape of result of 𝔽)" % <4
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (1 ≡ ≢⥊𝕩, ⟨⟩ ≡ shape of result of 𝔽)" % 4
!"𝔽⌾⥊: 𝔽 must return an array with the same shape as its input (2 ≡ ≢⥊𝕩, 2‿1 ≡ shape of result of 𝔽)" % 21 12
# !% ⊢⌾⥊ 4 # TODO enable
# !% ⊢⌾(3⥊⊢) 4 # TODO enable
# /
!"/: Lengths of components of 𝕨 must match 𝕩 (3 ≠ 10)" % 1(101/) 10
10+(1,01/)22 %% 2200,1011,10,1111
!"𝔽⌾(a⊸/): Incompatible result elements" % 12(20/)2
1+((10)/) 10 %% ×+ 10
# ↓ & ↑
!"𝔽⌾(n⊸↑)𝕩: 𝔽 must return an array with the same shape as its input (2 ≡ n, ⟨1⟩ ≡ shape of result of 𝔽)" % 1(2) 4
!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (2 ≡ n, ⟨1⟩ ≡ shape of result of 𝔽)" % 1(2) 4
!"𝔽⌾(n⊸↑)𝕩: 𝔽 must return an array with the same shape as its input (¯2 ≡ n, ⟨3⟩ ≡ shape of result of 𝔽)" % 1(¯2) 4
!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (¯2 ≡ n, ⟨3⟩ ≡ shape of result of 𝔽)" % 1(¯2) 4
!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (5 ≡ n, ⟨1⟩ ≡ shape of result of 𝔽)" % 1(5) 4
!"𝔽⌾(n⊸↓)𝕩: 𝔽 must return an array with the same shape as its input (1 ≡ n, 4‿5‿2 ≡ shape of result of 𝔽)" % (1) 34560
!"𝔽⌾(n⊸↑)𝕩: 𝔽 must return an array with the same shape as its input (¯2 ≡ n, 4‿5‿2 ≡ shape of result of 𝔽)" % (¯2) 34560
!"𝔽⌾(n⊸↑)𝕩: Cannot modify fill with Under (5 ≡ n, ⟨4⟩ ≡ ≢𝕩)" % (5) 4
(4) 4 %% 4
(5) 4 %% 4
•internal.Keep(¯5) 4 %% 4
{!(a×1+9× 012𝕩+3) 10×(𝕩) a34560}¨ ¯5+10
{!(a×1+9׬012𝕩+3) 10×(𝕩) a34560}¨ ¯3+7

200
test/run.bqn Normal file
View File

@ -0,0 +1,200 @@
NextIdx {i/𝕩 (i𝕩)˜i𝕨} # for each index 𝕨, find the index of the next 1 in mask 𝕩
UM {(𝕨)/𝕩}
Fail {•Out 𝕩 •Exit 1}
Trim {((``)𝕩' ')/𝕩}
{ 𝕊:
•Out "Usage: test/run.bqn [options | files]"
•Out "Options:"
•Out " lint Check that every test either is expected to return a specific value, error, or contains a '!'"
•Out " slow Enable slow tests"
•Out " noerr Disable erroring tests (ones expected to, or which contain ⎊)"
•Out " heapverify Disable tests that aren't runnable in heapverify"
•Out " debug Disable tests that aren't runnable in debug"
•Out " update-messages Auto-update error messages in tests"
•Out " ignore-messages Don't warn about incorrect error messages"
•Out " bin-search Binary search for some property. Next argument should be /[01]*/, with a 1 appended every time the property is matched, and a 0 otherwise"
•Out "Files:"
•Out " General:"
•Out " prims cells syntax system fills hash patterns under"
•Out " More special:"
•Out " fuzz perf"
•Out " For specific configurations:"
•Out " test_range // -DTEST_RANGE"
•Out "Lint all: test/run.bqn lint prims cells syntax system fills hash patterns under fuzz perf test_range"
•Exit 0
} (0=•args) ´ "help""h""?"'-'/¨•args
o {
args •args
search @
{
n»𝕩
search '0'-˜(n/args)<""
! ´search01
search search1
args (¬n𝕩)/args
}(´) "bin-search"¨ args
named "run""lint""update-messages""slow""ignore-messages""noerr""heapverify""debug"
i namedargs
run ´i=0
lint ´i=1
update ´i=2
slow ´i=3
errm ¬´i=4
noerr ´i=5
heapverify ´i=6
debug ´i=7
noerr heapverify
files (i=named)/args
run update ¬´lintupdate
}
searchRefine {
searchI 0
{
o.search@? 𝕩;
searchIo.search? 𝕩;
1𝕩? 𝕩;
SearchRefine (2÷˜𝕩) ((searchI+1) searchIo.search) 𝕩
}
}
exitCode 0
Run { 𝕊 testname:
lns •FLines fullfile "cases"•file.At filename testname".bqn"
defkdefv
i 0
Pos {filename, ":", •Repr 1+𝕩}
Next {𝕊: (i+1) ilns}
Process {
"%DEF "5𝕩?
defkdefv¨<¨ {(Process 1𝕩).str}(1) ' '() 5𝕩
@
;
"":@
;
'#'𝕩? @
;
"("𝕩?
Process (@+10)¨ ¯1 <Next•_while_{")"¯1𝕩} Next@
;
# insert defs
si /(𝕩)"%USE"𝕩
mi si+5
ei mi NextIdx ¬𝕩'_'"0aA"+¨102626
g (+`+´ 𝕩UM¨ simiei) 𝕩
pre g
[·,uk,post] 31g
{Fail (Pos i)": Unknown def "𝕩uk} /¬ukdefk
str pre ((defkuk)defv) ¨ post
Flag {
m (str) 𝕩str
str /˜ ¬ »(¯1+𝕩) m
´m
}
{lni-1 fast¬Flag"%SLOW" debug¬Flag"%NDEBUG" heapverify¬Flag"%NHEAPVERIFY" strstr}
}
tests SearchRefine @¨/ <(ProcessNext)•_while_{𝕊: ilns}
{𝕊: •Out "Narrowed down to test "Pos (tests).ln} (o.search@)1=tests
tests { 𝕊ns: ln,strns
idx str'%'
{
idx str? ns, "eval", str;
(i2idx+1)<str? '%'i2str? ns, "equal", idxstr, (2+idx)str;
{𝕊: Fail (Pos ln)": Unknown test format"} '!'str
ns, "error", (idx+1)str, 1idxstr
}
}¨
{ 𝕊 d:
ln(d).ln
ty1d
Lint {𝕊: •Out "Lint: ", Pos ln, ": ", 𝕨}(¬)
{
"eval"ty? "No check or assert" Lint ´'!'=2d;
@
}
}¨o.lint tests
{ 𝕊:
badCount 0
badMessage 0
currLn 0
skipped 0
dir •file.At "testDir"
•file.CreateDir(¬•file.Exists) dir
Bad {
""𝕊𝕩;
•Out Pos currLn, ": ", 𝕩
•Out¨ " "¨ 𝕨
badCount+ 1
}
ErrMsg {𝕊: m•CurrentError@ {1==m? ´2=•Type¨m? m; •Repr"(unrepresentable)" m}}
Eval {dir, testname,"_line_",•Repr currLn+1,".bqn", "arg0",1 •BQN 𝕩}
EvalS •BQN{𝕊: Bad "Bad comparison value" "(bad)"}
toRun tests
toRun {{𝕩.fast }¨/𝕩}(¬o.slow)
toRun {{𝕩.debug }¨/𝕩}o.debug
toRun {{𝕩.heapverify}¨/𝕩}o.heapverify
skipped+ (tests)-toRun
results {
"eval"str: {
o.noerr? '⎊'str? skipped+1;
Eval{𝕊: Bad "Expected success, got error: "ErrMsg@} str
@
};
"error"strexp: {
o.noerr? skipped+1;
okgot (1Eval)(0ErrMsg) str
exp EvalS{×Trim𝕩} exp
{
(gotexp) ¬ok? @;
ok? Bad "Expected error, but didn't get one" @;
"Expected: "exp "Got: "got Bado.errm "Wrong error message"
badMessage+ 1
got
}
};
"equal"strexp: {
o.noerr? '⎊'str? skipped+1;
okgot (1Eval)(0ErrMsg) str
exp EvalS exp
{
¬ok? Bad "Expected value, but got error: "got;
got •internal.EEqual exp? @;
"Expected: "•Repr exp "Got: "•Repr got Bad "Wrong value"
@
}
@
}
}{currLn(𝕩).ln 1𝕩}¨ toRun
{𝕊:
resdesc ({@𝕩? 0; ¬(@+10)𝕩}¨ results)/¨ resultstoRun
0res?
•Out "Update ", •Reprres, " entr", (1<res)"y""ies", " in ", filename, "?"
{
¬"yY"˜'n'˜•GetLine@? •Out "Not updating.";
[idxs, upd] >res {new𝕊ln, "error", str, ·: ln "!", •Repr new, " %", str}¨ desc
"Refusing to write over changed file" ! lns •FLines fullfile
fullfile •FLines lns {×𝕩? 𝕩; 𝕨}¨ (lns)idxsupd
•Out "Updated."
}
;@
} o.update
skipm (×skipped)/" (", •Repr skipped, " skipped)"
{
0=badCount? •Out filename": "(•ReprtoRun)" passed!"skipm;
•Out •Repr (toRun)-badCount, '/', •ReprtoRun ((¬o.errm)×badMessage)/"; ", •Repr badMessage, " mismatched error message", (1badMessage)/"s"skipm
exitCode 1
}
}o.run @
}
Run¨ SearchRefine o.files
•Exit(0)(¬o.heapverify) exitCode