Skip to content

Commit 5afd72a

Browse files
authored
Remove panics from xml writing (#1075)
1 parent 589df63 commit 5afd72a

File tree

34 files changed

+253
-179
lines changed

34 files changed

+253
-179
lines changed

bazelfe-bazel-wrapper/src/bazel_command_line_parser/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ pub fn parse_bazel_command_line(
329329
if cur_options.is_empty() {
330330
break 'outer;
331331
} else {
332-
action_options.extend(cur_options.into_iter());
332+
action_options.extend(cur_options);
333333
}
334334
}
335335
action_args.extend(command_line_iter.cloned());

bazelfe-bazel-wrapper/src/bazel_subprocess_wrapper/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ async fn execute_tokio_subprocess(
148148
break;
149149
}
150150
if show_output {
151-
if let Err(_) = stdout.write_all(&buffer[0..bytes_read]).await {
151+
if stdout.write_all(&buffer[0..bytes_read]).await.is_err() {
152152
break;
153153
}
154154
}
@@ -165,7 +165,7 @@ async fn execute_tokio_subprocess(
165165
break;
166166
}
167167
if show_output {
168-
if let Err(_) = stderr.write_all(&buffer[0..bytes_read]).await {
168+
if stderr.write_all(&buffer[0..bytes_read]).await.is_err() {
169169
break;
170170
}
171171
}

bazelfe-bazel-wrapper/src/bep/build_events/build_event_server.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,12 @@ pub mod bazel_event {
9191

9292
let aborted: Option<Evt> = {
9393
let abort_info = v.payload.as_ref().and_then(|e| match e {
94-
build_event_stream::build_event::Payload::Aborted(cfg) => Some((
95-
build_event_stream::aborted::AbortReason::from_i32(cfg.reason),
96-
cfg.description.clone(),
97-
)),
94+
build_event_stream::build_event::Payload::Aborted(cfg) => Some(
95+
match build_event_stream::aborted::AbortReason::try_from(cfg.reason) {
96+
Ok(ar) => (Some(ar), cfg.description.clone()),
97+
Err(_) => (None, cfg.description.clone()),
98+
},
99+
),
98100
_ => None,
99101
});
100102
let target_label_opt = v.id.as_ref().and_then(|e| e.id.as_ref()).and_then(label_of);
@@ -449,7 +451,7 @@ where
449451
let sequence_number = build_event.sequence_number;
450452
yield PublishBuildToolEventStreamResponse {
451453
stream_id: build_event.stream_id.clone(),
452-
sequence_number: sequence_number
454+
sequence_number
453455
};
454456

455457
}

bazelfe-bazel-wrapper/src/bep/build_events/hydrated_stream.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use super::build_event_server::BuildEventAction;
1313
use bazelfe_protos::build_event_stream::NamedSetOfFiles;
1414
use bazelfe_protos::*;
1515
use std::path::PathBuf;
16-
use std::pin::pin;
1716

1817
pub trait HasFiles {
1918
fn files(&self) -> Vec<build_event_stream::File>;
@@ -324,6 +323,24 @@ impl HydratedInfo {
324323
});
325324
next_rx
326325
}
326+
327+
pub fn label(&self) -> Option<&str> {
328+
match self {
329+
HydratedInfo::BazelAbort(ba) =>
330+
// this is a dance to return the ref
331+
{
332+
match &ba.label {
333+
Some(s) => Some(s.as_str()),
334+
None => None,
335+
}
336+
}
337+
HydratedInfo::ActionFailed(af) => Some(af.label.as_str()),
338+
HydratedInfo::Progress(_) => None,
339+
HydratedInfo::TestResult(tri) => Some(tri.test_summary_event.label.as_str()),
340+
HydratedInfo::ActionSuccess(asucc) => Some(asucc.label.as_str()),
341+
HydratedInfo::TargetComplete(tc) => Some(tc.label.as_str()),
342+
}
343+
}
327344
}
328345

329346
#[cfg(test)]
@@ -334,7 +351,7 @@ mod tests {
334351
#[tokio::test]
335352
async fn test_no_history() {
336353
let (tx, rx) = async_channel::unbounded();
337-
let mut child_rx = pin!(HydratedInfo::build_transformer(rx));
354+
let mut child_rx = std::pin::pin!(HydratedInfo::build_transformer(rx));
338355

339356
tx.send(BuildEventAction::BuildEvent(bazel_event::BazelBuildEvent {
340357
event: bazel_event::Evt::ActionCompleted(bazel_event::ActionCompletedEvt {
@@ -363,7 +380,7 @@ mod tests {
363380
#[tokio::test]
364381
async fn test_with_files() {
365382
let (tx, rx) = async_channel::unbounded();
366-
let mut child_rx = pin!(HydratedInfo::build_transformer(rx));
383+
let mut child_rx = std::pin::pin!(HydratedInfo::build_transformer(rx));
367384

368385
tx.send(BuildEventAction::BuildEvent(bazel_event::BazelBuildEvent {
369386
event: bazel_event::Evt::ActionCompleted(bazel_event::ActionCompletedEvt {
@@ -413,7 +430,7 @@ mod tests {
413430
#[tokio::test]
414431
async fn test_with_history() {
415432
let (tx, rx) = async_channel::unbounded();
416-
let mut child_rx = pin!(HydratedInfo::build_transformer(rx));
433+
let mut child_rx = std::pin::pin!(HydratedInfo::build_transformer(rx));
417434

418435
tx.send(BuildEventAction::BuildEvent(bazel_event::BazelBuildEvent {
419436
event: bazel_event::Evt::TargetConfigured(bazel_event::TargetConfiguredEvt {
@@ -472,7 +489,7 @@ mod tests {
472489
#[tokio::test]
473490
async fn state_resets_on_new_build() {
474491
let (tx, rx) = async_channel::unbounded();
475-
let mut child_rx = pin!(HydratedInfo::build_transformer(rx));
492+
let mut child_rx = std::pin::pin!(HydratedInfo::build_transformer(rx));
476493

477494
tx.send(BuildEventAction::BuildEvent(bazel_event::BazelBuildEvent {
478495
event: bazel_event::Evt::TargetConfigured(bazel_event::TargetConfiguredEvt {

bazelfe-bazel-wrapper/src/bep/target_completed_tracker/mod.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,10 @@ impl<T> super::BazelEventHandler<T> for TargetCompletedTracker {
1616
_bazel_run_id: usize,
1717
event: &hydrated_stream::HydratedInfo,
1818
) -> Vec<T> {
19-
match event {
20-
hydrated_stream::HydratedInfo::TargetComplete(tce) => {
21-
let mut guard = self.expected_targets.lock().await;
22-
guard.remove(&tce.label);
23-
}
24-
_ => (),
25-
};
19+
if let hydrated_stream::HydratedInfo::TargetComplete(tce) = event {
20+
let mut guard = self.expected_targets.lock().await;
21+
guard.remove(&tce.label);
22+
}
2623
Vec::default()
2724
}
2825
}

bazelfe-core/src/bazel_runner/bazel_runner_inst.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl BazelRunner {
7070
if let Some(bazel_command_line_parser::Action::Custom(cust_str)) =
7171
self.bazel_command_line.action.as_ref()
7272
{
73-
if CustomAction::AutoTest == parse_custom_action(&cust_str)? {
73+
if CustomAction::AutoTest == parse_custom_action(cust_str)? {
7474
self.config.daemon_config.enabled = true;
7575
}
7676
}

bazelfe-core/src/bazel_runner/processor_activity.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::collections::HashMap;
22

33
use crate::hydrated_stream_processors::process_bazel_failures::{TargetStory, TargetStoryAction};
44

5+
#[derive(Default)]
56
pub struct ProcessorActivity {
67
pub jvm_segments_indexed: u32,
78
pub actions_taken: u32,
@@ -63,12 +64,3 @@ impl ProcessorActivity {
6364
self.actions_taken += o.actions_taken;
6465
}
6566
}
66-
impl Default for ProcessorActivity {
67-
fn default() -> Self {
68-
ProcessorActivity {
69-
jvm_segments_indexed: 0,
70-
actions_taken: 0,
71-
target_story_actions: HashMap::new(),
72-
}
73-
}
74-
}

bazelfe-core/src/bazel_runner/test_file_to_target/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub async fn run<B: BazelQuery>(
5858
};
5959

6060
let query_for_target = bazel_query
61-
.execute(&vec![
61+
.execute(&[
6262
String::from("query"),
6363
format!(
6464
"rdeps(//{}/..., {},1)",

bazelfe-core/src/bep_junit/bep_junit_app.rs

+96-42
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use bazelfe_bazel_wrapper::bep::build_events::build_event_server::BuildEventAction;
22
use bazelfe_core::bep_junit::{
33
emit_backup_error_data, emit_junit_xml_from_aborted_action, emit_junit_xml_from_failed_action,
4-
label_to_junit_relative_path, suites_with_error_from_xml,
4+
label_to_junit_relative_path,
55
};
66

77
use bazelfe_bazel_wrapper::bep::build_events::hydrated_stream::{HydratedInfo, HydratorState};
@@ -10,6 +10,7 @@ use clap::Parser;
1010
use prost::Message;
1111
use std::collections::VecDeque;
1212
use std::error::Error;
13+
use std::os::unix::fs::MetadataExt;
1314
use std::path::{Path, PathBuf};
1415

1516
#[derive(Parser, Debug)]
@@ -77,19 +78,26 @@ async fn main() -> Result<(), Box<dyn Error>> {
7778
let mut failed_actions = Vec::default();
7879
let mut aborted_actions = Vec::default();
7980
let mut failed_tests = Vec::default();
81+
let mut failed_xml_writes = Vec::default();
8082
for build_event in hydrated_infos.into_iter() {
81-
match build_event {
83+
match &build_event {
8284
HydratedInfo::BazelAbort(abort_info) => {
83-
emit_junit_xml_from_aborted_action(
85+
aborted_actions.push(abort_info.label.clone());
86+
match emit_junit_xml_from_aborted_action(
8487
&abort_info,
8588
aborted_actions.len(),
8689
&opt.junit_output_path,
87-
);
88-
aborted_actions.push(abort_info.label);
90+
) {
91+
Ok(_) => (),
92+
Err(e) => failed_xml_writes.push((build_event, e)),
93+
}
8994
}
9095
HydratedInfo::ActionFailed(action_failed) => {
91-
emit_junit_xml_from_failed_action(&action_failed, &opt.junit_output_path);
92-
failed_actions.push(action_failed.label);
96+
failed_actions.push(action_failed.label.clone());
97+
match emit_junit_xml_from_failed_action(action_failed, &opt.junit_output_path) {
98+
Ok(_) => (),
99+
Err(e) => failed_xml_writes.push((build_event, e)),
100+
}
93101
}
94102
HydratedInfo::TestResult(r) => {
95103
let is_failure = r.test_summary_event.test_status.didnt_pass();
@@ -99,35 +107,60 @@ async fn main() -> Result<(), Box<dyn Error>> {
99107
let output_folder = opt.junit_output_path.join(label_to_junit_relative_path(
100108
r.test_summary_event.label.as_str(),
101109
));
102-
std::fs::create_dir_all(&output_folder).expect("Make dir failed");
103-
104-
let files: Vec<&str> = r
105-
.test_summary_event
106-
.output_files
107-
.iter()
108-
.flat_map(|e| match e {
109-
bazelfe_protos::build_event_stream::file::File::Uri(uri) => {
110-
let p = uri
111-
.strip_prefix("file://")
112-
.unwrap_or_else(|| panic!("Wasn't a local file for {}", uri));
113-
if p.ends_with("/test.xml") {
114-
Some(p)
115-
} else {
116-
None
110+
111+
match std::fs::create_dir_all(&output_folder) {
112+
Ok(_) => {
113+
let files: Vec<&str> = r
114+
.test_summary_event
115+
.output_files
116+
.iter()
117+
.flat_map(|e| match e {
118+
bazelfe_protos::build_event_stream::file::File::Uri(uri) => {
119+
let p = uri.strip_prefix("file://").unwrap_or_else(|| {
120+
panic!("Wasn't a local file for {}", uri)
121+
});
122+
if p.ends_with("/test.xml") {
123+
Some(p)
124+
} else {
125+
None
126+
}
127+
}
128+
bazelfe_protos::build_event_stream::file::File::Contents(_) => None,
129+
})
130+
.collect();
131+
132+
for (idx, f) in files.into_iter().enumerate() {
133+
match std::fs::metadata(f) {
134+
Ok(m) => {
135+
if m.size() > 0 {
136+
let output_file = output_folder.join(format!("test.{}.xml", idx));
137+
match std::fs::copy(f, output_file) {
138+
Ok(_) => (),
139+
Err(e) =>
140+
println!("could not access metadata for test result {} at file {}.\nError {}",
141+
r.test_summary_event.label,
142+
f,
143+
e)
144+
}
117145
}
146+
}
147+
Err(e) =>
148+
println!("could not access metadata for test result {} at file {}.\nError {}",
149+
r.test_summary_event.label,
150+
f,
151+
e)
118152
}
119-
bazelfe_protos::build_event_stream::file::File::Contents(_) => None,
120-
})
121-
.collect();
122-
123-
if is_failure {
124-
// Some failures don't get to the phase of writing junit output
125-
// this ensures we write something
126-
emit_backup_error_data(&r, &opt.junit_output_path);
127-
}
128-
for (idx, f) in files.into_iter().enumerate() {
129-
let output_file = output_folder.join(format!("test.{}.xml", idx));
130-
std::fs::copy(f, output_file).unwrap();
153+
}
154+
if is_failure {
155+
// Some failures don't get to the phase of writing junit output
156+
// this ensures we write something
157+
match emit_backup_error_data(&r, &opt.junit_output_path) {
158+
Ok(_) => (),
159+
Err(err) => failed_xml_writes.push((build_event, err)),
160+
}
161+
}
162+
}
163+
Err(e) => failed_xml_writes.push((build_event, e.into())),
131164
}
132165
}
133166
HydratedInfo::Progress(_) => (),
@@ -136,32 +169,53 @@ async fn main() -> Result<(), Box<dyn Error>> {
136169
}
137170
}
138171

139-
if failed_actions.is_empty() && failed_tests.is_empty() && aborted_actions.is_empty() {
140-
println!("Have zero failures, all successful.")
172+
if failed_actions.is_empty()
173+
&& failed_tests.is_empty()
174+
&& aborted_actions.is_empty()
175+
&& failed_xml_writes.is_empty()
176+
{
177+
println!("Have zero failures, all successful.");
178+
Ok(())
141179
} else {
142180
if !failed_actions.is_empty() {
143181
println!("Have {} failed actions", failed_actions.len());
144-
for a in failed_actions.iter() {
182+
for a in failed_actions {
145183
println!(" - {}", a);
146184
}
147185
}
148186

149187
if !failed_tests.is_empty() {
150188
println!("Have {} failed tests", failed_tests.len());
151-
for a in failed_tests.iter() {
189+
failed_tests.sort();
190+
for a in failed_tests {
152191
println!(" - {}", a);
153192
}
154193
}
155194

156195
if !aborted_actions.is_empty() {
157196
println!("Have {} aborted actions", aborted_actions.len());
158-
for a in aborted_actions.iter() {
197+
aborted_actions.sort();
198+
for a in aborted_actions {
199+
println!(" - {}", a.unwrap_or_else(|| "Unknown".to_string()));
200+
}
201+
}
202+
203+
if !failed_xml_writes.is_empty() {
204+
println!("Got {} xml write failures", failed_xml_writes.len());
205+
failed_xml_writes.sort_by(|p1, p2| p1.0.label().cmp(&p2.0.label()));
206+
for (r, err) in failed_xml_writes {
159207
println!(
160-
" - {}",
161-
a.to_owned().unwrap_or_else(|| "Unknown".to_string())
208+
"Target label = {} failed to write: {}",
209+
r.label().unwrap_or("<unknown>"),
210+
err
162211
);
163212
}
164213
}
214+
215+
let err: Box<dyn Error> = Box::new(std::io::Error::new(
216+
std::io::ErrorKind::Other,
217+
"non-zero error count.",
218+
));
219+
Err(err)
165220
}
166-
Ok(())
167221
}

0 commit comments

Comments
 (0)