@flemist/test-variants 5.0.1 → 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +0,0 @@
1
- "use strict";const Y=require("@flemist/time-controller"),k=require("@flemist/simple-utils"),S=require("@flemist/async-utils"),z=require("@flemist/abort-controller-fast"),H=require("@flemist/time-limits");function ee(){if(typeof process<"u"&&process.memoryUsage)try{return process.memoryUsage().heapUsed}catch{}if(typeof performance<"u"){const e=performance.memory;if(e)try{return e.usedJSHeapSize}catch{}}return null}const Fe=1e3,_=[];function je(e){return k.formatAny(e,{pretty:!0,maxDepth:5,maxItems:50})}function We(...e){const n=e.map(r=>typeof r=="string"?r:je(r)).join(" ");_.push(n),_.length>Fe&&_.shift(),console.log(n)}function ze(){return _.join(`
2
- `)}globalThis.__getStressTestLogLast=ze;const ce=(e,n)=>{We(n)},E={start:!0,progress:5e3,completed:!0,error:!0,modeChange:!0,debug:!1,func:ce},He={start:!1,progress:!1,completed:!1,error:!1,modeChange:!1,debug:!1,func:ce};function fe(e){return e===!1?He:e===!0||!e?E:{start:e.start??E.start,progress:e.progress??E.progress,completed:e.completed??E.completed,error:e.error??E.error,modeChange:e.modeChange??E.modeChange,debug:e.debug??E.debug,func:e.func??E.func}}function Je(e,n){const r=e.now();return{startTime:r,startMemory:n,debugMode:!1,tests:0,iterations:0,iterationsAsync:0,prevLogTime:r,prevLogMemory:n,pendingModeChange:null,prevGcTime:r,prevGcIterations:0,prevGcIterationsAsync:0}}class T extends z.AbortError{}const Xe=50,Ze=5;function se(e,n){return typeof e=="number"?{iterationsAsync:0,iterationsSync:e}:e!=null&&typeof e=="object"?e:n?{iterationsAsync:1,iterationsSync:0}:{iterationsAsync:0,iterationsSync:1}}function Ke(e,n){const r=n.log;let o=null,i=0;function a(t,l,u){o==null&&(o={error:t,args:l,tests:u},r.error&&r.func("error",`[test-variants] error variant: ${k.formatAny(l,{pretty:!0})}
3
- tests: ${u}
4
- ${k.formatAny(t)}`));const d=Date.now();if(Date.now()-d>Xe&&i<Ze){r.func("debug",`[test-variants] debug iteration: ${i}`),i++;return}const h=o;throw o=null,n.onError&&n.onError(h),h.error}return function(l,u,d){try{const f=e(l,d);return S.isPromiseLike(f)?f.then(h=>se(h,!0),h=>a(h,l,u)):se(f,!1)}catch(f){return f instanceof T?void 0:a(f,l,u)}}}function U(e,n,r){for(let o=0,i=e.length;o<i;o++)if(r?r(e[o],n):e[o]===n)return o;return-1}function le(e,n,r,o){const i=Object.keys(e.templates),a={},t=[],l=[],u=[],d=i.length;for(let f=0;f<d;f++){const h=i[f];a[h]=void 0,t.push(-1),l.push(void 0),u.push(null)}return{args:a,argsNames:i,indexes:t,argValues:l,argLimits:u,attempts:0,templates:e,limitArgOnError:r,equals:n,includeErrorVariant:o??!1}}function C(e,n){const r=e.templates.templates[n],o=e.templates.extra[n];let i;if(typeof r=="function"?i=r(e.args):i=r,o==null)return i;let a=null;const t=o.length;for(let l=0;l<t;l++){const u=o[l];U(i,u,e.equals)<0&&(a==null?a=[...i,u]:a.push(u))}return a??i}function M(e,n,r){const o=e.argValues[n].length;if(o===0)return-1;const i=e.argLimits[n];if(i==null)return o-1;let a=e.limitArgOnError;if(typeof a=="function"){const t=e.argsNames[n];a=a({name:t,values:e.argValues[n],maxValueIndex:i})}return!r||a?Math.min(i,o-1):o-1}function P(e){const n=e.indexes.length;for(let r=0;r<n;r++){const o=e.argLimits[r];if(o==null)return!1;const i=e.indexes[r];if(i>o)return!0;if(i<o)return!1}return!e.includeErrorVariant}function I(e){const n=e.indexes.length;for(let r=0;r<n;r++)e.indexes[r]=-1,e.argValues[r]=void 0,e.args[e.argsNames[r]]=void 0}function de(e){let n=!1,r=!0;const o=e.indexes.length;let i=o,a=!1,t=0;for(;t<o;t++){const l=e.argValues[t]==null;(l||a)&&(l&&(n=!0),e.argValues[t]=C(e,e.argsNames[t]));const u=M(e,t,t>i);if(u<0){r=!1,e.indexes[t]=-1;break}l&&(e.indexes[t]=0,e.args[e.argsNames[t]]=e.argValues[t][0]),(a||e.indexes[t]>u)&&(e.indexes[t]=u,e.args[e.argsNames[t]]=e.argValues[t][u],a=!0),i===o&&e.indexes[t]<u&&(i=t)}if(P(e))return I(e),!1;if(n&&r)return!0;for(t--;t>=0;t--){if(e.argValues[t]==null)continue;let l=t>i;const u=M(e,t,l),d=e.indexes[t]+1;if(d<=u){e.indexes[t]=d,e.args[e.argsNames[t]]=e.argValues[t][d],d<u&&(l=!0);for(let f=t+1;f<o;f++)e.args[e.argsNames[f]]=void 0;for(t++;t<o;t++){e.argValues[t]=C(e,e.argsNames[t]);const f=M(e,t,l);if(f<0)break;e.indexes[t]=0,e.args[e.argsNames[t]]=e.argValues[t][0],f>0&&(l=!0)}if(t>=o)return P(e)?(I(e),!1):!0}}return I(e),!1}function J(e){P(e)&&I(e);let n=!1,r=!0;const o=e.indexes.length;let i=o,a=!1,t=0;for(;t<o;t++){const l=e.argValues[t]==null;(l||a)&&(l&&(n=!0),e.argValues[t]=C(e,e.argsNames[t]));const u=M(e,t,t>i);if(u<0){r=!1,e.indexes[t]=-1;break}l&&(e.indexes[t]=u,e.args[e.argsNames[t]]=e.argValues[t][u]),(a||e.indexes[t]>u)&&(e.indexes[t]=u,e.args[e.argsNames[t]]=e.argValues[t][u],a=!0),i===o&&e.indexes[t]<u&&(i=t)}if((n||a)&&r&&!P(e))return!0;for(t--;t>=0;t--){if(e.argValues[t]==null)continue;let l=t>i;const u=M(e,t,l);let d=e.indexes[t]-1;if(d>u&&(d=u),d>=0){e.indexes[t]=d,e.args[e.argsNames[t]]=e.argValues[t][d],d<u&&(l=!0);for(let f=t+1;f<o;f++)e.args[e.argsNames[f]]=void 0;for(t++;t<o;t++){e.argValues[t]=C(e,e.argsNames[t]);const f=M(e,t,l);if(f<0)break;e.indexes[t]=f,e.args[e.argsNames[t]]=e.argValues[t][f],f>0&&(l=!0)}if(t>=o)return!0}}return I(e),!1}function Qe(e,n){I(e);const r=e.argsNames,o=r.length,i=[];let a=!1;for(let t=0;t<o;t++){const l=r[t],u=n[l];if(u===void 0)return null;e.argValues[t]=C(e,l);let d=-1;if(d=M(e,t,a),d<0)return null;const f=U(e.argValues[t],u,e.equals);if(f<0||f>d)return null;i.push(f),e.indexes[t]=f,e.args[e.argsNames[t]]=e.argValues[t][f],e.indexes[t]<d&&(a=!0)}return i}function Ye(e){const n=e.indexes.length;if(n===0)return!1;let r=!1;for(let o=0;o<n;o++){e.argValues[o]=C(e,e.argsNames[o]);const i=M(e,o,r);if(i<0)return Math.random()<.5?de(e):J(e);e.indexes[o]=Math.floor(Math.random()*(i+1)),e.args[e.argsNames[o]]=e.argValues[o][e.indexes[o]],e.indexes[o]<i&&(r=!0)}return P(e)?J(e):!0}function q(e){return e.mode==="forward"||e.mode==="backward"}function et(e,n,r,o){const i=n[r],a=e.templates[r];if(typeof a!="function"){if(U(a,i,o)>=0)return;a.push(i);return}const t=e.extra[r];if(t==null){e.extra[r]=[i];return}U(t,i,o)>=0||t.push(i)}function tt(e,n,r){for(const o in n)if(Object.prototype.hasOwnProperty.call(n,o)){if(o==="seed")continue;et(e,n,o,r)}}function rt(e,n){for(const r in n)if(Object.prototype.hasOwnProperty.call(n,r)){if(r==="seed")continue;if(!e[r])return!1}return!0}const nt=[{mode:"forward"}];function ot(e){const{argsTemplates:n,equals:r,limitArgOnError:o,includeErrorVariant:i,getSeed:a,iterationModes:t,onModeChange:l,limitCompletionCount:u,limitTests:d,limitTime:f}=e,h=e.timeController??Y.timeControllerDefault,y={templates:k.deepCloneJsonLike(n),extra:{}},p=t==null||t.length===0?nt:t,b=[];let w=null,L=null,g=0,x=0,A=!1,N=0;function ne(){A||(A=!0,N=h.now(),ye(),g=0,oe())}function ye(){for(let s=0,c=p.length;s<c;s++)b.push(ve())}function ve(){return{navigationState:le(y,r??null,o??null,i??null),cycleCount:0,completedCount:0,testsInLastTurn:0,tryNextVariantAttempts:0,startTime:null}}function oe(){l?.({mode:p[g],modeIndex:g,tests:x})}function Se(s){const c=s?.args;if(c==null||(ne(),!rt(y.templates,c)))return;s?.extendTemplates&&tt(y,c,r),w==null&&(w=le(y,r??null,!1,!1)),w.limitArgOnError=s?.limitArg??o??null;const m=Qe(w,c);if(m!=null){L={args:c,error:s?.error,tests:s?.tests??x},w.argLimits=m;for(let v=0,G=b.length;v<G;v++){const j=b[v].navigationState;j.argLimits=m}}}function we(){return ne(),xe()}function xe(){for(;;){if(!Ee())return null;for(;;){const s=Ne();if(s!=null)return b[g].testsInLastTurn++,x++,s;if(Ce()){if(!Le())return null;Pe();break}}}}function Ee(){return!(Me()||Te()||$()&&(Ae()||!Ve())||!Ie())}function Me(){return d!=null&&x>=d}function Te(){return f!=null&&h.now()-N>=f}function Ae(){if(!$())throw new Error("Unexpected behavior");return u!=null&&u<=0}function Ve(){if(!$())throw new Error("Unexpected behavior");for(let s=0,c=p.length;s<c;s++)if(V(p[s])&&R(s))return!0;return!1}function Ie(){for(let s=0,c=p.length;s<c;s++)if(R(s))return!0;return!1}function Ce(){g++;const s=g>=p.length;return s&&(g=0),oe(),s}function Le(){if($()){const s=Oe();if(u!=null&&s>=u)return!1}return!0}function $(){for(let s=0,c=p.length;s<c;s++)if(q(p[s]))return!0;return!1}function Oe(){let s=!1,c=1/0;for(let m=0,v=b.length;m<v;m++){const G=b[m],j=p[m];q(j)&&(s=!0,R(m)&&G.completedCount<c&&(c=G.completedCount))}if(!s)throw new Error("Unexpected behavior");return c}function R(s){const c=p[s],m=b[s];return c.limitTests!=null&&c.limitTests<=0||V(c)&&(c.cycles!=null&&c.cycles<=0||c.attemptsPerVariant!=null&&c.attemptsPerVariant<=0)?!1:m.tryNextVariantAttempts<2}function Pe(){g=0;for(let s=0,c=b.length;s<c;s++){const m=b[s];m.testsInLastTurn=0,m.startTime=null}}function Ne(){let s=0;for(;s<2;){if(!$e())return null;const c=Ue();if(c!=null)return c;if(V(p[g])&&ke())return null;s++}return null}function $e(){const s=p[g];return!(Ge()||qe()||V(s)&&!_e(g))}function Ge(){const s=p[g],c=b[g];return s.limitTests!=null&&c.testsInLastTurn>=s.limitTests}function qe(){const s=p[g],c=b[g];return s.limitTime!=null&&c.startTime!=null&&h.now()-c.startTime>=s.limitTime}function V(s){return q(s)}function _e(s){const c=p[s],m=b[s];if(!V(c))throw new Error("Unexpected behavior");return m.cycleCount<(c.cycles??1)}function ke(){const s=p[g],c=b[g];if(!V(s))throw new Error("Unexpected behavior");return c.cycleCount++,c.cycleCount>=(s.cycles??1)?(c.cycleCount=0,c.completedCount++,!0):!1}function Ue(){const s=p[g],c=b[g],m=c.navigationState;if(O(s)){if(F())return null;const v=De();if(v!=null)return c.startTime==null&&(c.startTime=h.now()),v}return Re()?(c.tryNextVariantAttempts=0,O(s)&&Be(),c.startTime==null&&(c.startTime=h.now()),ie(m.args)):(c.tryNextVariantAttempts++,null)}function De(){const s=p[g],m=b[g].navigationState;if(!O(s))throw new Error("Unexpected behavior");if(F())throw new Error("Unexpected behavior");const v=s.attemptsPerVariant??1;return m.attempts>0&&m.attempts<v?(m.attempts++,ie(m.args)):null}function Be(){const s=p[g],m=b[g].navigationState;if(!O(s))throw new Error("Unexpected behavior");if(F())throw new Error("Unexpected behavior");m.attempts=1}function O(s){return q(s)}function F(){const s=p[g];if(!O(s))throw new Error("Unexpected behavior");return(s.attemptsPerVariant??1)<=0}function Re(){const s=p[g],m=b[g].navigationState;switch(s.mode){case"forward":return de(m);case"backward":return J(m);case"random":return Ye(m);default:throw new Error(`Unknown mode: ${s.mode}`)}}function ie(s){const c={...s};return a!=null&&(c.seed=a({tests:x})),c}return{get limit(){return L},get modeIndex(){return g},get modeConfigs(){return p},get modeStates(){return b},get tests(){return x},addLimit:Se,next:we}}function te(e){if(e==null||e<=0)throw new Error(`Iterations = ${e}`);e--;const n=S.waitMicrotasks().then(()=>e);return e<=0?n:n.then(te)}function it(e,n,r){const o=n.limit?{error:n.limit.error,args:n.limit.args,tests:n.limit.tests}:null;if(o&&!r)throw o.error;return{iterations:e.iterations,bestError:o}}const ae=2**31;function st(e){if(e==null)return{parallel:1,sequentialOnError:!1};if(typeof e=="boolean")return{parallel:e?ae:1,sequentialOnError:!1};if(typeof e=="number")return{parallel:e>0?e:1,sequentialOnError:!1};const n=e.count;let r=1;return n===!0?r=ae:typeof n=="number"&&n>0&&(r=n),{parallel:r,sequentialOnError:e.sequentialOnError??!1}}function lt(e){const n=e?.saveErrorVariants,r=n&&e.createSaveErrorVariantsStore?e.createSaveErrorVariantsStore(n):null,o=e?.findBestError,{parallel:i,sequentialOnError:a}=st(e?.parallel);return{store:r,GC_Iterations:e?.GC_Iterations??1e6,GC_IterationsAsync:e?.GC_IterationsAsync??1e4,GC_Interval:e?.GC_Interval??1e3,logOptions:fe(e?.log),abortSignalExternal:e?.abortSignal,findBestError:o,dontThrowIfError:o?.dontThrowIfError,timeController:e?.timeController??Y.timeControllerDefault,parallel:i,sequentialOnError:a}}function D(e,n,r){const{options:o,variantsIterator:i}=e,a=i.limit?.args??n;if(!o.store)return;const t=o.store.save(a);if(r)return t}function at(e,n,r,o){const{abortControllerParallel:i,state:a,options:t}=e,{logOptions:l}=t;if(e.options.findBestError)e.variantsIterator.addLimit({args:n,error:r,tests:o}),a.debugMode=!1,D(e,n,!1),t.sequentialOnError&&!i.signal.aborted?(l.debug&&l.func("debug","[test-variants] sequentialOnError: aborting parallel, switching to sequential"),i.abort(new T)):l.debug&&l.func("debug","[test-variants] parallel error in findBestError mode, continuing with new limits");else{if(i.signal.aborted)return;D(e,n,!1),i.abort(r)}}function ue(e,n,r,o){const{state:i}=e;if(e.options.findBestError){e.variantsIterator.addLimit({args:n,error:r,tests:o});const t=D(e,n,!0);if(t)return t.then(()=>{i.debugMode=!1});i.debugMode=!1;return}const a=D(e,n,!0);if(a)return a.then(()=>{throw r});throw r}function ut(e,n){const{GC_Iterations:r,GC_IterationsAsync:o,GC_Interval:i}=e.options;return r>0&&e.state.iterations-e.state.prevGcIterations>=r||o>0&&e.state.iterationsAsync-e.state.prevGcIterationsAsync>=o||i>0&&n-e.state.prevGcTime>=i}async function ct(e,n){e.prevGcIterations=e.iterations,e.prevGcIterationsAsync=e.iterationsAsync,e.prevGcTime=n,await te(1)}function re(e){const n=e/1e3;if(n<60)return`${n.toFixed(1)}s`;const r=n/60;return r<60?`${r.toFixed(1)}m`:`${(r/60).toFixed(1)}h`}function X(e){const n=e/1073741824;if(n>=1)return n>=10?`${Math.round(n)}GB`:`${n.toFixed(1)}GB`;const r=e/(1024*1024);return r>=10?`${Math.round(r)}MB`:`${r.toFixed(1)}MB`}function ft(e,n){if(!e)return`mode[${n}]: null`;let r=`mode[${n}]: ${e.mode}`;return(e.mode==="forward"||e.mode==="backward")&&(e.cycles!=null&&(r+=`, cycles=${e.cycles}`),e.attemptsPerVariant!=null&&(r+=`, attempts=${e.attemptsPerVariant}`)),e.limitTime!=null&&(r+=`, limitTime=${re(e.limitTime)}`),e.limitTests!=null&&(r+=`, limitTests=${e.limitTests}`),r}function me(e,n){const r=e-n,o=r>=0?"+":"";return`${X(e)} (${o}${X(r)})`}function dt(e,n){if(!e.start)return;let r="[test-variants] start";n!=null&&(r+=`, memory: ${X(n)}`),e.func("start",r)}function mt(e){const{options:n,state:r}=e,{logOptions:o,timeController:i}=n;if(!o.completed)return;const a=i.now()-r.startTime;let t=`[test-variants] end, tests: ${r.tests} (${re(a)}), async: ${r.iterationsAsync}`;if(r.startMemory!=null){const l=ee();l!=null&&(t+=`, memory: ${me(l,r.startMemory)}`)}o.func("completed",t)}function ge(e){const{options:n,state:r}=e,{logOptions:o}=n,i=r.pendingModeChange;!o.modeChange||i==null||(o.func("modeChange",`[test-variants] ${ft(i.mode,i.modeIndex)}`),r.pendingModeChange=null)}function gt(e){const{options:n,state:r}=e,{logOptions:o,timeController:i}=n,a=i.now();if(!o.progress||a-r.prevLogTime<o.progress)return!1;ge(e);const t=a-r.startTime;let l=`[test-variants] tests: ${r.tests} (${re(t)}), async: ${r.iterationsAsync}`;if(r.prevLogMemory!=null){const u=ee();u!=null&&(l+=`, memory: ${me(u,r.prevLogMemory)}`,r.prevLogMemory=u)}return o.func("progress",l),r.prevLogTime=a,!0}function Z(e,n){e.debugMode=!1,n&&(e.iterationsAsync+=n.iterationsAsync,e.iterations+=n.iterationsSync+n.iterationsAsync)}function K(e){e.state.debugMode=!0,e.abortControllerParallel.abort(new T)}function pe(e,n){const{testRun:r,testOptions:o,state:i}=e,a=i.tests;i.tests++;try{const t=r(n,a,o);if(S.isPromiseLike(t))return t.then(l=>{if(!l){K(e);return}Z(i,l)},l=>ue(e,n,l,a));if(!t){K(e);return}Z(i,t)}catch(t){return t instanceof T?void 0:ue(e,n,t,a)}}function pt(e,n){const{pool:r,abortSignal:o,testRun:i,testOptionsParallel:a,state:t}=e;if(!r)return;const l=t.tests;t.tests++,(async()=>{try{if(o.aborted)return;let u=i(n,l,a);if(S.isPromiseLike(u)&&(u=await u),!u){K(e);return}Z(t,u)}catch(u){if(u instanceof T)return;at(e,n,u,l)}finally{r.release(1)}})()}function he(e){const{options:n,state:r}=e,{logOptions:o,timeController:i,GC_Interval:a}=n;if(!o.progress&&!a)return;gt(e);const t=i.now();if(ut(e,t))return ct(r,t)}function B(e){return e.options.abortSignalExternal?.aborted??!1}function Q(e){return e.abortSignal.aborted}function be(e,n){return e.state.debugMode?n:e.variantsIterator.next()}async function W(e,n){const{pool:r,state:o,options:i}=e,{parallel:a,logOptions:t}=i;let l=n??null;for(;!B(e);){const u=r&&!Q(e);let d=!1;u&&(r.hold(1)||await H.poolWait({pool:r,count:1,hold:!0}),d=!0);try{if(l==null&&(l=be(e,l),l==null))break;const f=he(e);if(S.isPromiseLike(f)&&await f,B(e)){l=null;continue}if(u)pt(e,l),d=!1;else{t.debug&&r&&Q(e)&&t.func("debug",`[test-variants] parallel aborted, running sequential: tests=${o.tests}`);const h=pe(e,l);S.isPromiseLike(h)&&await h}l=null}finally{d&&r.release(1)}}r&&(await H.poolWait({pool:r,count:a,hold:!0}),r.release(a))}function ht(e){const{pool:n,state:r,options:o}=e,{logOptions:i}=o;if(n)return W(e);let a=null;for(;!B(e)&&(a=be(e,a),a!=null);){const t=he(e);if(S.isPromiseLike(t)){const u=a;return t.then(()=>W(e,u))}if(B(e))continue;i.debug&&Q(e)&&i.func("debug",`[test-variants] parallel aborted, running sequential: tests=${r.tests}`);const l=pe(e,a);if(S.isPromiseLike(l))return l.then(()=>W(e))}}async function bt(e,n,r,o){const i=lt(o),{store:a,logOptions:t,abortSignalExternal:l,findBestError:u,dontThrowIfError:d,timeController:f,parallel:h}=i,y=new z.AbortControllerFast,p=new z.AbortControllerFast,b=S.combineAbortSignals(l,y.signal),w=S.combineAbortSignals(b,p.signal),L={abortSignal:b,timeController:f},g={abortSignal:w,timeController:f};a&&await a.replay({testRun:e,variantsIterator:n,testOptions:L,findBestErrorEnabled:!!u});const x=h<=1?null:new H.Pool(h);dt(t,r.startMemory);const A={options:i,testRun:e,variantsIterator:n,testOptions:L,testOptionsParallel:g,abortControllerGlobal:y,abortControllerParallel:p,abortSignal:w,pool:x,state:r};ge(A);try{await ht(A),w.throwIfAborted()}catch(N){throw y.abort(new T),N}return b.throwIfAborted(),y.abort(new T),mt(A),await te(1),it(r,n,d)}function yt(e){return function(r){return async function(i){const a=fe(i?.log),t=Ke(e,{onError:i?.onError,log:a}),l=i?.timeController??Y.timeControllerDefault,u=ee(),d=Je(l,u),f=i?.onModeChange;function h(p){d.pendingModeChange=p,f?.(p)}const y=ot({argsTemplates:r,getSeed:i?.getSeed,iterationModes:i?.iterationModes,equals:i?.findBestError?.equals,limitArgOnError:i?.findBestError?.limitArgOnError,includeErrorVariant:i?.findBestError?.includeErrorVariant,timeController:l,onModeChange:h,limitCompletionCount:i?.cycles??1,limitTests:i?.limitTests,limitTime:i?.limitTime});return bt(t,y,d,i)}}}exports.createTestVariants=yt;