blob: 1e3c64742e61de1d63aa9d89ea72301186c96e68 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
anyhow::{format_err, Context as _, Error},
fidl::endpoints,
fidl_fuchsia_io::DirectoryMarker,
fidl_fuchsia_sys2 as fsys, fidl_fuchsia_test as ftest,
fidl_fuchsia_test_manager as ftest_manager,
ftest_manager::LaunchOptions,
fuchsia_component::client,
fuchsia_component::client::connect_to_protocol_at_dir,
futures::{channel::mpsc, prelude::*},
test_executor::{TestEvent, TestResult, TestRunOptions},
};
async fn connect_test_manager() -> Result<ftest_manager::HarnessProxy, Error> {
let realm = client::connect_to_service::<fsys::RealmMarker>()
.context("could not connect to Realm service")?;
let mut child_ref = fsys::ChildRef { name: "test_manager".to_owned(), collection: None };
let (dir, server_end) = endpoints::create_proxy::<DirectoryMarker>()?;
realm
.bind_child(&mut child_ref, server_end)
.await
.context("bind_child fidl call failed for test manager")?
.map_err(|e| format_err!("failed to create test manager: {:?}", e))?;
connect_to_protocol_at_dir::<ftest_manager::HarnessMarker>(&dir)
.context("failed to open test suite service")
}
/// Returns SuiteProxy and SuiteControllerProxy. Keep SuiteControllerProxy alive for
/// length of your test run so that your test doesn't die.
async fn launch_test(
test_url: &str,
) -> Result<(ftest::SuiteProxy, ftest_manager::SuiteControllerProxy), Error> {
let proxy = connect_test_manager().await?;
let (suite_proxy, suite_server_end) = fidl::endpoints::create_proxy()?;
let (controller_proxy, controller_server_end) = fidl::endpoints::create_proxy()?;
proxy
.launch_suite(test_url, LaunchOptions {}, suite_server_end, controller_server_end)
.await
.context("launch_test call failed")?
.map_err(|e| format_err!("error launching test: {:?}", e))?;
Ok((suite_proxy, controller_proxy))
}
async fn run_test(test_url: &str) -> Result<Vec<TestEvent>, Error> {
let (suite_proxy, _keep_alive) = launch_test(test_url).await?;
let (sender, recv) = mpsc::channel(1);
// TODO(fxb/45852): Support disabled tests.
let test_run_options = TestRunOptions::default();
let (events, ()) = futures::future::try_join(
recv.collect::<Vec<_>>().map(Ok),
test_executor::run_and_collect_results(suite_proxy, sender, None, test_run_options),
)
.await
.context("running test")?;
let mut test_events = vec![];
// break logs as they can be grouped in any way.
for event in events {
match event {
TestEvent::LogMessage { test_case_name, msg } => {
let logs = msg.split("\n");
for log in logs {
if log.len() > 0 {
test_events.push(TestEvent::LogMessage {
test_case_name: test_case_name.clone(),
msg: log.to_string(),
});
}
}
}
event => {
test_events.push(event);
}
};
}
Ok(test_events)
}
#[fuchsia_async::run_singlethreaded(test)]
async fn launch_and_run_sample_test() {
let test_url = "fuchsia-pkg://fuchsia.com/gtest-runner-example-tests#meta/sample_tests.cm";
let mut events = run_test(test_url).await.unwrap();
let mut expected_events = vec![
TestEvent::test_case_started("SampleTest1.Crashing"),
TestEvent::test_case_started("SampleTest1.SimpleFail"),
TestEvent::log_message(
"SampleTest1.SimpleFail",
"../../src/sys/test_runners/gtest/test_data/sample_tests.cc:9: Failure",
),
TestEvent::log_message("SampleTest1.SimpleFail", "Value of: true"),
TestEvent::log_message("SampleTest1.SimpleFail", " Actual: true"),
TestEvent::log_message("SampleTest1.SimpleFail", "Expected: false"),
TestEvent::test_case_started("SampleFixture.Test2"),
TestEvent::test_case_started("Tests/SampleParameterizedTestFixture.Test/0"),
TestEvent::test_case_finished(
"Tests/SampleParameterizedTestFixture.Test/0",
TestResult::Passed,
),
TestEvent::test_case_started("Tests/SampleParameterizedTestFixture.Test/2"),
TestEvent::test_case_finished(
"Tests/SampleParameterizedTestFixture.Test/2",
TestResult::Passed,
),
TestEvent::test_case_started("Tests/SampleParameterizedTestFixture.Test/3"),
TestEvent::test_case_finished(
"Tests/SampleParameterizedTestFixture.Test/3",
TestResult::Passed,
),
TestEvent::test_case_started("WriteToStdout.TestPass"),
TestEvent::log_message("WriteToStdout.TestPass", "first msg"),
TestEvent::log_message("WriteToStdout.TestPass", "second msg"),
TestEvent::test_case_finished("WriteToStdout.TestPass", TestResult::Passed),
TestEvent::test_case_started("WriteToStdout.TestFail"),
TestEvent::log_message("WriteToStdout.TestFail", "first msg"),
TestEvent::log_message(
"WriteToStdout.TestFail",
"../../src/sys/test_runners/gtest/test_data/sample_tests.cc:37: Failure",
),
TestEvent::log_message("WriteToStdout.TestFail", "Value of: true"),
TestEvent::log_message("WriteToStdout.TestFail", " Actual: true"),
TestEvent::log_message("WriteToStdout.TestFail", "Expected: false"),
TestEvent::log_message("WriteToStdout.TestFail", "second msg"),
TestEvent::test_case_finished("WriteToStdout.TestFail", TestResult::Failed),
TestEvent::test_case_started("SampleDisabled.DISABLED_Test1"),
TestEvent::test_case_finished("SampleTest1.SimpleFail", TestResult::Failed),
TestEvent::log_message("SampleTest1.Crashing", "Test exited abnormally"),
TestEvent::test_case_finished("SampleTest1.Crashing", TestResult::Failed),
TestEvent::test_case_started("SampleFixture.Test1"),
TestEvent::test_case_finished("SampleDisabled.DISABLED_Test1", TestResult::Passed),
TestEvent::test_case_started("Tests/SampleParameterizedTestFixture.Test/1"),
TestEvent::test_case_started("SampleTest2.SimplePass"),
TestEvent::test_case_finished("SampleTest2.SimplePass", TestResult::Passed),
TestEvent::test_case_finished("SampleFixture.Test1", TestResult::Passed),
TestEvent::test_case_finished("SampleFixture.Test2", TestResult::Passed),
TestEvent::test_case_finished(
"Tests/SampleParameterizedTestFixture.Test/1",
TestResult::Passed,
),
TestEvent::test_finished(),
];
expected_events.sort();
events.sort();
assert_eq!(expected_events, events);
}
#[fuchsia_async::run_singlethreaded(test)]
async fn launch_and_run_empty_test() {
let test_url = "fuchsia-pkg://fuchsia.com/gtest-runner-example-tests#meta/empty_test.cm";
let events = run_test(test_url).await.unwrap();
let expected_events = vec![TestEvent::test_finished()];
assert_eq!(expected_events, events);
}
#[fuchsia_async::run_singlethreaded(test)]
async fn launch_and_test_echo_test() {
let test_url = "fuchsia-pkg://fuchsia.com/gtest-runner-example-tests#meta/echo_test_realm.cm";
let events = run_test(test_url).await.unwrap();
let expected_events = vec![
TestEvent::test_case_started("EchoTest.TestEcho"),
TestEvent::test_case_finished("EchoTest.TestEcho", TestResult::Passed),
TestEvent::test_finished(),
];
assert_eq!(expected_events, events);
}
/*
// fxb/50793: ignore doesn't work right now.
// Stress test with a very large gtest suite.
#[fuchsia_async::run_singlethreaded(test)]
#[ignore = "Timeouts on CQ bots"]
async fn launch_and_run_hugetest() {
let test_url = "fuchsia-pkg://fuchsia.com/gtest-runner-example-tests#meta/huge_gtest.cm";
let events = run_test(test_url).await.unwrap();
let mut expected_events = vec![];
for i in 0..1000 {
let s = format!("HugeStress/HugeTest.Test/{}", i);
expected_events.extend(vec![
TestEvent::test_case_started(&s),
TestEvent::test_case_finished(&s, TestResult::Passed),
])
}
expected_events.push(TestEvent::test_finished());
assert_eq!(expected_events, events);
}
*/