@@ -10,11 +10,13 @@ use super::{
1010 Analyzer ,
1111 LineType ,
1212 Stats ,
13+ standard:: StandardAnalyzer ,
1314} ;
1415
1516#[ derive( Debug , Default ) ]
1617pub struct NextestJSONAnalyzer {
1718 lines : Vec < CommandOutputLine > ,
19+ standard_analyzer : StandardAnalyzer ,
1820}
1921
2022impl Analyzer for NextestJSONAnalyzer {
@@ -31,7 +33,10 @@ impl Analyzer for NextestJSONAnalyzer {
3133 command_output : & mut crate :: CommandOutput ,
3234 ) {
3335 match line. origin {
34- CommandStream :: StdErr => command_output. push ( line) ,
36+ // In JSON mode, stderr output is human readable
37+ CommandStream :: StdErr => self . standard_analyzer . receive_line ( line, command_output) ,
38+
39+ // The JSON payloads come on stdout
3540 CommandStream :: StdOut => self . lines . push ( line) ,
3641 }
3742 }
@@ -44,7 +49,8 @@ impl Analyzer for NextestJSONAnalyzer {
4449 output : CommandOutput :: default ( ) ,
4550 failure_keys : Vec :: default ( ) ,
4651 } ;
47- let mut fail_idx = 0 ;
52+
53+ let mut item_idx = 0 ;
4854 for line in & self . lines {
4955 let line: OutputLine = serde_json:: from_str ( & line. content . to_raw ( ) ) ?;
5056 match line {
@@ -67,31 +73,37 @@ impl Analyzer for NextestJSONAnalyzer {
6773 TestEvent :: Started => ( ) ,
6874 TestEvent :: Ok { name : _ } => ( ) ,
6975 TestEvent :: Failed { name, stdout } => {
76+ let name = cleanup_name ( & name) ;
7077 report. lines . push ( crate :: Line {
71- item_idx : fail_idx ,
72- line_type : LineType :: TestResult ( false ) ,
78+ item_idx,
79+ line_type : LineType :: Title ( super :: Kind :: Error ) ,
7380 content : TLine :: failed ( & name) ,
7481 } ) ;
75- report. lines . push ( crate :: Line {
76- item_idx : fail_idx,
77- line_type : LineType :: Normal ,
78- content : TLine :: from_raw ( stdout) ,
79- } ) ;
82+ for outline in stdout. lines ( ) {
83+ report. lines . push ( crate :: Line {
84+ item_idx,
85+ line_type : LineType :: Normal ,
86+ content : TLine :: from_raw ( outline. to_owned ( ) ) ,
87+ } ) ;
88+ }
8089 report. failure_keys . push ( name) ;
81- fail_idx += 1 ;
90+ item_idx += 1 ;
8291 }
8392 } ,
8493 }
8594 }
86- report. lines . push ( crate :: Line {
87- item_idx : fail_idx,
88- line_type : LineType :: Normal ,
89- content : TLine :: default ( ) ,
90- } ) ;
9195 Ok ( report)
9296 }
9397}
9498
99+ fn cleanup_name ( name : & str ) -> String {
100+ if let Some ( idx) = name. chars ( ) . position ( |ch| ch == '$' ) {
101+ name. chars ( ) . skip ( idx + 1 ) . collect ( )
102+ } else {
103+ name. to_owned ( )
104+ }
105+ }
106+
95107#[ derive( Debug , serde:: Deserialize , serde:: Serialize , PartialEq ) ]
96108#[ serde( rename_all = "lowercase" ) ]
97109#[ serde( tag = "event" ) ]
@@ -140,84 +152,93 @@ enum OutputLine {
140152 } ,
141153}
142154
143- #[ test]
144- fn test_parse ( ) {
145- let suite_started = r#"{"type":"suite","event":"started","test_count":7}"# ;
146- assert_eq ! (
147- serde_json:: from_str:: <OutputLine >( suite_started) . unwrap( ) ,
148- OutputLine :: Suite {
149- event: SuiteEvent :: Started { test_count: 7 }
150- }
151- ) ;
152-
153- let suite_failed = r#"{"type":"suite","event":"failed","passed":6,"failed":1,"ignored":0,"measured":0,"filtered_out":0,"exec_time":0.015213355}"# ;
154- assert_eq ! (
155- serde_json:: from_str:: <OutputLine >( suite_failed) . unwrap( ) ,
156- OutputLine :: Suite {
157- event: SuiteEvent :: Failed {
158- passed: 6 ,
159- failed: 1 ,
160- ignored: 0 ,
161- measured: 0 ,
162- filtered_out: 0 ,
163- exec_time: 0.015213355
155+ #[ cfg( test) ]
156+ mod test {
157+ use super :: {
158+ OutputLine ,
159+ SuiteEvent ,
160+ TestEvent ,
161+ } ;
162+
163+ #[ test]
164+ fn parse ( ) {
165+ let suite_started = r#"{"type":"suite","event":"started","test_count":7}"# ;
166+ assert_eq ! (
167+ serde_json:: from_str:: <OutputLine >( suite_started) . unwrap( ) ,
168+ OutputLine :: Suite {
169+ event: SuiteEvent :: Started { test_count: 7 }
164170 }
165- }
166- ) ;
167-
168- let suite_ok = r#"{"type":"suite","event":"ok","passed":13,"failed":0,"ignored":0,"measured":0,"filtered_out":0,"exec_time":0.140588}"# ;
169-
170- assert_eq ! (
171- serde_json:: from_str:: <OutputLine >( suite_ok) . unwrap( ) ,
172- OutputLine :: Suite {
173- event: SuiteEvent :: Ok {
174- passed: 13 ,
175- failed: 0 ,
176- ignored: 0 ,
177- measured: 0 ,
178- filtered_out: 0 ,
179- exec_time: 0.140588
171+ ) ;
172+
173+ let suite_failed = r#"{"type":"suite","event":"failed","passed":6,"failed":1,"ignored":0,"measured":0,"filtered_out":0,"exec_time":0.015213355}"# ;
174+ assert_eq ! (
175+ serde_json:: from_str:: <OutputLine >( suite_failed) . unwrap( ) ,
176+ OutputLine :: Suite {
177+ event: SuiteEvent :: Failed {
178+ passed: 6 ,
179+ failed: 1 ,
180+ ignored: 0 ,
181+ measured: 0 ,
182+ filtered_out: 0 ,
183+ exec_time: 0.015213355
184+ }
180185 }
181- }
182- ) ;
183-
184- let test_started =
185- r#"{"type":"test","event":"started","name":"llm::llm$parser::test::number"}"# ;
186- assert_eq ! (
187- serde_json:: from_str:: <OutputLine >( test_started) . unwrap( ) ,
188- OutputLine :: Test {
189- event: TestEvent :: Started { }
190- }
191- ) ;
186+ ) ;
187+
188+ let suite_ok = r#"{"type":"suite","event":"ok","passed":13,"failed":0,"ignored":0,"measured":0,"filtered_out":0,"exec_time":0.140588}"# ;
189+
190+ assert_eq ! (
191+ serde_json:: from_str:: <OutputLine >( suite_ok) . unwrap( ) ,
192+ OutputLine :: Suite {
193+ event: SuiteEvent :: Ok {
194+ passed: 13 ,
195+ failed: 0 ,
196+ ignored: 0 ,
197+ measured: 0 ,
198+ filtered_out: 0 ,
199+ exec_time: 0.140588
200+ }
201+ }
202+ ) ;
203+
204+ let test_started =
205+ r#"{"type":"test","event":"started","name":"llm::llm$parser::test::number"}"# ;
206+ assert_eq ! (
207+ serde_json:: from_str:: <OutputLine >( test_started) . unwrap( ) ,
208+ OutputLine :: Test {
209+ event: TestEvent :: Started { }
210+ }
211+ ) ;
192212
193- let test_ok = r#"{"type":"test","event":"ok","name":"llm::llm$parser::test::identifier","exec_time":0.002138244}"# ;
213+ let test_ok = r#"{"type":"test","event":"ok","name":"llm::llm$parser::test::identifier","exec_time":0.002138244}"# ;
194214
195- assert_eq ! (
196- serde_json:: from_str:: <OutputLine >( test_ok) . unwrap( ) ,
197- OutputLine :: Test {
198- event: TestEvent :: Ok {
199- name: "llm::llm$parser::test::identifier" . to_owned( ) ,
215+ assert_eq ! (
216+ serde_json:: from_str:: <OutputLine >( test_ok) . unwrap( ) ,
217+ OutputLine :: Test {
218+ event: TestEvent :: Ok {
219+ name: "llm::llm$parser::test::identifier" . to_owned( ) ,
220+ }
200221 }
201- }
202- ) ;
203-
204- let test_fail = r#" {"type":"test","event":"failed","name":"llm::llm$parser::test::var","exec_time":0.002140747,"stdout":"thread 'parser::test::var' panicked at src"}"# ;
205- assert_eq ! (
206- serde_json :: from_str :: < OutputLine > ( test_fail ) . unwrap ( ) ,
207- OutputLine :: Test {
208- event : TestEvent :: Failed {
209- name : "llm::llm$ parser::test::var" . to_owned ( ) ,
210- stdout : "thread 'parser::test::var' panicked at src" . to_string ( ) ,
222+ ) ;
223+
224+ let test_fail = r#" {"type":"test","event":"failed","name":"llm::llm$parser::test::var","exec_time":0.002140747,"stdout":"thread 'parser::test::var' panicked at src"}"# ;
225+ assert_eq ! (
226+ serde_json :: from_str :: < OutputLine > ( test_fail ) . unwrap ( ) ,
227+ OutputLine :: Test {
228+ event : TestEvent :: Failed {
229+ name : "llm::llm$parser::test::var" . to_owned ( ) ,
230+ stdout : "thread ' parser::test::var' panicked at src" . to_string ( ) ,
231+ }
211232 }
212- }
213- ) ;
214- }
233+ ) ;
234+ }
215235
216- #[ test]
217- fn test_fail ( ) {
218- assert ! ( false ) ;
236+ #[ test]
237+ fn cleanup_name ( ) {
238+ let name = "bacon::bacon$analysis::nextest_json::test_fail" ;
239+ assert_eq ! (
240+ super :: cleanup_name( name) ,
241+ "analysis::nextest_json::test_fail" . to_owned( )
242+ ) ;
243+ }
219244}
220-
221- /*
222- * NEXTEST_EXPERIMENTAL_LIBTEST_JSON=1 cargo nextest run --message-format libtest-json --failure-output final --hide-progress-bar 2>/dev/null
223- */
0 commit comments