char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
688e96e
main
1# [ path = "common/http.rs" ] 2mod http_fixture; 3 4use http_fixture:: Http ; 5 6fn cli ( directory : & std:: path:: Path , args : & [ & str ]) -> std:: process:: Output { 7 std:: process:: Command :: new ( env! ( "CARGO_BIN_EXE_avril" )) 8. current_dir ( directory) 9. arg ( args[ 0 ]) 10. arg ( "--cache-dir=cache" ) 11. args ( & args[ 1 ..]) 12. output () 13. unwrap () 14} 15 16fn success ( output : std:: process:: Output ) ->String { 17assert! ( 18 output. status . success (), 19"{}" , 20String :: from_utf8_lossy ( & output. stderr ) 21); 22String :: from_utf8 ( output. stdout ). unwrap () 23} 24 25# [ test ] 26fn http_graphs_resolve_maps_cycles_queries_and_concurrent_dynamic_imports () { 27let http =Http :: new (); 28let dir = tempfile:: tempdir (). unwrap (); 29 http. source ( "lib/mod.ts?version=1" , "import type {Missing} from './missing.ts'; import './cycle.ts'; export {value} from './dep.mts'; export const count: number = globalThis.count = (globalThis.count ?? 0) + 1; export const url = import.meta.url; export const self = () => import(import.meta.url);" ); 30 http. source ( 31"lib/cycle.ts" , 32"import {count} from './mod.ts?version=1'; export const read = () => count;" , 33); 34 http. source ( "lib/dep.mts" , "export const value: number = 42;" ); 35 http. source ( 36"lib/lazy.ts" , 37"import {value} from './dep.mts'; export {value};" , 38); 39let name = http. name ( "lib/mod.ts?version=1" ); 40 std:: fs:: write ( 41 dir. path (). join ( "avril.conf" ), 42format! ( "imports: {{lib: '{name}'}}" ), 43) 44. unwrap (); 45 std:: fs:: write ( dir. path (). join ( "main.ts" ), format! ( "import * as a from 'lib'; import * as b from '{name}'; const lazy = '{}'; const [x,y] = await Promise.all([import(lazy),import(lazy)]); console.log(a === b, a.value, a.count, (await a.self()) === a, x === y, x.value, a.url);" , http. name ( "lib/lazy.ts" ))). unwrap (); 46let expected =format! ( "true 42 1 true true 42 {name}\n" ); 47assert_eq! ( success ( cli ( dir. path (), & [ "run" , "main.ts" ])), expected); 48let requests = http. requests . lock (). unwrap (). clone (); 49assert_eq! ( requests. len (), 4 , "{requests:?}" ); 50assert_eq! ( 51success ( cli ( 52 dir. path (), 53& [ "run" , "--offline" , "--frozen" , "main.ts" ] 54)), 55 expected 56); 57assert_eq! ( * http. requests . lock (). unwrap (), requests); 58let info: serde_json:: Value = 59 serde_json:: from_str ( & success ( cli ( dir. path (), & [ "info" , "--offline" , "main.ts" ]))). unwrap (); 60assert_eq! ( info[ "modules" ][ & name][ "url" ], name); 61assert_eq! ( 62 info[ "modules" ][ & name][ "imports" ][ "./dep.mts" ], 63 http. name ( "lib/dep.mts" ) 64); 65} 66 67# [ test ] 68fn redirected_modules_use_the_final_base_without_authorizing_redirect_targets () { 69let http =Http :: new (); 70let target =Http :: new (); 71let dir = tempfile:: tempdir (). unwrap (); 72 http. redirect ( "start" , & target. name ( "nested/mod.ts" )); 73 target. source ( "nested/mod.ts" , "export const value: number = 7; export const url = import.meta.url; export const self = () => import(import.meta.url);" ); 74let name = http. name ( "start" ); 75 std:: fs:: write ( 76 dir. path (). join ( "main.ts" ), 77format! ( 78"import * as a from '{name}'; console.log(a.value, a.url, (await a.self()) === a);" 79), 80) 81. unwrap (); 82let allow =format! ( "--allow-js-exec={name}" ); 83let deny =format! ( "--deny-js-exec={}" , target. url ); 84let args =[ "run" , "-0" , & allow, & deny, "main.ts" ]; 85let expected =format! ( "7 {name} true\n" ); 86assert_eq! ( success ( cli ( dir. path (), & args)), expected); 87let mut offline = args. to_vec (); 88 offline. insert ( 1 , "--offline" ); 89assert_eq! ( success ( cli ( dir. path (), & offline)), expected); 90 target. source ( "nested/mod.ts" , "import {value} from './dep.ts'; export {value}; export const url = import.meta.url; export const self = () => import(import.meta.url);" ); 91 target. source ( "nested/dep.ts" , "export const value: number = 9;" ); 92let output =cli ( dir. path (), & [ "update" , "-0" , & allow, & deny, "main.ts" ]); 93assert! ( !output. status . success ()); 94assert! ( String :: from_utf8_lossy ( & output. stderr ). contains ( "PermissionDenied" )); 95assert! ( 96 !target 97. requests 98. lock () 99. unwrap () 100. iter () 101. any ( |path| path. ends_with ( "dep.ts" )) 102); 103let dep = target. name ( "nested/dep.ts" ); 104let allow_dep =format! ( "--allow-js-exec={dep}" ); 105success ( cli ( 106 dir. path (), 107& [ "update" , "-0" , & allow, & allow_dep, "main.ts" ], 108)); 109assert_eq! ( 110success ( cli ( 111 dir. path (), 112& [ 113"run" , 114"--offline" , 115"--frozen" , 116"-0" , 117& allow, 118& allow_dep, 119"main.ts" 120] 121)), 122 expected. replace ( "7 " , "9 " ) 123); 124} 125 126# [ test ] 127fn update_refreshes_cli_graphs_and_http_urls_can_be_entries () { 128let http =Http :: new (); 129let dir = tempfile:: tempdir (). unwrap (); 130let name = http. name ( "entry.ts?x=1" ); 131 http. source ( 132"entry.ts?x=1" , 133"console.log(1, import.meta.main, import.meta.url); export {};" , 134); 135let expected =format! ( "1 true {name}\n" ); 136assert_eq! ( success ( cli ( dir. path (), & [ "run" , "-0" , & name])), expected); 137 http. source ( 138"entry.ts?x=1" , 139"console.log(2, import.meta.main, import.meta.url); export {};" , 140); 141assert_eq! ( success ( cli ( dir. path (), & [ "run" , "-0" , & name])), expected); 142success ( cli ( dir. path (), & [ "update" , & name])); 143assert_eq! ( 144success ( cli ( 145 dir. path (), 146& [ "run" , "--offline" , "--frozen" , "-0" , & name] 147)), 148 expected. replace ( "1 true" , "2 true" ) 149); 150let deny =format! ( "--deny-js-exec={}" , http. url ); 151let output =cli ( dir. path (), & [ "run" , "--offline" , "-0" , & deny, & name]); 152assert! ( !output. status . success ()); 153assert! ( String :: from_utf8_lossy ( & output. stderr ). contains ( "PermissionDenied" )); 154} 155 156# [ test ] 157fn http_modules_do_not_inherit_local_aliases_or_resolve_file_urls () { 158let http =Http :: new (); 159let dir = tempfile:: tempdir (). unwrap (); 160 std:: fs:: write ( dir. path (). join ( "avril.conf" ), "imports: {dep: './dep.ts'}" ). unwrap (); 161 std:: fs:: write ( 162 dir. path (). join ( "dep.ts" ), 163"throw new Error('local file executed');" , 164) 165. unwrap (); 166for ( specifier, expected) in [ 167( "dep" , "Unsupported module specifier: dep" ), 168( 169"file:///tmp/dep.ts" , 170"Unsupported module specifier: file:///tmp/dep.ts" , 171), 172( 173"node:fs" , 174"node: builtin modules are not supported: node:fs" , 175), 176] { 177 http. source ( "mod.js" , & format! ( "import '{specifier}';" )); 178 std:: fs:: write ( 179 dir. path (). join ( "main.ts" ), 180format! ( "import '{}';" , http. name ( "mod.js" )), 181) 182. unwrap (); 183let output =cli ( dir. path (), & [ "update" , "main.ts" ]); 184assert! ( !output. status . success ()); 185assert! ( 186String :: from_utf8_lossy ( & output. stderr ). contains ( expected), 187"{specifier}: {}" , 188String :: from_utf8_lossy ( & output. stderr ) 189); 190} 191} 192 193# [ test ] 194fn http_sources_are_vendored_and_usable_offline () { 195let http =Http :: new (); 196let dir = tempfile:: tempdir (). unwrap (); 197let name = http. name ( "start" ); 198 http. redirect ( "start" , "/nested/mod.ts" ); 199 http. source ( "nested/mod.ts" , "export {value} from './dep.ts';" ); 200 http. source ( "nested/dep.ts" , "export const value: number = 42;" ); 201 std:: fs:: write ( 202 dir. path (). join ( "main.ts" ), 203format! ( "import {{value}} from '{name}'; console.log(value);" ), 204) 205. unwrap (); 206success ( cli ( dir. path (), & [ "vendor" , "main.ts" ])); 207 std:: fs:: remove_dir_all ( dir. path (). join ( "cache" )). unwrap (); 208assert_eq! ( 209success ( cli ( 210 dir. path (), 211& [ "run" , "--vendor=vendor" , "--offline" , "--frozen" , "main.ts" ] 212)), 213"42\n" 214); 215} 216 217# [ test ] 218fn complete_http_modules_obey_live_revocation_of_the_requested_url () { 219let http =Http :: new (); 220let target =Http :: new (); 221let dir = tempfile:: tempdir (). unwrap (); 222let name = http. name ( "start" ); 223 http. redirect ( "start" , & target. name ( "mod.ts" )); 224 target. source ( "mod.ts" , "export const value = 42;" ); 225 std:: fs:: write ( dir. path (). join ( "main.ts" ), format! ( "import {{pledge}} from 'avril:std'; const a = await import('{name}'); pledge({{jsExec: {{deny: ['{}']}}}}); console.log((await import('{name}')) === a); pledge({{jsExec: {{deny: ['{name}']}}}}); try {{await import('{name}'); console.log('allowed');}} catch(e) {{console.log(e.message.includes('PermissionDenied'));}}" , target. url )). unwrap (); 226assert_eq! ( 227success ( cli ( dir. path (), & [ "run" , "main.ts" ])), 228"true\ntrue\n" 229); 230}