1
1
use proc_macro2:: { Span , TokenStream } ;
2
2
use quote:: ToTokens ;
3
- use serde:: { Deserialize , Serialize } ;
4
- use std:: collections:: HashMap ;
5
3
use std:: env:: VarError ;
6
- use std:: fmt:: Write ;
7
- use std:: fs:: create_dir_all;
8
- use std:: path:: { Path , PathBuf } ;
9
4
use syn:: { parse_quote, Error , ItemFn } ;
10
5
11
6
pub fn parse_qemu_attribute ( mut item : ItemFn ) -> Result < TokenStream , Error > {
12
- // Get path for the integration test data.
13
- let root = match std:: env:: var ( "CARGO_TARGET_TMPDIR" ) {
14
- Ok ( v) => PathBuf :: from ( v) ,
15
- Err ( e) => match e {
16
- VarError :: NotPresent => {
17
- // We are not running by the integration test, keep the original function body.
18
- return Ok ( item. into_token_stream ( ) ) ;
19
- }
20
- VarError :: NotUnicode ( _) => {
21
- return Err ( Error :: new (
22
- Span :: call_site ( ) ,
23
- "non-unicode value in CARGO_TARGET_TMPDIR" ,
24
- ) )
25
- }
26
- } ,
27
- } ;
28
-
29
- // Generate a test project.
30
- let name = item. sig . ident . to_string ( ) ;
31
- let body = item. block . brace_token . span . join ( ) . source_text ( ) . unwrap ( ) ;
32
-
33
- generate_test ( root. join ( "project" ) , & name, & body) ?;
34
-
35
- // Construct a new body.
36
- let root = root. to_str ( ) . unwrap ( ) ;
37
-
38
- item. block = Box :: new ( parse_quote ! ( {
39
- let dest = std:: path:: PathBuf :: from( env!( "CARGO_TARGET_TMPDIR" ) ) ;
40
- :: zfi_testing:: gen_qemu_test( dest, #name, #body) ;
41
- :: zfi_testing:: run_qemu_test( :: std:: path:: Path :: new( #root) ) ;
42
- } ) ) ;
43
-
44
- Ok ( item. into_token_stream ( ) )
45
- }
46
-
47
- fn generate_test < P : AsRef < Path > > ( dir : P , name : & str , body : & str ) -> Result < ( ) , Error > {
48
- // Create project directory.
49
- let dir = dir. as_ref ( ) ;
50
-
51
- create_dir_all ( dir) . unwrap ( ) ;
7
+ // Do nothing if we are not running by the integration test.
8
+ if std:: env:: var ( "CARGO_TARGET_TMPDIR" ) . is_err_and ( |e| e == VarError :: NotPresent ) {
9
+ // Keep the original function body.
10
+ return Ok ( item. into_token_stream ( ) ) ;
11
+ }
52
12
53
13
// Get path to the project.
54
14
let proj = match std:: env:: var ( "CARGO_MANIFEST_DIR" ) {
55
- Ok ( v) => PathBuf :: from ( v ) ,
15
+ Ok ( v) => v ,
56
16
Err ( e) => {
57
17
return Err ( match e {
58
18
VarError :: NotPresent => {
@@ -65,144 +25,18 @@ fn generate_test<P: AsRef<Path>>(dir: P, name: &str, body: &str) -> Result<(), E
65
25
}
66
26
} ;
67
27
68
- // Copy application dependencies.
69
- let cargo = std:: fs:: read_to_string ( proj. join ( "Cargo.toml" ) ) . unwrap ( ) ;
70
- let mut cargo = toml:: from_str :: < Cargo > ( & cargo) . unwrap ( ) ;
71
-
72
- cargo. dev_dependencies . remove ( "zfi-testing" ) ;
73
- cargo. dependencies . extend ( cargo. dev_dependencies . drain ( ) ) ;
74
-
75
- // Fix relative path.
76
- for dep in cargo. dependencies . values_mut ( ) {
77
- let path = match dep {
78
- Dependency :: Complex {
79
- version : _,
80
- path : Some ( v) ,
81
- } => v,
82
- _ => continue ,
83
- } ;
84
-
85
- if !Path :: new ( path. as_str ( ) ) . is_relative ( ) {
86
- continue ;
87
- }
88
-
89
- * path = proj
90
- . join ( path. as_str ( ) )
91
- . canonicalize ( )
92
- . unwrap ( )
93
- . into_os_string ( )
94
- . into_string ( )
95
- . unwrap ( ) ;
96
- }
97
-
98
- // Check if the test being run is our test.
99
- if cargo. package . take ( ) . unwrap ( ) . name == "zfi" {
100
- cargo. dependencies . remove ( "zfi-macros" ) ;
101
- cargo. dependencies . insert (
102
- String :: from ( "zfi" ) ,
103
- Dependency :: Complex {
104
- version : None ,
105
- path : Some ( proj. into_os_string ( ) . into_string ( ) . unwrap ( ) ) ,
106
- } ,
107
- ) ;
108
- }
109
-
110
- // Create Cargo.toml.
111
- let mut data = String :: new ( ) ;
112
-
113
- writeln ! ( data, r#"[package]"# ) . unwrap ( ) ;
114
- writeln ! ( data, r#"name = "{name}""# ) . unwrap ( ) ;
115
- writeln ! ( data, r#"version = "0.1.0""# ) . unwrap ( ) ;
116
- writeln ! ( data, r#"edition = "2021""# ) . unwrap ( ) ;
117
- writeln ! ( data) . unwrap ( ) ;
118
- data. push_str ( & toml:: to_string_pretty ( & cargo) . unwrap ( ) ) ;
119
- writeln ! ( data) . unwrap ( ) ;
120
- writeln ! ( data, r#"[workspace]"# ) . unwrap ( ) ;
121
- writeln ! ( data, r#"members = []"# ) . unwrap ( ) ;
122
-
123
- std:: fs:: write ( dir. join ( "Cargo.toml" ) , data) . unwrap ( ) ;
124
-
125
- // Create src directory.
126
- let mut path = dir. join ( "src" ) ;
127
-
128
- create_dir_all ( & path) . unwrap ( ) ;
129
-
130
- // Generate src/main.rs.
131
- let mut data = String :: new ( ) ;
132
-
133
- writeln ! ( data, r#"#![no_std]"# ) . unwrap ( ) ;
134
- writeln ! ( data, r#"#![no_main]"# ) . unwrap ( ) ;
135
- writeln ! ( data) . unwrap ( ) ;
136
- writeln ! ( data, r#"#[::zfi::main(no_ph)]"# ) . unwrap ( ) ;
137
- writeln ! ( data, r#"fn main() -> ::zfi::Status {{"# ) . unwrap ( ) ;
138
- writeln ! ( data, r#"{}"# , & body[ 1 ..( body. len( ) - 1 ) ] ) . unwrap ( ) ;
139
- writeln ! ( data, r#" ::zfi::println!("zfi:ok");"# ) . unwrap ( ) ;
140
- writeln ! ( data, r#" loop {{}}"# ) . unwrap ( ) ;
141
- writeln ! ( data, r#"}}"# ) . unwrap ( ) ;
142
- writeln ! ( data) . unwrap ( ) ;
143
- writeln ! ( data, r#"#[panic_handler]"# ) . unwrap ( ) ;
144
- writeln ! (
145
- data,
146
- r#"fn panic_handler(i: &::core::panic::PanicInfo) -> ! {{"#
147
- )
148
- . unwrap ( ) ;
149
- writeln ! ( data, r#" let l = i.location().unwrap();"# ) . unwrap ( ) ;
150
- writeln ! ( data) . unwrap ( ) ;
151
- writeln ! (
152
- data,
153
- r#" ::zfi::println!("zfi:panic:{{}}:{{}}:{{}}", l.file(), l.line(), l.column());"#
154
- )
155
- . unwrap ( ) ;
156
- writeln ! ( data) . unwrap ( ) ;
157
- writeln ! (
158
- data,
159
- r#" if let Some(&p) = i.payload().downcast_ref::<&str>() {{"#
160
- )
161
- . unwrap ( ) ;
162
- writeln ! ( data, r#" ::zfi::println!("{{p}}");"# ) . unwrap ( ) ;
163
- writeln ! (
164
- data,
165
- r#" }} else if let Some(p) = i.payload().downcast_ref::<::alloc::string::String>() {{"#
166
- )
167
- . unwrap ( ) ;
168
- writeln ! ( data, r#" ::zfi::println!("{{p}}");"# ) . unwrap ( ) ;
169
- writeln ! ( data, r#" }} else {{"# ) . unwrap ( ) ;
170
- writeln ! ( data, r#" ::zfi::println!("{{i}}");"# ) . unwrap ( ) ;
171
- writeln ! ( data, r#" }}"# ) . unwrap ( ) ;
172
- writeln ! ( data) . unwrap ( ) ;
173
- writeln ! ( data, r#" ::zfi::println!("zfi:end");"# ) . unwrap ( ) ;
174
- writeln ! ( data) . unwrap ( ) ;
175
- writeln ! ( data, r#" loop {{}}"# ) . unwrap ( ) ;
176
- writeln ! ( data, r#"}}"# ) . unwrap ( ) ;
177
-
178
- // Write src/main.rs.
179
- path. push ( "main.rs" ) ;
180
-
181
- std:: fs:: write ( & path, data) . unwrap ( ) ;
182
-
183
- Ok ( ( ) )
184
- }
185
-
186
- #[ derive( Serialize , Deserialize ) ]
187
- struct Cargo {
188
- package : Option < Package > ,
189
- dependencies : HashMap < String , Dependency > ,
28
+ // Generate a test project.
29
+ let name = item. sig . ident . to_string ( ) ;
30
+ let body = item. block . brace_token . span . join ( ) . source_text ( ) . unwrap ( ) ;
190
31
191
- #[ serde( rename = "dev-dependencies" ) ]
192
- dev_dependencies : HashMap < String , Dependency > ,
193
- }
32
+ // Construct a new body.
33
+ item. block = Box :: new ( parse_quote ! ( {
34
+ let proj = std:: path:: PathBuf :: from( #proj) ;
35
+ let dest = std:: path:: PathBuf :: from( env!( "CARGO_TARGET_TMPDIR" ) ) ;
36
+ let root = :: zfi_testing:: gen_qemu_test( proj, dest, #name, #body) ;
194
37
195
- #[ derive( Serialize , Deserialize ) ]
196
- struct Package {
197
- name : String ,
198
- }
38
+ :: zfi_testing:: run_qemu_test( root) ;
39
+ } ) ) ;
199
40
200
- #[ derive( Serialize , Deserialize ) ]
201
- #[ serde( untagged) ]
202
- enum Dependency {
203
- Simple ( String ) ,
204
- Complex {
205
- version : Option < String > ,
206
- path : Option < String > ,
207
- } ,
41
+ Ok ( item. into_token_stream ( ) )
208
42
}
0 commit comments