diff --git a/crates/abq_cli/src/report.rs b/crates/abq_cli/src/report.rs index 6b81724d..91b9dc6a 100644 --- a/crates/abq_cli/src/report.rs +++ b/crates/abq_cli/src/report.rs @@ -181,6 +181,7 @@ fn process_results( let completed_summary = &CompletedSummary { native_runner_info: Some(native_runner_info), + other_error_messages: vec![], }; for reporter in reporters { diff --git a/crates/abq_cli/src/reporting.rs b/crates/abq_cli/src/reporting.rs index a436999a..92a84f20 100644 --- a/crates/abq_cli/src/reporting.rs +++ b/crates/abq_cli/src/reporting.rs @@ -229,7 +229,7 @@ impl Reporter for RwxV1JsonReporter { .map(|runner| &runner.specification); self.collector - .write_json(fd, opt_specification) + .write_json(fd, opt_specification, summary.other_error_messages.clone()) .map_err(|_| ReportingError::FailedToFormat)?; Ok(()) diff --git a/crates/abq_cli/src/workers.rs b/crates/abq_cli/src/workers.rs index ee0eeee8..016c6909 100644 --- a/crates/abq_cli/src/workers.rs +++ b/crates/abq_cli/src/workers.rs @@ -152,7 +152,7 @@ async fn do_shutdown( .. } = worker_pool.shutdown().await; - tracing::debug!("Workers shutdown"); + tracing::debug!(?status, "Workers shutdown"); let finalized_reporters = reporting_handle.join().await; @@ -174,7 +174,11 @@ async fn do_shutdown( } let native_runner_info = native_runner_info.clone(); - let completed_summary = CompletedSummary { native_runner_info }; + let other_error_messages = status.error_messages().cloned().unwrap_or_default(); + let completed_summary = CompletedSummary { + native_runner_info, + other_error_messages, + }; let (suite_result, errors) = finalized_reporters.finish(&completed_summary); diff --git a/crates/abq_cli/tests/cli.rs b/crates/abq_cli/tests/cli.rs index 448b3da5..c461de5a 100644 --- a/crates/abq_cli/tests/cli.rs +++ b/crates/abq_cli/tests/cli.rs @@ -4717,11 +4717,17 @@ fn warn_on_different_runner_command() { args }; - let instance1 = Abq::new(format!("{name}_inst1")).args(test_args(0)).run(); + let instance1 = Abq::new(format!("{name}_inst1")) + .args(test_args(0)) + .always_capture_stderr(true) + .run(); assert!(instance1.exit_status.success()); - let instance2 = Abq::new(format!("{name}_inst2")).args(test_args(1)).run(); + let instance2 = Abq::new(format!("{name}_inst2")) + .args(test_args(1)) + .always_capture_stderr(true) + .run(); assert!(instance2.exit_status.success()); @@ -4735,3 +4741,169 @@ fn warn_on_different_runner_command() { term(queue_proc); } + +#[test] +#[with_protocol_version] +#[serial] +fn write_partial_rwx_v1_json_results_on_early_runner_termination() { + let name = "warn_on_different_runner_command"; + let conf = CSConfigOptions { + use_auth_token: true, + tls: true, + }; + + let (_queue_proc, queue_addr) = setup_queue!(name, conf); + + let proto = AbqProtocolVersion::V0_2.get_supported_witness().unwrap(); + + let manifest = vec![ + TestOrGroup::test(Test::new( + proto, + "test1".to_string(), + [], + Default::default(), + )), + TestOrGroup::test(Test::new( + proto, + "test2".to_string(), + [], + Default::default(), + )), + ]; + + let manifest = ManifestMessage::new(Manifest::new(manifest, Default::default())); + + let simulation = [ + Connect, + // + // Write spawn message + OpaqueWrite(pack(legal_spawned_message(proto))), + // + // Write the manifest if we need to. + // Otherwise handle the one test. + IfGenerateManifest { + then_do: vec![OpaqueWrite(pack(&manifest))], + else_do: vec![ + // + // Read init context message + write ACK + OpaqueRead, + OpaqueWrite(pack(InitSuccessMessage::new(proto))), + // Read first test, write okay + OpaqueRead, + OpaqueWrite(pack(RawTestResultMessage::fake(proto))), + // Read second test, bail + OpaqueRead, + Exit(1), + ], + }, + // + // Finish + Exit(0), + ]; + + let packed = pack_msgs_to_disk(simulation); + let rwx_v1_json = tempfile::NamedTempFile::new().unwrap(); + + let test_args = { + let simulator = native_runner_simulation_bin(); + let simfile_path = packed.path.display().to_string(); + let rwx_v1_json_path = rwx_v1_json.path().display().to_string(); + let args = vec![ + format!("test"), + format!("--worker=0"), + format!("--queue-addr={queue_addr}"), + format!("--run-id=test-run-id"), + format!("--reporter=rwx-v1-json={rwx_v1_json_path}"), + ]; + let mut args = conf.extend_args_for_client(args); + args.extend([s!("--"), simulator, simfile_path]); + args + }; + + let CmdOutput { + stdout, + stderr, + exit_status, + } = Abq::new(format!("{name}_worker0")) + .args(test_args) + .always_capture_stderr(true) + .run(); + + assert!(!exit_status.success()); + assert_eq!(exit_status.code(), Some(ExitCode::ABQ_ERROR.get())); + + assert!( + stdout.contains("2 tests, 1 failures"), + "STDOUT:\n{stdout}\nSTDERR:\n{stderr}" + ); + assert!( + stderr.contains("ABQ had an error communicating with the native runner"), + "STDOUT:\n{stdout}\nSTDERR:\n{stderr}" + ); + + let rwx_v1_json = std::fs::read_to_string(rwx_v1_json.path()).unwrap(); + let rwx_v1_json: serde_json::Value = serde_json::from_str(&rwx_v1_json).unwrap(); + insta::assert_json_snapshot!(rwx_v1_json, { + }, @r###" + { + "$schema": "https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json", + "framework": { + "kind": "RSpec", + "language": "Ruby" + }, + "otherErrors": [ + { + "message": "ABQ had an error communicating with the native runner: early eof at crates/abq_runners/generic_test_runner/src/lib.rs@1035:87" + } + ], + "summary": { + "canceled": 0, + "failed": 0, + "otherErrors": 2, + "pended": 0, + "quarantined": 0, + "retries": 0, + "skipped": 0, + "status": { + "kind": "failed" + }, + "successful": 1, + "tests": 1, + "timedOut": 0, + "todo": 0 + }, + "tests": [ + { + "attempt": { + "durationInNanoseconds": 0, + "finishedAt": "1994-11-05T13:17:30Z", + "meta": { + "abq_metadata": { + "runner": 1, + "worker": 0 + } + }, + "startedAt": "1994-11-05T13:15:30Z", + "status": { + "kind": "successful" + }, + "stderr": "", + "stdout": "" + }, + "id": "zzz-faux", + "lineage": [ + "TopLevel", + "SubModule", + "Test" + ], + "location": { + "column": 15, + "file": "a/b/x.file", + "line": 10 + }, + "name": "zzz-faux" + } + ] + } + "###); +} diff --git a/crates/abq_reporting/src/lib.rs b/crates/abq_reporting/src/lib.rs index 5d7db58e..bc683306 100644 --- a/crates/abq_reporting/src/lib.rs +++ b/crates/abq_reporting/src/lib.rs @@ -16,6 +16,7 @@ pub struct CompletedSummary { /// The native test runner that was in use for this test run. /// Can be [None] if the returned worker never ran any tests. pub native_runner_info: Option, + pub other_error_messages: Vec, } #[derive(Debug, Error)] diff --git a/crates/abq_runners/generic_test_runner/src/lib.rs b/crates/abq_runners/generic_test_runner/src/lib.rs index b7c19be3..0fe366ec 100644 --- a/crates/abq_runners/generic_test_runner/src/lib.rs +++ b/crates/abq_runners/generic_test_runner/src/lib.rs @@ -89,8 +89,8 @@ impl RunnerConnection { } } -#[derive(Debug)] -pub struct NativeRunnerInfo { +#[derive(Debug, Clone)] +pub struct NativeRunnerConfiguration { protocol: ProtocolWitness, specification: NativeRunnerSpecification, } @@ -103,7 +103,7 @@ pub struct NativeRunnerInfo { pub async fn open_native_runner_connection( listener: &mut TcpListener, timeout: Duration, -) -> Result<(NativeRunnerInfo, RunnerConnection), GenericRunnerErrorKind> { +) -> Result<(NativeRunnerConfiguration, RunnerConnection), GenericRunnerErrorKind> { let start = Instant::now(); let ( NativeRunnerSpawnedMessage { @@ -134,7 +134,7 @@ pub async fn open_native_runner_connection( match protocol_version.get_supported_witness() { None => Err(ProtocolVersionError::NotCompatible.into()), Some(witness) => { - let runner_info = NativeRunnerInfo { + let runner_info = NativeRunnerConfiguration { protocol: witness, specification: runner_specification, }; @@ -148,6 +148,7 @@ macro_rules! try_setup { $err.located(here!()).map_err(|e| GenericRunnerError { error: e, output: StdioOutput::empty(), + native_runner_info: None, })? }; } @@ -177,12 +178,14 @@ async fn retrieve_manifest<'a>( return Err(GenericRunnerError { error, output: final_stdio_output.into(), + native_runner_info: Some(native_runner.get_native_runner_info()), }); } Err(error) => { return Err(GenericRunnerError { error, output: final_stdio_output.into(), + native_runner_info: Some(native_runner.get_native_runner_info()), }); } } @@ -227,7 +230,7 @@ pub enum GenericRunnerErrorKind { Io(#[from] io::Error), #[error("{0}")] ProtocolVersion(#[from] ProtocolVersionError), - #[error("{0}")] + #[error("ABQ had an error communicating with the native runner: {0}")] NativeRunner(#[from] NativeTestRunnerError), } @@ -235,6 +238,7 @@ pub enum GenericRunnerErrorKind { pub struct GenericRunnerError { pub error: LocatedError, pub output: StdioOutput, + pub native_runner_info: Option, } impl std::fmt::Display for GenericRunnerError { @@ -244,10 +248,14 @@ impl std::fmt::Display for GenericRunnerError { } impl GenericRunnerError { - pub fn no_captures(kind: LocatedError) -> Self { + pub fn no_captures( + kind: LocatedError, + native_runner_info: Option, + ) -> Self { Self { error: kind, output: StdioOutput::empty(), + native_runner_info, } } } @@ -348,7 +356,7 @@ struct NativeRunnerState { // Needed to keep the port alive. _tcp_listener: TcpListener, conn: RunnerConnection, - runner_info: NativeRunnerInfo, + runner_info: NativeRunnerConfiguration, runner_meta: RunnerMeta, for_manifest_generation: bool, } @@ -508,7 +516,11 @@ impl<'a> NativeRunnerHandle<'a> { protocol_version_timeout, ) .await; - return Err(GenericRunnerError { error, output }); + return Err(GenericRunnerError { + error, + output, + native_runner_info: None, + }); } }; @@ -665,10 +677,10 @@ impl<'a> NativeRunnerHandle<'a> { Ok(()) } - fn get_native_runner_info(self) -> queue::NativeRunnerInfo { + fn get_native_runner_info(&self) -> queue::NativeRunnerInfo { queue::NativeRunnerInfo { protocol_version: self.state.runner_info.protocol.get_version(), - specification: self.state.runner_info.specification, + specification: self.state.runner_info.specification.clone(), } } } @@ -858,6 +870,7 @@ async fn run_help( Err(err) => Err(GenericRunnerError { error: err, output: StdioOutput { stderr, stdout }, + native_runner_info: Some(native_runner_handle.get_native_runner_info()), }), } } @@ -899,7 +912,7 @@ async fn execute_all_tests<'a>( runner_meta: RunnerMeta, test_timeout: Duration, ) -> Result { - let NativeRunnerInfo { + let NativeRunnerConfiguration { protocol: _, specification: runner_spec, } = &native_runner_handle.runner_info; @@ -1531,6 +1544,7 @@ pub fn execute_wrapped_runner( return Err(GenericRunnerError { error: io::Error::new(io::ErrorKind::InvalidInput, error).located(here!()), output: StdioOutput::empty(), + native_runner_info: None, }); } diff --git a/crates/abq_runners/generic_test_runner/tests/simulation.rs b/crates/abq_runners/generic_test_runner/tests/simulation.rs index 004b2de5..62225f7c 100644 --- a/crates/abq_runners/generic_test_runner/tests/simulation.rs +++ b/crates/abq_runners/generic_test_runner/tests/simulation.rs @@ -633,7 +633,16 @@ fn native_runner_fails_while_executing_tests() { let (error, mut results, _notified_all_run) = run_simulated_runner_to_error(simulation, None, Box::new(get_next_tests)); - let GenericRunnerError { error: _, output } = error; + let GenericRunnerError { + error: _, + output, + native_runner_info, + } = error; + + assert!( + native_runner_info.is_some(), + "Native runner info should be defined because some tests ran" + ); check_bytes!(&output.stdout, b"I failed catastrophically"); check_bytes!( diff --git a/crates/abq_test_support/abq_reporting_test_utils/src/lib.rs b/crates/abq_test_support/abq_reporting_test_utils/src/lib.rs index 35b05a14..788457f1 100644 --- a/crates/abq_test_support/abq_reporting_test_utils/src/lib.rs +++ b/crates/abq_test_support/abq_reporting_test_utils/src/lib.rs @@ -53,6 +53,7 @@ pub fn mock_summary() -> CompletedSummary { host: "zmachine".to_owned(), }, }), + other_error_messages: vec![], } } diff --git a/crates/abq_workers/src/workers.rs b/crates/abq_workers/src/workers.rs index 30308666..e61c414f 100644 --- a/crates/abq_workers/src/workers.rs +++ b/crates/abq_workers/src/workers.rs @@ -110,6 +110,13 @@ pub enum WorkersExitStatus { impl WorkersExitStatus { pub const SUCCESS: Self = Self::Completed(ExitCode::SUCCESS); + + pub fn error_messages(&self) -> Option<&Vec> { + match self { + Self::Completed(_) => None, + Self::Error { errors } => Some(errors), + } + } } #[derive(Debug)] @@ -303,7 +310,10 @@ impl WorkerPool { Err(GenericRunnerError { error: kind, output, + native_runner_info: this_native_runner_info, }) => { + native_runner_info = native_runner_info.or(this_native_runner_info); + let LocatedError { error, location: Location { file, line, column }, @@ -538,6 +548,7 @@ async fn start_test_like_runner( return Err(GenericRunnerError::no_captures( io::Error::new(io::ErrorKind::Unsupported, "will not return manifest") .located(here!()), + None, )); } TestLikeRunner::ExitWith(ec) => { @@ -572,6 +583,7 @@ async fn start_test_like_runner( .await; return Err(GenericRunnerError::no_captures( GenericRunnerErrorKind::NativeRunner(oob.into()).located(here!()), + None, )); } }; @@ -649,7 +661,12 @@ async fn test_like_runner_exec_loop( 'tests_done: loop { let NextWorkBundle { work, eow } = match tests_fetcher.get_next_tests().await { Ok(bundle) => bundle, - Err(e) => return Some(Err(GenericRunnerError::no_captures(e.located(here!())))), + Err(e) => { + return Some(Err(GenericRunnerError::no_captures( + e.located(here!()), + None, + ))) + } }; for WorkerTest { @@ -661,6 +678,7 @@ async fn test_like_runner_exec_loop( return Some(Err(GenericRunnerError::no_captures( io::Error::new(io::ErrorKind::Unsupported, "will not return test") .located(here!()), + None, ))); } diff --git a/crates/reporters/rwx_v1_json/src/lib.rs b/crates/reporters/rwx_v1_json/src/lib.rs index 8238e564..cde077ea 100644 --- a/crates/reporters/rwx_v1_json/src/lib.rs +++ b/crates/reporters/rwx_v1_json/src/lib.rs @@ -4,7 +4,10 @@ use std::{collections::HashMap, io::Write, ops::Deref}; use abq_utils::net_protocol::{ entity::RunnerMeta, - runners::{self, NativeRunnerSpecification, Status, TestResult, TestResultSpec, TestRuntime}, + runners::{ + self, MetadataMap, NativeRunnerSpecification, Status, TestResult, TestResultSpec, + TestRuntime, + }, }; // Note: this is intentionally permissive right now for `kind` and `language` until we have @@ -159,6 +162,10 @@ impl Summary { self.status = SummaryStatus::Failed; } } + + fn account_other_errors(&mut self, len: u64) { + self.other_errors += len; + } } #[derive(Serialize, Deserialize, Clone)] @@ -418,6 +425,31 @@ impl From<&TestResult> for TestSketch { } } +#[derive(Serialize, Deserialize, Clone)] +struct OtherError { + #[serde(skip_serializing_if = "Option::is_none")] + location: Option, + #[serde(skip_serializing_if = "Option::is_none")] + meta: Option, + #[serde(skip_serializing_if = "Option::is_none")] + exception: Option, + message: String, + #[serde(skip_serializing_if = "Option::is_none")] + backtrace: Option>, +} + +impl OtherError { + fn from_message(message: String) -> Self { + Self { + location: None, + meta: None, + exception: None, + message, + backtrace: None, + } + } +} + // Note: this does not currently implement support for otherErrors nor derivedFrom // derivedFrom is not necessary for ABQ (it's not parsing original test results files) // otherErrors are not exposed to the reporters right now @@ -428,6 +460,8 @@ pub struct TestResults { framework: Framework, summary: Summary, tests: Vec, + #[serde(rename = "otherErrors")] + other_errors: Vec, } #[derive(Default, Clone)] @@ -492,25 +526,38 @@ impl Collector { self, writer: impl Write, runner_specification: Option<&NativeRunnerSpecification>, + other_error_messages: Vec, ) -> Result<(), String> { - serde_json::to_writer(writer, &self.test_results(runner_specification)) - .map_err(|e| e.to_string()) + serde_json::to_writer( + writer, + &self.test_results(runner_specification, other_error_messages), + ) + .map_err(|e| e.to_string()) } pub fn write_json_pretty( self, writer: impl Write, runner_specification: Option<&NativeRunnerSpecification>, + other_error_messages: Vec, ) -> Result<(), String> { - serde_json::to_writer_pretty(writer, &self.test_results(runner_specification)) - .map_err(|e| e.to_string()) + serde_json::to_writer_pretty( + writer, + &self.test_results(runner_specification, other_error_messages), + ) + .map_err(|e| e.to_string()) } - fn test_results(self, runner_specification: Option<&NativeRunnerSpecification>) -> TestResults { + fn test_results( + self, + runner_specification: Option<&NativeRunnerSpecification>, + other_error_messages: Vec, + ) -> TestResults { let mut summary = Summary::default(); self.tests.values().for_each(|test| summary.account(test)); summary.account_native_runner_errors(self.native_runner_errors); + summary.account_other_errors(other_error_messages.len() as _); let reified_schema_tests = if cfg!(test) { let mut ordered_tests: Vec = self.tests.into_values().map(Into::into).collect(); @@ -522,15 +569,14 @@ impl Collector { let framework = match runner_specification { Some(spec) => spec.into(), - None => { - assert!( - reified_schema_tests.is_empty(), - "runner specification may only be unknown if no tests were run on a node" - ); - Framework::other() - } + None => Framework::other(), }; + let other_errors = other_error_messages + .into_iter() + .map(OtherError::from_message) + .collect(); + TestResults { schema: "https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json" @@ -538,6 +584,7 @@ impl Collector { framework, summary, tests: reified_schema_tests, + other_errors, } } } @@ -632,7 +679,7 @@ mod test { let mut buf = vec![]; collector .clone() - .write_json(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); insta::assert_snapshot!("generates_rwx_v1_json_for_all_statuses__compact", json) @@ -642,7 +689,7 @@ mod test { let mut buf = vec![]; collector .clone() - .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); insta::assert_snapshot!("generates_rwx_v1_json_for_all_statuses__pretty", json) @@ -670,7 +717,7 @@ mod test { let mut buf = vec![]; collector .clone() - .write_json(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); insta::assert_snapshot!("generates_rwx_v1_json_for_successful_runs__compact", json) @@ -680,7 +727,7 @@ mod test { let mut buf = vec![]; collector .clone() - .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); insta::assert_snapshot!("generates_rwx_v1_json_for_successful_runs__pretty", json) @@ -735,7 +782,7 @@ mod test { let mut buf = vec![]; collector - .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); @@ -787,7 +834,7 @@ mod test { let mut buf = vec![]; collector - .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); @@ -848,7 +895,7 @@ mod test { let mut buf = vec![]; collector - .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); @@ -864,7 +911,7 @@ mod test { let mut buf = vec![]; collector - .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake())) + .write_json_pretty(&mut buf, Some(&NativeRunnerSpecification::fake()), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); @@ -887,7 +934,7 @@ mod test { let mut buf = vec![]; collector - .write_json_pretty(&mut buf, Some(&runner_spec)) + .write_json_pretty(&mut buf, Some(&runner_spec), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); insta::assert_snapshot!(json) @@ -909,9 +956,68 @@ mod test { let mut buf = vec![]; collector - .write_json_pretty(&mut buf, Some(&runner_spec)) + .write_json_pretty(&mut buf, Some(&runner_spec), vec![]) .expect("failed to write"); let json = String::from_utf8(buf).expect("not utf8 JSON"); insta::assert_snapshot!(json) } + + #[test] + fn generates_rwx_v1_json_with_unknown_framework_if_runner_info_is_missing() { + let mut collector = Collector::default(); + + collector.push_result(&TestResult::new( + RunnerMeta::fake(), + TestResultSpec { + status: Status::Failure { + exception: None, + backtrace: None, + }, + id: "id1".to_string(), + display_name: "app::module::test1".to_string(), + output: Some("I failed once".to_string()), + ..TestResultSpec::fake() + }, + )); + + let mut buf = vec![]; + collector + .write_json_pretty(&mut buf, None, vec![]) + .expect("failed to write"); + + let json = String::from_utf8(buf).expect("not utf8 JSON"); + insta::assert_snapshot!(json) + } + + #[test] + fn writes_passed_other_error_messages() { + let mut collector = Collector::default(); + + collector.push_result(&TestResult::new( + RunnerMeta::fake(), + TestResultSpec { + status: Status::Failure { + exception: None, + backtrace: None, + }, + id: "id1".to_string(), + display_name: "app::module::test1".to_string(), + output: Some("I failed once".to_string()), + ..TestResultSpec::fake() + }, + )); + + let other_errors = vec![ + "Something else weird happened during in test suite".to_owned(), + "Today, 1 = 2".to_owned(), + ]; + + let mut buf = vec![]; + collector + .write_json_pretty(&mut buf, None, other_errors) + .expect("failed to write"); + + let json = String::from_utf8(buf).expect("not utf8 JSON"); + insta::assert_snapshot!(json) + } } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__compact.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__compact.snap index 1789d1b7..7ae97016 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__compact.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__compact.snap @@ -2,4 +2,4 @@ source: crates/reporters/rwx_v1_json/src/lib.rs expression: json --- -{"$schema":"https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json","framework":{"kind":"other","language":"other","providedKind":"zframework","providedLanguage":"zlang"},"summary":{"status":{"kind":"failed"},"tests":5,"otherErrors":0,"retries":0,"canceled":0,"failed":2,"pended":1,"quarantined":0,"skipped":1,"successful":1,"timedOut":0,"todo":0},"tests":[{"id":"id1","name":"app::module::test1","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":11000000,"meta":{"abq_metadata":{"runner":1,"worker":3},"some":"value"},"status":{"kind":"successful"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id2","name":"app::module::test2","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":22000000,"meta":{"abq_metadata":{"runner":4,"worker":2}},"status":{"kind":"failed","exception":"test-exception","message":"Test 2 failed","backtrace":["file1.cpp:10","file2.cpp:20"]},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id3","name":"app::module::test3","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":33000000,"meta":{"abq_metadata":{"runner":8,"worker":1}},"status":{"kind":"failed"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id4","name":"app::module::test4","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":44000000,"meta":{"abq_metadata":{"runner":3,"worker":0}},"status":{"kind":"pended","message":"Test 4 pending"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id5","name":"app::module::test5","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":55000000,"meta":{"abq_metadata":{"runner":1,"worker":5}},"status":{"kind":"skipped"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}}]} +{"$schema":"https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json","framework":{"kind":"other","language":"other","providedKind":"zframework","providedLanguage":"zlang"},"summary":{"status":{"kind":"failed"},"tests":5,"otherErrors":0,"retries":0,"canceled":0,"failed":2,"pended":1,"quarantined":0,"skipped":1,"successful":1,"timedOut":0,"todo":0},"tests":[{"id":"id1","name":"app::module::test1","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":11000000,"meta":{"abq_metadata":{"runner":1,"worker":3},"some":"value"},"status":{"kind":"successful"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id2","name":"app::module::test2","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":22000000,"meta":{"abq_metadata":{"runner":4,"worker":2}},"status":{"kind":"failed","exception":"test-exception","message":"Test 2 failed","backtrace":["file1.cpp:10","file2.cpp:20"]},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id3","name":"app::module::test3","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":33000000,"meta":{"abq_metadata":{"runner":8,"worker":1}},"status":{"kind":"failed"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id4","name":"app::module::test4","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":44000000,"meta":{"abq_metadata":{"runner":3,"worker":0}},"status":{"kind":"pended","message":"Test 4 pending"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}},{"id":"id5","name":"app::module::test5","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":55000000,"meta":{"abq_metadata":{"runner":1,"worker":5}},"status":{"kind":"skipped"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}}],"otherErrors":[]} diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__pretty.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__pretty.snap index 5afc51ff..45e48dc4 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__pretty.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_all_statuses__pretty.snap @@ -185,5 +185,6 @@ expression: json "finishedAt": "1994-11-05T13:17:30Z" } } - ] + ], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__compact.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__compact.snap index 651b3369..0e913931 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__compact.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__compact.snap @@ -2,4 +2,4 @@ source: crates/reporters/rwx_v1_json/src/lib.rs expression: json --- -{"$schema":"https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json","framework":{"kind":"other","language":"other","providedKind":"zframework","providedLanguage":"zlang"},"summary":{"status":{"kind":"successful"},"tests":1,"otherErrors":0,"retries":0,"canceled":0,"failed":0,"pended":0,"quarantined":0,"skipped":0,"successful":1,"timedOut":0,"todo":0},"tests":[{"id":"id1","name":"app::module::test1","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":11000000,"meta":{"abq_metadata":{"runner":1,"worker":0}},"status":{"kind":"successful"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}}]} +{"$schema":"https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json","framework":{"kind":"other","language":"other","providedKind":"zframework","providedLanguage":"zlang"},"summary":{"status":{"kind":"successful"},"tests":1,"otherErrors":0,"retries":0,"canceled":0,"failed":0,"pended":0,"quarantined":0,"skipped":0,"successful":1,"timedOut":0,"todo":0},"tests":[{"id":"id1","name":"app::module::test1","lineage":["TopLevel","SubModule","Test"],"location":{"file":"a/b/x.file","line":10,"column":15},"attempt":{"durationInNanoseconds":11000000,"meta":{"abq_metadata":{"runner":1,"worker":0}},"status":{"kind":"successful"},"stderr":"my stdout","stdout":"my stderr","startedAt":"1994-11-05T13:15:30Z","finishedAt":"1994-11-05T13:17:30Z"}}],"otherErrors":[]} diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__pretty.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__pretty.snap index b2eedaa6..9b6b7a07 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__pretty.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_for_successful_runs__pretty.snap @@ -57,5 +57,6 @@ expression: json "finishedAt": "1994-11-05T13:17:30Z" } } - ] + ], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_failing.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_failing.snap index 121aa442..85986993 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_failing.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_failing.snap @@ -94,5 +94,6 @@ expression: json } ] } - ] + ], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_succeeding.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_succeeding.snap index 5f1603ee..db1728a1 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_succeeding.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_retries_ultimately_succeeding.snap @@ -93,5 +93,6 @@ expression: json } ] } - ] + ], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_unknown_framework_if_runner_info_is_missing.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_unknown_framework_if_runner_info_is_missing.snap new file mode 100644 index 00000000..6134c208 --- /dev/null +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__generates_rwx_v1_json_with_unknown_framework_if_runner_info_is_missing.snap @@ -0,0 +1,61 @@ +--- +source: crates/reporters/rwx_v1_json/src/lib.rs +expression: json +--- +{ + "$schema": "https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json", + "framework": { + "kind": "other", + "language": "other" + }, + "summary": { + "status": { + "kind": "failed" + }, + "tests": 1, + "otherErrors": 0, + "retries": 0, + "canceled": 0, + "failed": 1, + "pended": 0, + "quarantined": 0, + "skipped": 0, + "successful": 0, + "timedOut": 0, + "todo": 0 + }, + "tests": [ + { + "id": "id1", + "name": "app::module::test1", + "lineage": [ + "TopLevel", + "SubModule", + "Test" + ], + "location": { + "file": "a/b/x.file", + "line": 10, + "column": 15 + }, + "attempt": { + "durationInNanoseconds": 0, + "meta": { + "abq_metadata": { + "runner": 1, + "worker": 0 + } + }, + "status": { + "kind": "failed", + "message": "I failed once" + }, + "stderr": "my stdout", + "stdout": "my stderr", + "startedAt": "1994-11-05T13:15:30Z", + "finishedAt": "1994-11-05T13:17:30Z" + } + } + ], + "otherErrors": [] +} diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__javascript_jest_lang.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__javascript_jest_lang.snap index 2f3b6aa4..40a8615e 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__javascript_jest_lang.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__javascript_jest_lang.snap @@ -24,5 +24,6 @@ expression: json "timedOut": 0, "todo": 0 }, - "tests": [] + "tests": [], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__native_runner_error_seen_as_other_error.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__native_runner_error_seen_as_other_error.snap index 2cc9f4e7..9f9e10cb 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__native_runner_error_seen_as_other_error.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__native_runner_error_seen_as_other_error.snap @@ -26,5 +26,6 @@ expression: json "timedOut": 0, "todo": 0 }, - "tests": [] + "tests": [], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__retries_with_nested_past_attempts.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__retries_with_nested_past_attempts.snap index f39d1147..26d3b3e1 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__retries_with_nested_past_attempts.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__retries_with_nested_past_attempts.snap @@ -111,5 +111,6 @@ expression: json } ] } - ] + ], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__ruby_rspec_lang.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__ruby_rspec_lang.snap index e5cb8af5..2ee13a5c 100644 --- a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__ruby_rspec_lang.snap +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__ruby_rspec_lang.snap @@ -24,5 +24,6 @@ expression: json "timedOut": 0, "todo": 0 }, - "tests": [] + "tests": [], + "otherErrors": [] } diff --git a/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__writes_passed_other_error_messages.snap b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__writes_passed_other_error_messages.snap new file mode 100644 index 00000000..925d8a61 --- /dev/null +++ b/crates/reporters/rwx_v1_json/src/snapshots/abq_rwx_v1_json__test__writes_passed_other_error_messages.snap @@ -0,0 +1,68 @@ +--- +source: crates/reporters/rwx_v1_json/src/lib.rs +expression: json +--- +{ + "$schema": "https://raw.githubusercontent.com/rwx-research/test-results-schema/main/v1.json", + "framework": { + "kind": "other", + "language": "other" + }, + "summary": { + "status": { + "kind": "failed" + }, + "tests": 1, + "otherErrors": 2, + "retries": 0, + "canceled": 0, + "failed": 1, + "pended": 0, + "quarantined": 0, + "skipped": 0, + "successful": 0, + "timedOut": 0, + "todo": 0 + }, + "tests": [ + { + "id": "id1", + "name": "app::module::test1", + "lineage": [ + "TopLevel", + "SubModule", + "Test" + ], + "location": { + "file": "a/b/x.file", + "line": 10, + "column": 15 + }, + "attempt": { + "durationInNanoseconds": 0, + "meta": { + "abq_metadata": { + "runner": 1, + "worker": 0 + } + }, + "status": { + "kind": "failed", + "message": "I failed once" + }, + "stderr": "my stdout", + "stdout": "my stderr", + "startedAt": "1994-11-05T13:15:30Z", + "finishedAt": "1994-11-05T13:17:30Z" + } + } + ], + "otherErrors": [ + { + "message": "Something else weird happened during in test suite" + }, + { + "message": "Today, 1 = 2" + } + ] +} diff --git a/development.md b/development.md index 57755c05..5bf981ed 100644 --- a/development.md +++ b/development.md @@ -127,7 +127,7 @@ An example of how to create such a certificate follows: ```bash openssl \ req -x509 -newkey rsa:4096 \ - -keyout server.key -out ssl_certs/server.crt \ + -keyout testdata/certs/server.key -out testdata/certs/server.crt \ -days 365 -sha256 -nodes \ -subj '/CN=abq.rwx' \ -extensions san \ diff --git a/testdata/certs/README.md b/testdata/certs/README.md index 3cd28c54..e00c5594 100644 --- a/testdata/certs/README.md +++ b/testdata/certs/README.md @@ -1,4 +1,4 @@ The certificate in this folder are used for integration tests in `crates/abq_cli/tests`. -The certifiacte expires September 1, 2023. +The certifiacte expires September 27, 2024. diff --git a/testdata/certs/server.crt b/testdata/certs/server.crt index 81b696ea..72b48728 100644 --- a/testdata/certs/server.crt +++ b/testdata/certs/server.crt @@ -1,28 +1,28 @@ -----BEGIN CERTIFICATE----- -MIIEvTCCAqWgAwIBAgIJAP6ZpysymZpnMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV -BAMMB2FicS5yd3gwHhcNMjIwOTAxMjE0MjAwWhcNMjMwOTAxMjE0MjAwWjASMRAw +MIIEvTCCAqWgAwIBAgIJAIpPWXSXbdNGMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV +BAMMB2FicS5yd3gwHhcNMjMwOTI3MTczMTA1WhcNMjQwOTI2MTczMTA1WjASMRAw DgYDVQQDDAdhYnEucnd4MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA -tP/mRNW8SOBt+8FHottI2Ym+c+32CSeBEJbbqLh/1NXW5+KozGoyCumGu3u1Met5 -q2GfvJPfqeNzjh4lIWGTRZDNfStSnAEPX3B+IO420eMQrs40tVfFrRO00ZCDg2xz -LIFEcKOS9QAWNGnpXfR9k9X12xTEjrVPMu0RDh+WqgdiC8RI21TnhbvNt+q3pxPX -zo2JAuwYybnSznco0+eFQYAwVixesHBaVP0QPsWqXHYq2VACLWHxWJCjmirH0cQp -duswTvKZlmw9g7Pre7EItWtQhrn2g95pal3R98HQQZ/VHd4IHfxcDTfPo1eNtktc -aP8sS03/Nb14Moufc8AC1xm1rPz+l6Xnn1+rM/jC9gT5P6gQk4o1BdOz33TvC5x5 -uRgpTCiyQnb9hvkKzjnYN7L7Rg8SOj98gRtkt6Fsssd84ssfNoOcWtWvxE5oD79W -gAA6DtYwfL2/mxt92dMYh7Imc0EURyjwwSuWarQBya3F2H3G42ICs+A1nRgKkHzs -3t7gV/bG+faY1TK5/nkD7OW4G/7uIWDYiyxgG6+YpsVVwx71K4NKpYTE6oe7fnk6 -geRDyg/s4UY/O4+wRzL+Hugy6myqm/gJe1JisJWRSYQ386RNR8gIrbxxgjuxhBuA -ri9oivyT5uZ58AF8P+8o+Jw5+JOUAww4ZsPl96Rn7U0CAwEAAaMWMBQwEgYDVR0R -BAswCYIHYWJxLnJ3eDANBgkqhkiG9w0BAQsFAAOCAgEAoccLJSPFR79i73e/971K -cHR+5IE17zVLRMfWe8xDtlHWLyUJ9rTx0UNt6NaUAqWqZjfC0Vjvf1t5Ojz+9xjZ -rlxW/M7mEBXZEqxT5Gy+5FyNaQA1CtXljNnJKVBX4eL4LFaCQl8hvCmrhNqDcg/t -pfMui7sZwoWpL54mywlOIhWv5RAJTwsAlEWj5uQxylVm630lNOV6UdnZuJGR1+D7 -oLTvEyz6RPJc8HAChdiPYoj1aBoWW3zJszN2RfU/a4jwXVSqD6AEiTRbpmdrzRKO -sOpfDsgwV1xdahrA7VmrrLnfp3+wePdRrthghxibw71K3AQFgL7ND3/MGNIm8WaO -WQAmNSfjTkXaSTFwXZV75cIwfgKHNRv2rfQrixDi2Dd5U2nOqc4ygyBAAds2O9mm -FAT2rly217IMKZBs89xsINS+IoxG7DeJSq2sipT5K0KLtoCJU4h/tFWKxc9NQFeN -wKZvOk/ZPGodhTY5ODYDFStHGCQLbCaCzpOsMK99wW9NjjaNgSThAAwxnyAfBlrf -CQ2tokLGZPCvz6Qj7NofR5LppeAQ4lmxqv74OSU2zhmXpwuzOiyfKII6NCMo//KR -/2Q8gJiJljYOb+JKy1/CcdITcJ1N9p32hUq7sowQx3n60SeJwqDI84dxpM1rEFM3 -73iKnhDpCSsGarv2fH5R238= +q/2W+mhUWRB5QNrwpmIKcX52s/b4gKAZZtsPcOidkDPUK4pwFZs0W6JDbKxZ5fnt +kOqI4le0ojjxnM9KFktkXtJH6ERg4gXgV0c5uS+uoeyP5RzxmPRki7nVwiho0Eab +p/bYVU6hhd9Byzlfl8pGLI476r/JJjKpR9PwqkE7w3+U6l/eefb6nrrTqWbz3zTn +QtdYN/qaYZUTKTJHBrfcKDDxv4LCKLheD+BFgaGtZ8HgDn4o+kC52FEzj03SiX/N +nXFeg53oZ8fftZ4DB04Ba5m9fZIXcwMCdiJ39ZS6Jw04A98Uv95ucAK2a2+CsfML +VfY09RZ1eJxUL1A7xRI0CpaEnEmMH6c9/8/CvAL1FHgf12bYhUR6MMEEXgLCHvDE +o5C2kCEHiIXW4C7ZDtOiEn8LOl0HlNdXaftvZzB9AT4toYLReMAmX7iR40okMCgT +Oak43Tu+ysvZxnQjwtEVOYl2CkSOp5PMPEqJzJKoYc0CdF3fcavkCMp2Ssdi8J7H +KSvKPobkYz3xJcP/bRaAOZeV1rUqX7Ps296XbytawvwyBbJSTvFgsk/HS5tJola7 +MWqw2wT4G24g05lTfXFFHQ+rJi1Nf+iCurjGDPa2RZZUWxHPXfDraYur/E9ic5DA +0QGXaGd1UQem0U0/BBib1/+Wipe6y4RXTjBfWgmMIbMCAwEAAaMWMBQwEgYDVR0R +BAswCYIHYWJxLnJ3eDANBgkqhkiG9w0BAQsFAAOCAgEAVvM0GP0IHDmbzvi4+p5i +KcDoMLF5b487Rq6gWfrFNJdBUGdE7s7/ML1nIHqXfSkC0vYbUPbZ4mCqzWUPppoI +KT7VFd2qM8dnCkac1VcZweNavyF0YWqZJUEhvwmsIRGLTy+KPA9/HRAJeGs+8g+r +VCuajTduS9WbEK8PqwIFg9UNfGMotYzW1i8S0OyvXW0qJBOtgDRV6NHZUWUkqMED +c7+6yQ2H2rMDdTgT/7A9+1SEESsh3mXGBklpgYaHhxW5/vQz0ib0ZGNIRnMKkDJf +XgW1lPY7DB1KJeSjS6XDuRoNKUEJ5I/qyj8poDObzKK4/WD32LgPudVqN9yuXn8L +qeFpwuzMT8+Z56BJH5ECuMOr3OU5fVSehfGgwSS1HlY1MvVlctfXqdX3fE5Gfml4 +tfrqAOyoQpEyvN3HbjzmgvwHuPLfSQps9kqxxt/h6x85Pt7oLC8Qyy2Mn3FByMp2 +D2Dz1J2Ba1pXVmm6tCrhqMcwzmIJQoFOSO5SDHw8xi14K5STE/TSJxJXrpzmkXVK +3ojtmkcOnnbai1PZepSwIPSUq49r9ulXjGNigq73TpH6VEb9pkPrIDQ63kYCzZEy +P4jr0v60nBSq7ToJ+jdCXFRO3cB7+tLrWnYixRJ7YoAvsTMIEXfIXmkCgZ1Gyacn +GKfUHq5Fi953yB2iKCITzPI= -----END CERTIFICATE----- diff --git a/testdata/certs/server.key b/testdata/certs/server.key index 08e94965..b6697116 100644 --- a/testdata/certs/server.key +++ b/testdata/certs/server.key @@ -1,52 +1,52 @@ -----BEGIN PRIVATE KEY----- -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 -j1fansTTiEVwWLNCDgCq9tWoA60kfTQ= +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 +0KRc50Tu0nPYKosi/MV4HYna6UGtPis= -----END PRIVATE KEY-----