Files
MikrotikManager/backend/scripts/test-flow-read-profile-startup.mjs
T

29 lines
3.8 KiB
JavaScript

import{readFile,writeFile,mkdtemp,rm}from'node:fs/promises'
import{resolve,join,dirname}from'node:path'
import{spawn}from'node:child_process'
import assert from'node:assert/strict'
import ts from'typescript'
import{build,stop}from'esbuild'
const repo=resolve(import.meta.dirname,'../..'),folder=await mkdtemp(join(repo,'tmp','mm-flow-profile-startup-owned-'))
async function run(file,cwd,explicit,expected){
const env={...process.env,NODE_ENV:'test',AUTH_REQUIRED:'false',DATABASE_URL:'postgresql://unused:unused@127.0.0.1:1/unused',EXPECT_PROFILE:expected};delete env.MM_FLOW_READ_RESOURCE_PROFILE;if(explicit!==undefined)env.MM_FLOW_READ_RESOURCE_PROFILE=explicit
return new Promise((resolve,reject)=>{let output='';const child=spawn(process.execPath,[file],{cwd,env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',x=>output+=x);child.stderr.on('data',x=>output+=x);child.once('error',reject);child.once('exit',code=>resolve({code,output}))})
}
try{
const source=await readFile(resolve(repo,'backend/src/services/traffic-flow-read-resource-profile.ts'),'utf8'),js=ts.transpileModule(source,{compilerOptions:{target:ts.ScriptTarget.ES2022,module:ts.ModuleKind.ESNext}}).outputText
await writeFile(join(folder,'profile.mjs'),js);await writeFile(join(folder,'eager-negative.mjs'),js+'\ngetFlowReadResourceProfile();\n');await writeFile(join(folder,'load-env.mjs'),"import{config}from'dotenv';config({quiet:true});");await writeFile(join(folder,'.env'),'MM_FLOW_READ_RESOURCE_PROFILE=constrained\n')
for(const[profile,success]of[['profile.mjs',true],['eager-negative.mjs',false]]){
await writeFile(join(folder,'policy.mjs'),`import{getFlowReadResourceProfile}from'./${profile}';import'./load-env.mjs';export const policy=getFlowReadResourceProfile();`)
await writeFile(join(folder,'order.mjs'),"import assert from'node:assert/strict';import{policy}from'./policy.mjs';assert.equal(policy.name,'constrained');")
const result=await run(join(folder,'order.mjs'),folder,undefined,'constrained');if(success)assert.equal(result.code,0,result.output);else{assert.notEqual(result.code,0);assert.match(result.output,/standard/)}
}
const abs=path=>JSON.stringify(resolve(repo,path).replaceAll('\\','/'))
await writeFile(join(folder,'actual.ts'),`import{getFlowReadResourceProfile}from${abs('backend/src/services/traffic-flow-read-resource-profile.ts')};import{FLOW_READ_RESERVATION_BYTES}from${abs('backend/src/services/traffic-flow-read-policy.ts')};import{pool}from${abs('backend/src/db/index.ts')};import assert from'node:assert/strict';const p=getFlowReadResourceProfile();assert.equal(p.name,process.env.EXPECT_PROFILE);assert.equal(FLOW_READ_RESERVATION_BYTES,p.reservationBytes);assert.equal(p.parallelSql,8);process.env.MM_FLOW_READ_RESOURCE_PROFILE=p.name==='standard'?'constrained':'standard';assert.equal(getFlowReadResourceProfile().name,p.name);await pool.end();`)
await build({entryPoints:[join(folder,'actual.ts')],outfile:join(folder,'actual.mjs'),bundle:true,format:'esm',platform:'node',packages:'external'})
for(const[label,dotenv,explicit,expected]of[['standard','standard',undefined,'standard'],['dotenv-constrained','constrained',undefined,'constrained'],['explicit-standard','constrained','standard','standard'],['invalid','constrained','invalid','INVALID']]){
await writeFile(join(folder,'.env'),'MM_FLOW_READ_RESOURCE_PROFILE='+dotenv+'\n');const result=await run(join(folder,'actual.mjs'),folder,explicit,expected)
if(expected==='INVALID'){assert.notEqual(result.code,0);assert.match(result.output,/MM_FLOW_READ_RESOURCE_PROFILE must be/)}else assert.equal(result.code,0,label+':'+result.output)
}
console.log('PASS pure import order/.env actual policy/explicit override/invalid profile/immutable selection')
}finally{stop();assert.equal(dirname(folder),resolve(repo,'tmp'));await rm(folder,{recursive:true,force:true,maxRetries:10,retryDelay:100})}