var P=Object.defineProperty;var m=(i,e)=>P(i,"name",{value:e,configurable:!0});import I from"node:net";import _ from"node:os";import{spawn as F}from"node:child_process";import C from"node:path";import{platform as B}from"node:os";var T=class{static{m(this,"CircularBuffer")}buffer;maxSize;currentPosition;isFull;atCapacity;constructor(e,t=e/8){this.maxSize=Math.ceil(e/8)*8;let r=Math.ceil(t/8)*8;this.buffer=Buffer.alloc(r),this.currentPosition=0,this.isFull=!1,this.atCapacity=!1}grow(e){let t=Math.min(Math.pow(2,Math.ceil(Math.log2(e))),this.maxSize);t===this.maxSize&&(this.atCapacity=!0);let r=Buffer.alloc(t);r.set(this.getContent()),this.buffer=r,this.isFull=!1}clear(){this.currentPosition=0,this.isFull=!1}append(e){if(e.length>=this.maxSize){this.atCapacity||(this.buffer=Buffer.alloc(this.maxSize)),this.buffer.set(e.slice(-this.maxSize)),this.currentPosition=0,this.isFull=!0;return}if(!this.atCapacity&&this.currentPosition+e.length>this.buffer.length&&this.grow(this.currentPosition+e.length),this.currentPosition+e.length>=this.buffer.length){let t=this.buffer.length-this.currentPosition;this.buffer.set(e.subarray(0,t),this.currentPosition),this.buffer.set(e.subarray(t)),this.currentPosition=e.length-t,this.isFull=!0}else this.buffer.set(e,this.currentPosition),this.currentPosition+=e.length}getContent(){return this.isFull?Buffer.concat([this.buffer.subarray(this.currentPosition),this.buffer.subarray(0,this.currentPosition)]):this.buffer.subarray(0,this.currentPosition)}};import{dimensions as y}from"llrt:util";var A=B()==="win32",l=class i{static{m(this,"Color")}static colorizer=m((e,t=null,r=null)=>s=>`\x1B[${e||t||r}m${s}${i.RESET}`,"colorizer");static GREEN=i.colorizer(32);static RED=i.colorizer(31);static GREEN_BACKGROUND=i.colorizer(null,42);static RED_BACKGROUND=i.colorizer(null,41);static DIM=i.colorizer(null,null,2);static BOLD=i.colorizer(null,null,1);static CYAN_BOLD=i.colorizer(36,null,1);static RESET="\x1B[0m"},D=class i{static{m(this,"TestServer")}static UPDATE_FPS=15;static UPDATE_INTERVAL_MS=1e3/i.UPDATE_FPS;static DEFAULT_TIMEOUT_MS=parseInt(process.env.TEST_TIMEOUT)||5e3;static DEFAULT_PROGRESS_BAR_WIDTH=24;static SPINNER=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];static TESTING_TEXT=" Testing ";static CHECKMARK="\u2714";static CROSS="\u2718";static ERROR_CODE_SOCKET_ERROR=1;static ERROR_CODE_SOCKET_WRITE_ERROR=2;static ERROR_CODE_PROCESS_ERROR=4;static ERROR_CODE_HANDLE_DATA=8;server=null;workerCount;workerIdBySocket=new Map;testFiles;testFileNames;fileQueue;filesFailed;filesCompleted;completedWorkers=0;workerData={};workerDataFileInProgress=new Map;results=new Map;totalTests=0;totalSuccess=0;totalSkipped=0;totalFailed=0;totalOnly=0;lastUpdate=0;updateInterval=null;spinnerFrameIndex=0;started=0;shutdownPending=!1;nextWorkerId=0;activeWorkers=0;printFinalResults=!1;constructor(e,{workerCount:t=_.availableParallelism()}={}){this.fileQueue=[...e],this.testFiles=[...e],this.testFileNames=e.map(r=>C.basename(r)),this.filesFailed=new Map,this.filesCompleted=new Set,this.workerCount=Math.min(t,e.length)}async start(){if(this.testFiles.length===0){this.printResults(),this.shutdown();return}this.started=performance.now();let e=I.createServer(t=>this.handleSocketConnected(t));this.server=e,await new Promise(t=>{e.listen(t)}),this.spawnWorkers(),this.updateInterval=setInterval(()=>{this.tick()},i.UPDATE_INTERVAL_MS)}handleSocketConnected(e){e.on("data",t=>{let r;try{r=this.handleData(e,t)}catch(a){this.handleError(i.ERROR_CODE_HANDLE_DATA,a);return}let{response:s,workerId:o}=r;if(o===void 0)throw new Error("Could not determine workerId from socket or message");let n=this.workerData[o];n.writeInProgress=!0,e.write(JSON.stringify(s),a=>{if(n.writeInProgress=!1,a)return this.handleError(i.ERROR_CODE_SOCKET_WRITE_ERROR,a,{socket:e});this.shutdownPending&&this.shutdown()})}),e.on("error",t=>{let r=this.workerIdBySocket.get(e);if(!r||!this.workerData[r].completed){if(r){let s=this.workerData[r],o=s.stdErrBuffer.getContent().toString(),n=s.stdOutBuffer.getContent().toString(),a=l.RED_BACKGROUND(l.BOLD(`Worker Error:
`));o&&(a+=l.RED(`
Std Err:
${o}`)),n&&(a+=l.RED(`
Std Out:
${n}`)),console.error(a)}this.handleError(i.ERROR_CODE_SOCKET_ERROR,t,{socket:e})}})}spawnWorkers(){for(;this.activeWorkers<this.workerCount&&this.fileQueue.length>0;){let e=this.fileQueue.shift(),t=this.nextWorkerId++;this.workerData[t]={writeInProgress:!1,currentTest:null,success:!0,completed:!1,result:null,file:e,currentTimeout:i.DEFAULT_TIMEOUT_MS,lastUpdate:Date.now(),currentPath:[],connectionTimeout:null,stdOutBuffer:new T(1024,64),stdErrBuffer:new T(1024,64)},this.results.set(e,{results:[],name:C.basename(e),success:!0,started:0,ended:0,printed:!1}),this.workerDataFileInProgress.set(e,this.workerData[t]),this.spawnWorker(t,e),this.activeWorkers++}}spawnWorker(e,t){let r=this.workerData[e],s=r.stdOutBuffer,o=r.stdErrBuffer,n={...process.env,__LLRT_TEST_SERVER_PORT:(this.server?.address()).port,__LLRT_TEST_WORKER_ID:e.toString(),__LLRT_TEST_FILE:t};delete n.LLRT_LOG;let a=F(process.argv0,["-e",'import("llrt:test/worker").catch(console.error)'],{env:n});a.stderr.on("data",u=>{o.append(u)}),a.stdout.on("data",u=>{s.append(u)}),a.on("error",u=>{this.handleError(i.ERROR_CODE_PROCESS_ERROR,u,{id:e,ended:performance.now()})}),a.on("exit",u=>{u!=0&&(this.handleError(i.ERROR_CODE_PROCESS_ERROR,new Error("Worker process exited with a non-zero exit code"),{id:e,ended:performance.now()}),this.handleWorkerCompleted(e))}),r.connectionTimeout=setTimeout(()=>{try{a.kill()}catch{}},5e3),r.childProc=a}handleError(e,t,r){switch(e){case i.ERROR_CODE_HANDLE_DATA:console.error("Error handling data,",t),process.exit(1);case i.ERROR_CODE_SOCKET_WRITE_ERROR:case i.ERROR_CODE_SOCKET_ERROR:console.error("Socket error,",t),process.exit(1);case i.ERROR_CODE_PROCESS_ERROR:{let{id:s,ended:o}=r;this.handleTestError(s,t,o);break}}}handleData(e,t){let r=JSON.parse(t),{type:s}=r,o=this.workerIdBySocket.get(e);switch(o===void 0&&"workerId"in r&&(o=r.workerId),o!==void 0&&(this.workerData[o].lastUpdate=Date.now()),s){case"ready":{o=r.workerId,this.workerIdBySocket.set(e,o),clearTimeout(this.workerData[o].connectionTimeout);break}case"module":{let{testCount:n,skipCount:a,onlyCount:u}=r;this.totalTests+=n,this.totalSkipped+=a,this.totalOnly+=u;break}case"start":{let{desc:n,isSuite:a,started:u,timeout:c}=r,h=this.workerData[o];if(h.currentTimeout=c||i.DEFAULT_TIMEOUT_MS,a){let d={desc:n,tests:[],success:!0,children:[],parent:h.result,started:0,ended:0};if(d.parent)h.result.children.push(d);else{let R=this.results.get(h.file);R.started=u,R.results.push(d)}h.result=d}else{let d={desc:n,success:!0,started:u,ended:0,error:null};h.result.tests.push(d),h.currentTest=d}h.currentPath.push(n);break}case"end":{let{isSuite:n,ended:a,started:u}=r,c=this.workerData[o],h=c.result;if(c.lastUpdate=0,n){if(h.ended=a,h.started=u,c.result=h.parent,!c.result){let d=this.results.get(c.file);d.ended=a,d.started=u,c.success&&this.filesCompleted.add(c.file)}}else{this.totalSuccess++;let d=c.currentTest;d.ended=a,d.success=!0}c.currentPath.pop();break}case"error":{let{error:n,ended:a,workerId:u}=r,c=o??u;c!==void 0?this.handleTestError(c,n,a):console.error("Error from unknown worker:",n);break}case"completed":{this.handleWorkerCompleted(o);break}default:throw new Error("Unknown type")}return{response:null,workerId:o}}handleWorkerCompleted(e){let t=this.workerData[e];if(t.completed)return;t.completed=!0,this.completedWorkers++,this.activeWorkers--;let r=m(()=>{this.completedWorkers==this.testFiles.length&&!this.printFinalResults&&(this.printFinalResults=!0,clearInterval(this.updateInterval),this.tick(),this.printResults(),t.writeInProgress?this.shutdownPending=!0:this.shutdown())},"shutdownOrPrint");if(t.childProc){let s=setTimeout(()=>{let o=new Error("Test did not exit within 1s. It does not properly clean up created resources (servers, timeouts etc)");this.handleTestError(e,o,performance.now());try{t.childProc?.kill()}catch{}},1e3);t.childProc?.once("exit",()=>{clearTimeout(s),r()})}else r();this.spawnWorkers()}shutdown(){this.shutdownPending=!1,this.server?.close(()=>{A&&process.exit(0)})}handleTestError(e,t,r){let s=this.workerData[e],o=s.currentTest||{desc:"",success:!1,started:0,ended:0,error:t};s.success=!1;let n=this.results.get(s.file);n&&(n.success=!1);let a=this.filesFailed.get(s.file)||[];a.push({desc:s.currentPath.slice(1),error:t,stdErr:s.stdErrBuffer.getContent().toString(),stdOut:s.stdOutBuffer.getContent().toString()}),s.stdErrBuffer.clear(),s.stdOutBuffer.clear(),this.filesFailed.set(s.file,a),this.totalFailed++,o.ended=r,o.error=t,o.success=!1,s.currentPath.pop()}tick(){let e=Date.now(),t=this.lastUpdate==0;e-this.lastUpdate>i.UPDATE_INTERVAL_MS&&(this.spinnerFrameIndex=(this.spinnerFrameIndex+1)%i.SPINNER.length,this.lastUpdate=e);for(let E in this.workerData){let f=this.workerData[E];if(!f.completed&&f.lastUpdate>0&&e-f.lastUpdate>=f.currentTimeout){this.handleTestError(E,new Error(`Test timed out after ${f.currentTimeout}ms`),performance.now());try{f.childProc?.kill()}catch{}f.childProc=void 0,this.handleWorkerCompleted(parseInt(E))}}let[r]=y(),s="";t||(s="\x1B[F\x1B[2K");let o=i.SPINNER[this.spinnerFrameIndex];r>80&&(r=80);let n=this.testFiles.length,a=(this.filesCompleted.size+this.filesFailed.size)/n,u=`${this.totalSuccess}/${this.totalTests}`,c=Math.min(i.DEFAULT_PROGRESS_BAR_WIDTH,Math.max(10,r-(2+u.length+2))),h=c,d=h==i.DEFAULT_PROGRESS_BAR_WIDTH;d&&(h+=i.TESTING_TEXT.length);let R=!1,k=!1,S=0,p="",O=!1;for(let E of this.testFiles){let f=this.results.get(E);if(R=this.filesCompleted.has(E),R||(k=this.filesFailed.has(E)),f&&(R||k)){f.printed||(f.printed=!0,s+=R?l.GREEN(i.CHECKMARK):l.RED(i.CROSS),s+=" ",s+=f.name,s+=`
`),S++;continue}let v=this.workerDataFileInProgress.has(E),w=this.testFileNames[S];v&&h+p.length+4<r&&(h+p.length+w.length+4<r?(p+=w,p+=", "):(O=!0,p+=w.slice(0,r-(h+p.length+5)),p+="...")),S++}O||(p=p.slice(0,-2));let g=Math.floor(c*a),b=c-g;s+=o,d&&(s+=l.CYAN_BOLD(i.TESTING_TEXT)),s+=`[${"=".repeat(g)}${"-".repeat(b)}]`,s+=u,s+=": ",s+=l.DIM(p),console.log(s)}printResults(){let e=performance.now(),t="";for(let r of this.testFiles){let s=this.results.get(r);t+=`${s.success?l.GREEN_BACKGROUND(l.BOLD(" PASS ")):l.RED_BACKGROUND(l.BOLD(" FAIL "))} ${s.name} ${l.DIM(i.elapsed(s))}
`;for(let o of s.results)t+=this.printSuiteResult(o);t+=`
`}if(this.totalFailed==0?t+=l.GREEN_BACKGROUND(l.BOLD(` ${i.CHECKMARK} ALL PASS `)):t+=l.RED_BACKGROUND(l.BOLD(` ${i.CHECKMARK} TESTS FAILED `)),t+=` ${l.DIM(i.elapsed({started:this.started,ended:e}))}
`,t+=`${this.totalSuccess} passed, ${this.totalFailed} failed, ${this.totalSkipped} skipped, ${this.totalTests} tests
`,console.log(t),this.totalFailed>0){t="";let r=new Map(Array.from(this.filesFailed.entries()).sort(([s],[o])=>s.localeCompare(o)));for(let[s,o]of r){t+=`
${l.RED_BACKGROUND(` ${s} `)}
`;for(let n of o)t+=n.desc.map(a=>l.BOLD(a)).join(" > ")+`
${this.formattedError(n.error)}
`,n.stdOut&&(t+=`----- LAST STDOUT: -----
`+n.stdOut+`
`),n.stdErr&&(t+=`----- LAST STDERR: -----
`+n.stdErr+`
`)}process.exitCode=1,console.error(t)}}printSuiteResult(e,t=0){let r="",s=" ".repeat(t);for(let n of e.tests){let a=n.success?l.GREEN(i.CHECKMARK):l.RED(i.CROSS);r+=`${s}${a} ${n.desc} ${l.DIM(i.elapsed(n))}
`,n.error&&(r+=this.formattedError(n.error)+`
`)}let o=e.children;for(let n of o)r+=`${s}${l.BOLD(n.desc)} ${l.DIM(i.elapsed(n))}
`,r+=this.printSuiteResult(n,t+1);return r}formattedError(e,t=""){let r=e.stack||"";return t&&r&&(r=r.split(`
`).map(s=>t+s).join(`
`)),l.RED(`${t}\x1B[1m${e.name}:\x1B[22m ${e.message}
${r}`)}static elapsed({started:e,ended:t}){return`${(t-e).toFixed(3)}ms`}},M=new D(globalThis.__testEntries,{workerCount:void 0});await M.start();