diff options
author | dzaima <dzaimagit@gmail.com> | 2023-04-24 15:25:44 +0300 |
---|---|---|
committer | dzaima <dzaimagit@gmail.com> | 2023-04-24 19:43:04 +0300 |
commit | 77154be2a883b0c33f141d6b4b29330db900d8a4 (patch) | |
tree | ac4efd7673a4c964b7f4454f9ee3c45cf9669427 | |
parent | 6d33018788661f628979a4ab057f6e1fac90fa49 (diff) |
testing setup for ˘ & ⎉
incl. toggleable fill testing for !CATCH_ERRORS
-rw-r--r-- | src/builtins/cells.c | 32 | ||||
-rw-r--r-- | src/builtins/internal.c | 15 | ||||
-rw-r--r-- | test/cells.bqn | 200 | ||||
-rw-r--r-- | test/generated/.gitignore | 2 |
4 files changed, 238 insertions, 11 deletions
diff --git a/src/builtins/cells.c b/src/builtins/cells.c index 257226c3..fa086e79 100644 --- a/src/builtins/cells.c +++ b/src/builtins/cells.c @@ -57,6 +57,19 @@ B insert_base(B f, B x, usz xia, bool has_w, B w) { return r; } + +#if TEST_CELL_FILLS + i32 fullCellFills = 2*CATCH_ERRORS; + i32 cellFillErrored = 0; + #define DO_CELL_CATCH (fullCellFills==2) + #define getFillQ2 (fullCellFills? getFillR : getFillQ) + #define SET_FILL_ERRORED cellFillErrored = 1 +#else + #define DO_CELL_CATCH CATCH_ERRORS + #define getFillQ2 getFillQ + #define SET_FILL_ERRORED +#endif + static NOINLINE B empty_frame(usz* xsh, ur k) { if (k==1) return emptyHVec(); assert(k>1); @@ -219,7 +232,7 @@ static NOINLINE B transp_cells(ur ax, ur k, B x) { // helpers static NOINLINE B to_fill_cell(B x, ur k, u32 chr) { // consumes x - B xf = getFillQ(x); + B xf = getFillQ2(x); if (noFill(xf)) xf = m_f64(0); ur cr = RNK(x)-k; usz* sh = SH(x)+k; @@ -237,7 +250,7 @@ static NOINLINE B to_fill_cell(B x, ur k, u32 chr) { // consumes x static NOINLINE B merge_fill_result(B rc, ur k, usz* sh, u32 chr) { u64 rr = k; if (isArr(rc)) rr+= RNK(rc); if (rr>UR_MAX) thrF("%c: Result rank too large", chr); - Arr* r = m_fillarrpEmpty(getFillQ(rc)); + Arr* r = m_fillarrpEmpty(getFillQ2(rc)); usz* rsh = arr_shAlloc(r, rr); if (rr>1) { shcpy(rsh, sh, k); @@ -265,7 +278,6 @@ static ur cell_rank(f64 r, f64 k) { // ⎉k over arg rank r - static NOINLINE B c1wrap(B f, B x) { B r = c1(f, x); return isAtm(r)? m_atomUnit(r) : r; } static NOINLINE B c2wrap(B f, B w, B x) { B r = c2(f, w, x); return isAtm(r)? m_atomUnit(r) : r; } // monadic ˘ & ⎉ @@ -355,11 +367,13 @@ B for_cells_c1(B f, u32 xr, u32 cr, u32 k, B x, u32 chr) { // F⎉cr x, with arr noCells:; usz s0=0; ShArr* s=NULL; if (xr<=1) { s0=xsh[0]; xsh=&s0; } else { s=ptr_inc(shObj(x)); } - if (!isPureFn(f) || !CATCH_ERRORS) { decG(x); goto empty; } + if (!DO_CELL_CATCH || !isPureFn(f)) { decG(x); goto empty; } B cf = to_fill_cell(x, k, chr); B r; - if (CATCH) { empty: + if (CATCH) { + SET_FILL_ERRORED; freeThrown(); + empty: r = empty_frame(xsh, k); } else { B rc = c1(f, cf); @@ -406,18 +420,20 @@ B rank_c1(Md2D* d, B x) { B f = d->f; B g = d->g; } -static NOINLINE B rank2_empty(B f, B w, ur wk, B x, ur xk) { +static NOINLINE B rank2_empty(B f, B w, ur wk, B x, ur xk) { // TODO pass chr around everywhere B fa = wk>xk?w:x; ur k = wk>xk?wk:xk; usz* sh = SH(fa); usz s0=0; ShArr* s=NULL; ur sho=RNK(fa)>1; if (!sho) { s0=sh[0]; sh=&s0; } else { s=ptr_inc(shObj(fa)); } - if (!isPureFn(f) || !CATCH_ERRORS) { dec(w); dec(x); goto empty; } + if (!DO_CELL_CATCH || !isPureFn(f)) { dec(w); dec(x); goto empty; } B r; if (wk) w = to_fill_cell(w, wk, U'⎉'); if (xk) x = to_fill_cell(x, xk, U'⎉'); - if (CATCH) { empty: + if (CATCH) { + SET_FILL_ERRORED; freeThrown(); + empty: r = empty_frame(sh, k); } else { B rc = c2(f, w, x); diff --git a/src/builtins/internal.c b/src/builtins/internal.c index f6828fcd..26a05cd0 100644 --- a/src/builtins/internal.c +++ b/src/builtins/internal.c @@ -276,8 +276,17 @@ B eequal_c2(B t, B w, B x) { extern B native_comp; void switchComp(void); #endif +#if TEST_CELL_FILLS + extern i32 fullCellFills; + extern i32 cellFillErrored; +#endif B internalTemp_c1(B t, B x) { - + #if TEST_CELL_FILLS + if (isNum(x)) fullCellFills = o2iG(x); + B r = m_i32(cellFillErrored); + cellFillErrored = 0; + return r; + #endif #if NATIVE_COMPILER switchComp(); B r = bqn_exec(x, bi_N, bi_N); @@ -285,8 +294,8 @@ B internalTemp_c1(B t, B x) { return r; #endif #ifdef TEST_BITCPY - SGetU(x) - bit_cpyN(bitarr_ptr(GetU(x,0)), o2s(GetU(x,1)), bitarr_ptr(GetU(x,2)), o2s(GetU(x,3)), o2s(GetU(x,4))); + SGetU(x) + bit_cpyN(bitarr_ptr(GetU(x,0)), o2s(GetU(x,1)), bitarr_ptr(GetU(x,2)), o2s(GetU(x,3)), o2s(GetU(x,4))); #endif return x; } diff --git a/test/cells.bqn b/test/cells.bqn new file mode 100644 index 00000000..23ae1e8f --- /dev/null +++ b/test/cells.bqn @@ -0,0 +1,200 @@ +# build/build replxx singeli native g debug f=-DEACH_FILLS f=-DTEST_CELL_FILLS && build/build replxx singeli native g debug heapverify f=-DTEST_CELL_FILLS OUTPUT=BQNh && ./BQN test/cells.bqn path/to/mlochbaum/BQN/bqn.js ./BQNh +# (replace bqn.js path with "reuse" to use the previous result (requires the test set to not have changed)) +{𝕊: •Out "Usage: ./nonHeapverifyCBQN test/cells.bqn path/to/bqn.js heapverifyCBQN" ⋄ •Exit 0}⍟⊢ 2>≠•args +a0 ← ⊑•args +bqnjs‿hCBQN ← •wdpath⊸•file.At¨ •args +bqnjsFile ← •file.At "generated/cells_bqnjsOut.bqn" +hCBQNFile ← •file.At "generated/cells_hCBQNOut.bqn" +validFile ← •file.At "generated/cells_valid.bqn" + +cbqni ← {⊑"internal"<⊸∊•listsys? •BQN"•internal"; @} +bqntype ← {cbqni≡@? 2; "harr"≡cbqni.Type ⊢⎉0 ""} # 0: full CBQN; 1: heapverify CBQN; 2: bqn.js + +SHRun ← { + f←•BQN"•SH" + c‿o‿e ← F 𝕩 + g←•BQN"•term.OutRaw‿•term.ErrRaw {𝕎•ToUTF8𝕩}¨ ⊢" ⋄ G o‿e + c≢0? •Exit c; @ +} + +GetTests ← { 𝕊: + + tests ← ⟨⟩ + AddTests ← {tests∾↩ 𝕩 ⋄ @} + + Prod ← {⥊ (<⟨⟩) <⊸∾⌜´ 𝕩} + + # generating random numerical arrays: + # )r N←{⟨⟩:"1";•Repr⊑⍟(1=≠)𝕩} ⋄ J←{(⊣∾𝕨∾⊢)´𝕩} ⋄ •Out '⟨'∾'⟩'∾˜','J ("⥊"J≢⋈○N⥊)¨ 15↑ ⍷ {𝕊: ((1+•rand.Range 4)•rand.Range 4)•rand.Range 10}¨ ↕100 + # xs ↩ ⟨0,↕0⟩ ∾ + + { 𝕊: # F⎉k x + fs ← ⟨<,⊏,⊑,≍,⥊,«,»,⍉,×˝,¨,1˙,∞,'a'˙,'𝕨',"ab"‿2˙,⟨⟩,<"ab"‿1,2‿3,↕2‿3‿1⟩ + xs ← ⟨ + 1, <2, + 2‿3, 2‿3‿4⥊↕24, 1‿1‿1‿1⥊4, + ↕0, 0‿2⥊"", 4‿0⥊0, 0‿2‿3‿4‿5⥊0, + 1‿1‿2‿1⥊2‿'a', 2‿2⥊"abcd", ↕2‿3, + ⟩ + ks ← ⟨@, ¯∞, ¯1, 0‿∞‿∞, 10‿1, ⟨2⟩, 3, 4, 5, ∞⟩ + AddTests Prod ⟨fs, ks, xs⟩ + }⍟⊢ 1 + + { 𝕊: # w ⋈⎉k x + xs ← ⟨0, 2‿2⥊"a"‿1⟩∾ {𝕩⥊↕×´⥊𝕩}¨ ⟨1, 2‿3, 2‿0, 2‿3‿4, 2‿2‿3‿4, 3‿4⟩ + ks ← ⟨¯∞, ¯1, 0, 1, 2, 3, 4, ∞‿0‿1, ¯∞‿2‿1, ∞, 0‿∞, ∞‿0, 1‿∞, ∞‿1, 2‿∞, ∞‿2⟩ + AddTests Prod ⟨xs, ⋈, ks, xs⟩ + }⍟⊢ 1 + + { 𝕊: # w ⊏⎉k x / w ⊑⎉k x + ws ← ⟨0, 1, 2, 3, ¯1, ¯2, <1⟩ + xs ← ⟨2‿2⥊"a"‿1‿"b"‿"cd", 3‿3‿3⥊'a'+↕27, 3‿6⟩∾ {𝕩⥊↕×´⥊𝕩}¨ ⟨2‿3, 2‿0, 2‿3‿4, 2‿2‿3‿4, 3‿4⟩ + ks ← ⟨0, 1, 2, 3, 4, 0‿1, 0‿2⟩ + AddTests Prod ⟨ws, ⊏‿⊑, ks, xs⟩ + AddTests Prod ⟨0‿100‿¯100‿∞, ⊏‿⊑, 0‿1‿2, xs∾⟨0,<4⟩⟩ + }⍟⊢ 1 + + { 𝕊: # w ≡⎉k x + xs ← ⟨0, 2‿3⥊@+↕6⟩∾ {𝕩⥊↕×´⥊𝕩}¨ ⟨1, 2‿3, 0‿3, 2‿0‿3, 4‿2‿3, 2‿4‿2‿3, 3‿1⟩ + ks ← ⟨¯∞, ¯1, 0, 1, 2, 3, 4, 0‿1, 2‿1⟩ + AddTests Prod ⟨xs, ≡, ks, xs⟩ + xs2 ← ⟨2‿3⥊175, [¯81‿¯81‿¯81, 0‿0‿0]⟩∾{𝕩-˜𝕩+2‿3⥊'¯'}¨ 0‿100‿100000 + AddTests Prod ⟨xs2, ≡, ks, xs2⟩ + }⍟⊢ 1 + + { 𝕊: # w ⍉⎉k x + ws ← ⟨0, 1, 2, 3, 4, ¯1, 1‿0⟩ + xs ← ⟨2‿2‿2⥊"a"‿1‿"b", 3‿3‿3⥊'a'+↕27, 3‿6⟩∾ {𝕩⥊↕×´⥊𝕩}¨ ⟨2‿3, 2‿0, 2‿3‿4, 2‿2‿3‿4, 3‿4, 3‿2‿1‿2‿2⟩ + ks ← ⟨0, 1, 2, 3, 4, 5, 0‿1, 0‿2⟩ + AddTests Prod ⟨ws, ⍉, ks, xs⟩ + }⍟⊢ 1 + + { 𝕊: # w »⎉k x / w «⎉k x + ws ← ⟨0, 1, 'a', "ab", <"h"‿2⟩ + xs ← ⟨2‿2‿2⥊"a"‿1‿"b", 3‿3‿3⥊'a'+↕27, 3‿6⟩∾ {𝕩⥊↕×´⥊𝕩}¨ ⟨2‿3, 2‿0, 2‿3‿4, 2‿2‿3‿4, 3‿4, 3‿2‿1‿2‿2⟩ + ks ← ⟨0, 1, 2, 3, 4, @, 0‿1, 0‿2⟩ + AddTests Prod ⟨ws, «‿», ks, xs⟩ + }⍟⊢ 1 + + { 𝕊: # w ↑⎉k x / w ↓⎉k x + ws ← ⟨0,1,2,¯1,¯2,10,1‿1⟩ + xs ← ⟨2‿2‿2⥊"a"‿1‿"b", 3‿3‿3⥊'a'+↕27, 3‿6⟩∾ {𝕩⥊↕×´⥊𝕩}¨ ⟨2‿3, 0‿2, 2‿0, 2‿3‿4, 2‿2‿3‿4, 3‿4, 3‿2‿1‿2‿2⟩ + ks ← ⟨0, 1, 2, 3, 4, @, 0‿1, 0‿2, 1‿¯1⟩ + AddTests Prod ⟨ws, ↑‿↓, ks, xs⟩ + }⍟⊢ 1 + + tests +} + +getFill ← {bqntype≢2? cbqni•ns.Has"hasfill"? {cbqni.HasFill 𝕩? ⊑1↑0⥊𝕩; '!'}; {1 ⊑∘↑⎊'!' 0⥊𝕩}} +Info ← {⟨𝕩, GetFill 𝕩⟩} +RunTests ← { + f‿k‿x: (Info F{k≡@? 𝔽˘; 𝔽⎉k})⎊"err" x; + w‿f‿k‿x: w (Info F{k≡@? 𝔽˘; 𝔽⎉k})⎊"err" x +}¨ + + +{ + "0"≡a0? # bqn.js + •Out⍟(bqntype≠2) "Warning: doesn't seem like the first argument is bqn.js!" + res ← RunTests GetTests@ + bqnjsFile •FChars •Repr res + ; + "1"≡a0? # heapverify + •Out⍟(bqntype≠1) "Warning: doesn't seem like the second argument is CBQN with heapverify!" + tests ← GetTests@ + valid ← '0'-˜•FChars validFile + ok ← valid≠2 + HTests ← { 𝕊: + okTests ← ok/tests + hasFill ← 0=ok/valid + cbqni.Temp 2 ⋄ f1 ← RunTests okTests /˜ hasFill + cbqni.Temp 1 ⋄ f0 ← RunTests okTests /˜ ¬hasFill + cbqni.Temp 0 + (⍋⍋hasFill) ⊏ f0∾f1 + } + hCBQNFile •FChars •Repr HTests⌾(ok⊸/) "err"¨ tests + ; + # base + •Out⍟(bqntype≠0) "Warning: doesn't seem like the running binary is CBQN without heapverify!" + + tests ← GetTests@ + •Out ∾⟨"Running ", •Repr ≠tests, " tests on base CBQN.."⟩ + cfe‿fo ← <˘⍉>{cbqni.Temp@ ⋄ (cbqni.Temp@) ⋈ ⊑RunTests ⋈𝕩}¨ tests + validFile •FChars '0'+ 2⌊ cfe + 2×"err"⊸≡¨ fo # 2: errored; 1: invalid fill; 0: valid fill + + { 𝕊: + •Out "Calling bqn.js.." + •file.Remove⍟•file.Exists bqnjsFile + SHRun ⟨bqnjs, •file.At "cells.bqn", "0", ""⟩ + {•file.Exists bqnjsFile?@; •Out "bqn.js didn't produce the result file!" ⋄ •Exit 1} + }⍟⊢ "reuse"≢a0 + + •file.Remove⍟•file.Exists hCBQNFile + •Out "Calling heapverify build.." + SHRun ⟨hCBQN, •file.At "cells.bqn", "1", ""⟩ + + •Out "Comparing.." + bo ← •Import bqnjsFile + ho ← •Import hCBQNFile + + hCount ← +´ "err"⊸≢¨ bo + badH←0 ⋄ hBadFill←0 ⋄ hSuperset←0 + badB←0 ⋄ bBadFill←0 ⋄ bSuperset←0 + + hBadEmpty←0 + hBadButBase←0 + + FRepr ← {0≢≠⥊𝕩? •Repr 𝕩; '!'≢f←GetFill 𝕩? ∾⟨•Repr≢𝕩, "⥊", "<"⊸∾⍟(0≠≡f) •Repr f⟩; •Repr 𝕩} + FTest ← { test‿exp‿got: + ! exp≢got + ∾⟨ + {F‿k‿x←¯3↑𝕩 ⋄ ∾⟨{3≡≠𝕩?""; "("∾") "∾˜FRepr⊑𝕩}𝕩 , •Repr f, {k≡@?"˘";"⎉"∾•Repr k}, " ", FRepr x⟩} test + ": " + { + exp≡"err"? "expected error, but got "∾•Repr ⊑got; + got≡"err"? "expected result, but got error"; + {𝕨∾"; "∾𝕩}´ @⊸≢¨⊸/ "result"‿"result fill" {m𝕊e‿g: {e≡g? @; ∾⟨"expected ",m," to be ",FRepr e,", got ",FRepr g⟩}}¨ <˘⍉>⟨exp,got⟩ + } + ⟩ + } + + { 𝕊 t‿f‿b‿h: + { + b≡f?@; + b≢○⊑f? badB+↩1 ⋄ •Out ∾⟨"base: incrorrect result: ",FTest t‿b‿f⟩; + '!'≡1⊑b? bSuperset+↩1; + bBadFill+↩1 ⋄ •Out ∾⟨"base: bad fill: ",FTest t‿b‿f⟩ + } + { + b≡h?@; {∨´0=≠∘⥊¨ (¯3↓t)∾¯1↑t? hBadEmpty+↩1;@} + f≡h? hBadButBase+↩1; + b≢○⊑h? badH+↩1 ⋄ •Out ∾⟨"heapverify: incrorrect result: ",FTest t‿b‿h⟩; + '!'≡1⊑b? hSuperset+↩1; + hBadFill+↩ 1 ⋄ •Out ∾⟨"heapverify: bad fill: ",FTest t‿b‿h⟩ + + # ∨´0=≠∘⥊¨ (¯3↓t)∾¯1↑t? hBadEmpty+↩1; + # badH+↩1 ⋄ •Out ∾⟨"heapverify: incrorrect result: ",FTest t‿b‿h⟩ + } + }¨ <˘⍉>⟨tests, fo, bo, ho⟩ + + •Out ∾⟨ + "Base: ", + •Repr ≠tests, " tests: " + •Repr badB, " wrong results, " + •Repr bBadFill, " wrong fills, " + •Repr bSuperset, " superset fills" + ⟩ + hBadTot ← hBadFill + •Out ∾⟨ + "Heapverify: " + •Repr hCount, " tests: " + •Repr hBadButBase, " wrong results equal to base, " + •Repr badH, " wrong results, " + •Repr hBadFill, " wrong fills, " + •Repr hSuperset, " superset fills; " + •Repr hBadEmpty, " wrong results had empty input(s)" + ⟩ + •Exit⍟(∨´0≠badH‿badB) 1 + •Out "Passed!" +} diff --git a/test/generated/.gitignore b/test/generated/.gitignore new file mode 100644 index 00000000..c96a04f0 --- /dev/null +++ b/test/generated/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore
\ No newline at end of file |