11use std:: {
2- cell:: RefCell ,
32 ffi:: { OsStr , OsString } ,
43 sync:: Arc ,
54 thread,
65} ;
76
87use rustc_hash:: FxHashMap ;
98use tokio:: runtime:: Builder ;
10- use vite_path:: { AbsolutePath , AbsolutePathBuf } ;
11- use vite_str:: Str ;
9+ use vite_path:: AbsolutePathBuf ;
1210use vite_task_client:: Client ;
13- use vite_task_server:: { Handler , ServerHandle , serve} ;
14-
15- #[ derive( Default ) ]
16- struct RecordingHandler {
17- ignore_inputs : RefCell < Vec < Arc < AbsolutePath > > > ,
18- ignore_outputs : RefCell < Vec < Arc < AbsolutePath > > > ,
19- disable_cache_count : RefCell < u32 > ,
20- env_calls : RefCell < Vec < ( Str , bool ) > > ,
21- env_map : FxHashMap < & ' static str , & ' static str > ,
22- }
23-
24- impl Handler for RecordingHandler {
25- fn ignore_input ( & self , path : & Arc < AbsolutePath > ) {
26- self . ignore_inputs . borrow_mut ( ) . push ( Arc :: clone ( path) ) ;
27- }
28-
29- fn ignore_output ( & self , path : & Arc < AbsolutePath > ) {
30- self . ignore_outputs . borrow_mut ( ) . push ( Arc :: clone ( path) ) ;
31- }
32-
33- fn disable_cache ( & self ) {
34- * self . disable_cache_count . borrow_mut ( ) += 1 ;
35- }
36-
37- fn get_env ( & self , name : & str , tracked : bool ) -> Option < Arc < OsStr > > {
38- self . env_calls . borrow_mut ( ) . push ( ( name. into ( ) , tracked) ) ;
39- self . env_map . get ( name) . map ( |value| Arc :: < OsStr > :: from ( OsStr :: new ( value) ) )
40- }
41- }
11+ use vite_task_server:: { Recorder , Reports , ServerHandle , serve} ;
4212
4313fn abs ( path : & str ) -> AbsolutePathBuf {
4414 AbsolutePathBuf :: new ( path. into ( ) ) . expect ( "absolute path literal" )
4515}
4616
47- fn run_with_server < F > ( handler : RecordingHandler , client_work : F ) -> RecordingHandler
17+ fn run_with_server < F > ( env_map : FxHashMap < & ' static str , & ' static str > , client_work : F ) -> Reports
4818where
4919 F : FnOnce ( OsString ) + Send + ' static ,
5020{
21+ let recorder = Recorder :: new ( move |name : & str | {
22+ env_map. get ( name) . map ( |value| Arc :: < OsStr > :: from ( OsStr :: new ( value) ) )
23+ } ) ;
24+
5125 let rt = Builder :: new_current_thread ( ) . enable_all ( ) . build ( ) . unwrap ( ) ;
5226 rt. block_on ( async move {
53- let ( envs, ServerHandle { driver, stop_accepting } ) = serve ( handler ) . expect ( "bind server" ) ;
27+ let ( envs, ServerHandle { driver, stop_accepting } ) = serve ( recorder ) . expect ( "bind server" ) ;
5428 let name = envs. into_iter ( ) . next ( ) . expect ( "serve should yield an IPC env" ) . 1 ;
5529
5630 let client = async move {
@@ -61,55 +35,73 @@ where
6135 } ;
6236
6337 let ( recorder, ( ) ) = tokio:: join!( driver, client) ;
64- recorder
38+ recorder. into_reports ( )
6539 } )
6640}
6741
6842#[ test]
6943fn single_client_fire_and_forget ( ) {
70- let h = run_with_server ( RecordingHandler :: default ( ) , |name| {
44+ let reports = run_with_server ( FxHashMap :: default ( ) , |name| {
7145 let mut client = Client :: from_name ( & name) . expect ( "connect" ) ;
7246 client. ignore_input ( abs ( "/tmp/in.txt" ) . as_absolute_path ( ) ) . unwrap ( ) ;
7347 client. ignore_output ( abs ( "/tmp/out.txt" ) . as_absolute_path ( ) ) . unwrap ( ) ;
7448 client. disable_cache ( ) . unwrap ( ) ;
7549 } ) ;
7650
77- let inputs = h. ignore_inputs . into_inner ( ) ;
78- let outputs = h. ignore_outputs . into_inner ( ) ;
79- assert_eq ! ( inputs. len( ) , 1 ) ;
80- assert_eq ! ( inputs[ 0 ] . as_path( ) . as_os_str( ) , OsStr :: new( "/tmp/in.txt" ) ) ;
81- assert_eq ! ( outputs. len( ) , 1 ) ;
82- assert_eq ! ( outputs[ 0 ] . as_path( ) . as_os_str( ) , OsStr :: new( "/tmp/out.txt" ) ) ;
83- assert_eq ! ( h. disable_cache_count. into_inner( ) , 1 ) ;
51+ let inputs: Vec < _ > = reports. ignored_inputs . iter ( ) . map ( |p| p. as_path ( ) . as_os_str ( ) ) . collect ( ) ;
52+ let outputs: Vec < _ > = reports. ignored_outputs . iter ( ) . map ( |p| p. as_path ( ) . as_os_str ( ) ) . collect ( ) ;
53+ assert_eq ! ( inputs, vec![ OsStr :: new( "/tmp/in.txt" ) ] ) ;
54+ assert_eq ! ( outputs, vec![ OsStr :: new( "/tmp/out.txt" ) ] ) ;
55+ assert ! ( reports. cache_disabled) ;
8456}
8557
8658#[ test]
8759fn get_env_found_and_not_found ( ) {
88- let mut handler = RecordingHandler :: default ( ) ;
89- handler . env_map . insert ( "NODE_ENV" , "production" ) ;
60+ let mut env_map = FxHashMap :: default ( ) ;
61+ env_map. insert ( "NODE_ENV" , "production" ) ;
9062
91- let h = run_with_server ( handler , |name| {
63+ let reports = run_with_server ( env_map , |name| {
9264 let mut client = Client :: from_name ( & name) . expect ( "connect" ) ;
9365 let present = client. get_env ( "NODE_ENV" , true ) . unwrap ( ) ;
9466 assert_eq ! ( present. as_deref( ) , Some ( OsStr :: new( "production" ) ) ) ;
9567 let missing = client. get_env ( "MISSING" , false ) . unwrap ( ) ;
9668 assert ! ( missing. is_none( ) ) ;
9769 } ) ;
9870
99- let calls = h. env_calls . into_inner ( ) ;
100- assert_eq ! ( calls. len( ) , 2 ) ;
101- assert_eq ! ( calls[ 0 ] . 0 . as_str( ) , "NODE_ENV" ) ;
102- assert ! ( calls[ 0 ] . 1 ) ;
103- assert_eq ! ( calls[ 1 ] . 0 . as_str( ) , "MISSING" ) ;
104- assert ! ( !calls[ 1 ] . 1 ) ;
71+ let node = reports. env_records . get ( "NODE_ENV" ) . expect ( "NODE_ENV recorded" ) ;
72+ assert ! ( node. tracked) ;
73+ assert_eq ! ( node. value. as_deref( ) , Some ( OsStr :: new( "production" ) ) ) ;
74+
75+ let missing = reports. env_records . get ( "MISSING" ) . expect ( "MISSING recorded" ) ;
76+ assert ! ( !missing. tracked) ;
77+ assert ! ( missing. value. is_none( ) ) ;
78+ }
79+
80+ #[ test]
81+ fn get_env_tracked_upgrade_is_monotonic ( ) {
82+ let mut env_map = FxHashMap :: default ( ) ;
83+ env_map. insert ( "NODE_ENV" , "production" ) ;
84+
85+ let reports = run_with_server ( env_map, |name| {
86+ let mut client = Client :: from_name ( & name) . expect ( "connect" ) ;
87+ let a = client. get_env ( "NODE_ENV" , false ) . unwrap ( ) ;
88+ let b = client. get_env ( "NODE_ENV" , true ) . unwrap ( ) ;
89+ let c = client. get_env ( "NODE_ENV" , false ) . unwrap ( ) ;
90+ for v in [ a, b, c] {
91+ assert_eq ! ( v. as_deref( ) , Some ( OsStr :: new( "production" ) ) ) ;
92+ }
93+ } ) ;
94+
95+ let node = reports. env_records . get ( "NODE_ENV" ) . expect ( "recorded" ) ;
96+ assert ! ( node. tracked, "tracked must remain true once set" ) ;
10597}
10698
10799#[ test]
108100fn concurrent_clients ( ) {
109- let mut handler = RecordingHandler :: default ( ) ;
110- handler . env_map . insert ( "SHARED" , "value" ) ;
101+ let mut env_map = FxHashMap :: default ( ) ;
102+ env_map. insert ( "SHARED" , "value" ) ;
111103
112- let h = run_with_server ( handler , |name| {
104+ let reports = run_with_server ( env_map , |name| {
113105 let threads: Vec < _ > = ( 0 ..4 )
114106 . map ( |i| {
115107 let name = name. clone ( ) ;
@@ -127,6 +119,8 @@ fn concurrent_clients() {
127119 }
128120 } ) ;
129121
130- assert_eq ! ( h. ignore_inputs. into_inner( ) . len( ) , 4 ) ;
131- assert_eq ! ( h. env_calls. into_inner( ) . len( ) , 4 ) ;
122+ assert_eq ! ( reports. ignored_inputs. len( ) , 4 ) ;
123+ let shared = reports. env_records . get ( "SHARED" ) . expect ( "recorded" ) ;
124+ assert ! ( shared. tracked) ;
125+ assert_eq ! ( shared. value. as_deref( ) , Some ( OsStr :: new( "value" ) ) ) ;
132126}
0 commit comments