char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
688e96e
main
1mod common; 2 3use std:: fs; 4use std:: process::{ Command , Stdio }; 5use std:: time::{ SystemTime , UNIX_EPOCH }; 6 7# [ test ] 8fn embedded_startup_uses_live_state_in_main_and_nested_workers () { 9let directory = tempfile:: tempdir (). unwrap (); 10let root = directory. path (); 11 fs:: write ( 12 root. join ( "state.js" ), 13r#" 14import {env, process} from 'avril:std'; 15export async function state() { 16let value, denied; 17try { value = env.get('AVRIL_STARTUP_VALUE'); } 18catch (error) { value = error.name; } 19try { env.get('AVRIL_STARTUP_UNGRANTED'); } 20catch (error) { denied = error.name; } 21await new Promise(resolve => setTimeout(resolve, 1)); 22return { 23pid: process.pid, args: process.args, value, denied, 24origin: performance.timeOrigin, 25storage: typeof Storage !== 'undefined', 26name: globalThis.name ?? '', url: globalThis.location?.href ?? '', 27random: Array.from({length: 4}, () => Math.random()), 28uuid: crypto.randomUUID(), 29}; 30} 31export function child(name) { 32const worker = new Worker('./worker.js', {type: 'module', name}); 33return new Promise((resolve, reject) => { 34worker.onmessage = event => resolve(event.data); 35worker.onerror = event => reject(Error(event.message)); 36}); 37} 38"# , 39) 40. unwrap (); 41 fs:: write ( 42 root. join ( "worker.js" ), 43r#" 44import {env} from 'avril:std'; 45import {state, child} from './state.js'; 46const result = await state(); 47if (name === 'branch') { 48env.set('AVRIL_STARTUP_VALUE', 'nested value'); 49result.nested = await child('leaf'); 50} 51postMessage(result); 52close(); 53"# , 54) 55. unwrap (); 56 fs:: write ( 57 root. join ( "main.js" ), 58r#" 59import {env, pledge} from 'avril:std'; 60import {state, child} from './state.js'; 61const result = await state(); 62result.worker = await child('branch'); 63if (env.get('AVRIL_STARTUP_VALUE') !== result.value) throw Error('Shared environment'); 64pledge({env: false}); 65result.narrowed = await child('denied'); 66console.log(JSON.stringify(result)); 67"# , 68) 69. unwrap (); 70let worker_url = url:: Url :: from_file_path ( root. join ( "worker.js" )) 71. unwrap () 72. to_string (); 73let mut random_sequences = std:: collections:: HashSet :: new (); 74let mut uuids = std:: collections:: HashSet :: new (); 75for labelin [ "first process" , "second process" ] { 76let started =SystemTime :: now () 77. duration_since ( UNIX_EPOCH ) 78. unwrap () 79. as_millis (); 80let child =Command :: new ( env! ( "CARGO_BIN_EXE_avril" )) 81. current_dir ( root) 82. env ( "AVRIL_STARTUP_VALUE" , label) 83. args ([ 84"run" , 85"-0" , 86"--allow-js-exec=." , 87"--allow-env=AVRIL_STARTUP_VALUE" , 88"main.js" , 89 label, 90]) 91. stdin ( Stdio :: null ()) 92. stdout ( Stdio :: piped ()) 93. stderr ( Stdio :: piped ()) 94. spawn () 95. unwrap (); 96let pid = child. id (); 97let output = common:: wait ( child); 98assert! ( 99 output. status . success (), 100"{}" , 101String :: from_utf8_lossy ( & output. stderr ) 102); 103let result: serde_json:: Value = serde_json:: from_slice ( & output. stdout ). unwrap (); 104for ( state, name, value) in [ 105( & result, "" , label), 106( & result[ "worker" ], "branch" , label), 107( & result[ "worker" ][ "nested" ], "leaf" , "nested value" ), 108( & result[ "narrowed" ], "denied" , "PermissionDenied" ), 109] { 110assert! ( random_sequences. insert ( state[ "random" ]. to_string ())); 111assert! ( uuids. insert ( state[ "uuid" ]. as_str (). unwrap (). to_owned ())); 112assert_eq! ( state[ "pid" ], pid); 113assert_eq! ( state[ "args" ], serde_json:: json!([ label])); 114assert_eq! ( state[ "value" ], value); 115assert_eq! ( state[ "denied" ], "PermissionDenied" ); 116assert_eq! ( state[ "name" ], name); 117assert_eq! ( state[ "storage" ], name. is_empty ()); 118assert_eq! ( state[ "url" ], if name. is_empty () { "" } else { & worker_url}); 119assert! ( state[ "origin" ]. as_f64 (). unwrap () >= startedas f64 -1000.0 ); 120} 121} 122}