/* * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "test/test_main_lib.h" #include #include #include #include #include "absl/flags/flag.h" #include "absl/memory/memory.h" #include "absl/strings/match.h" #include "absl/types/optional.h" #include "api/test/metrics/chrome_perf_dashboard_metrics_exporter.h" #include "api/test/metrics/global_metrics_logger_and_exporter.h" #include "api/test/metrics/metrics_exporter.h" #include "api/test/metrics/metrics_set_proto_file_exporter.h" #include "api/test/metrics/print_result_proxy_metrics_exporter.h" #include "api/test/metrics/stdout_metrics_exporter.h" #include "rtc_base/checks.h" #include "rtc_base/event_tracer.h" #include "rtc_base/logging.h" #include "rtc_base/ssl_adapter.h" #include "rtc_base/ssl_stream_adapter.h" #include "rtc_base/thread.h" #include "system_wrappers/include/field_trial.h" #include "system_wrappers/include/metrics.h" #include "test/field_trial.h" #include "test/gtest.h" #include "test/test_flags.h" #include "test/testsupport/perf_test.h" #include "test/testsupport/resources_dir_flag.h" #if defined(WEBRTC_WIN) #include "rtc_base/win32_socket_init.h" #endif #if defined(WEBRTC_IOS) #include "test/ios/test_support.h" ABSL_FLAG(std::string, NSTreatUnknownArgumentsAsOpen, "", "Intentionally ignored flag intended for iOS test runner."); ABSL_FLAG(std::string, ApplePersistenceIgnoreState, "", "Intentionally ignored flag intended for iOS test runner."); ABSL_FLAG(bool, enable_run_ios_unittests_with_xctest, false, "Intentionally ignored flag intended for iOS test runner."); ABSL_FLAG(bool, write_compiled_tests_json_to_writable_path, false, "Intentionally ignored flag intended for iOS test runner."); // This is the cousin of isolated_script_test_perf_output, but we can't dictate // where to write on iOS so the semantics of this flag are a bit different. ABSL_FLAG( bool, write_perf_output_on_ios, false, "Store the perf results in Documents/perftest_result.pb in the format " "described by histogram.proto in " "https://chromium.googlesource.com/catapult/."); #elif defined(WEBRTC_FUCHSIA) ABSL_FLAG(std::string, use_vulkan, "", "Intentionally ignored flag."); #else // TODO(bugs.webrtc.org/8115): Remove workaround when fixed. ABSL_FLAG(bool, no_sandbox, false, "Intentionally ignored flag."); ABSL_FLAG(bool, test_launcher_bot_mode, false, "Intentionally ignored flag."); #endif ABSL_FLAG(std::string, isolated_script_test_output, "", "Path to output an empty JSON file which Chromium infra requires."); ABSL_FLAG(bool, logs, true, "print logs to stderr"); ABSL_FLAG(bool, verbose, false, "verbose logs to stderr"); ABSL_FLAG(std::string, trace_event, "", "Path to collect trace events (json file) for chrome://tracing. " "If not set, events aren't captured."); ABSL_FLAG(std::string, test_launcher_shard_index, "", "Index of the test shard to run, from 0 to " "the value specified with --test_launcher_total_shards."); ABSL_FLAG(std::string, test_launcher_total_shards, "", "Total number of shards."); namespace webrtc { namespace { constexpr char kPlotAllMetrics[] = "all"; class TestMainImpl : public TestMain { public: int Init(int* argc, char* argv[]) override { return Init(); } int Init() override { // Make sure we always pull in the --resources_dir flag, even if the test // binary doesn't link with fileutils (downstream expects all test mains to // have this flag). (void)absl::GetFlag(FLAGS_resources_dir); // Default to LS_INFO, even for release builds to provide better test // logging. if (rtc::LogMessage::GetLogToDebug() > rtc::LS_INFO) rtc::LogMessage::LogToDebug(rtc::LS_INFO); if (absl::GetFlag(FLAGS_verbose)) rtc::LogMessage::LogToDebug(rtc::LS_VERBOSE); rtc::LogMessage::SetLogToStderr(absl::GetFlag(FLAGS_logs) || absl::GetFlag(FLAGS_verbose)); // The sharding arguments take precedence over the sharding environment // variables. if (!absl::GetFlag(FLAGS_test_launcher_shard_index).empty() && !absl::GetFlag(FLAGS_test_launcher_total_shards).empty()) { std::string shard_index = "GTEST_SHARD_INDEX=" + absl::GetFlag(FLAGS_test_launcher_shard_index); std::string total_shards = "GTEST_TOTAL_SHARDS=" + absl::GetFlag(FLAGS_test_launcher_total_shards); putenv(shard_index.data()); putenv(total_shards.data()); } // InitFieldTrialsFromString stores the char*, so the char array must // outlive the application. field_trials_ = absl::GetFlag(FLAGS_force_fieldtrials); webrtc::field_trial::InitFieldTrialsFromString(field_trials_.c_str()); webrtc::metrics::Enable(); #if defined(WEBRTC_WIN) winsock_init_ = std::make_unique(); #endif // Initialize SSL which are used by several tests. rtc::InitializeSSL(); rtc::SSLStreamAdapter::EnableTimeCallbackForTesting(); return 0; } int Run(int argc, char* argv[]) override { std::string trace_event_path = absl::GetFlag(FLAGS_trace_event); const bool capture_events = !trace_event_path.empty(); if (capture_events) { rtc::tracing::SetupInternalTracer(); rtc::tracing::StartInternalCapture(trace_event_path); } absl::optional> metrics_to_plot = absl::GetFlag(FLAGS_plot); if (metrics_to_plot->empty()) { metrics_to_plot = absl::nullopt; } else { if (metrics_to_plot->size() == 1 && (*metrics_to_plot)[0] == kPlotAllMetrics) { metrics_to_plot->clear(); } } #if defined(WEBRTC_IOS) rtc::test::InitTestSuite( RUN_ALL_TESTS, argc, argv, absl::GetFlag(FLAGS_write_perf_output_on_ios), absl::GetFlag(FLAGS_export_perf_results_new_api), absl::GetFlag(FLAGS_webrtc_test_metrics_output_path), metrics_to_plot); rtc::test::RunTestsFromIOSApp(); int exit_code = 0; #else int exit_code = RUN_ALL_TESTS(); std::vector> exporters; if (absl::GetFlag(FLAGS_export_perf_results_new_api)) { exporters.push_back(std::make_unique()); if (!absl::GetFlag(FLAGS_webrtc_test_metrics_output_path).empty()) { exporters.push_back( std::make_unique( webrtc::test::MetricsSetProtoFileExporter::Options( absl::GetFlag(FLAGS_webrtc_test_metrics_output_path)))); } if (!absl::GetFlag(FLAGS_isolated_script_test_perf_output).empty()) { exporters.push_back( std::make_unique( absl::GetFlag(FLAGS_isolated_script_test_perf_output))); } } else { exporters.push_back( std::make_unique()); } test::ExportPerfMetric(*test::GetGlobalMetricsLogger(), std::move(exporters)); if (!absl::GetFlag(FLAGS_export_perf_results_new_api)) { std::string perf_output_file = absl::GetFlag(FLAGS_isolated_script_test_perf_output); if (!perf_output_file.empty()) { if (!webrtc::test::WritePerfResults(perf_output_file)) { return 1; } } if (metrics_to_plot) { webrtc::test::PrintPlottableResults(*metrics_to_plot); } } std::string result_filename = absl::GetFlag(FLAGS_isolated_script_test_output); if (!result_filename.empty()) { std::ofstream result_file(result_filename); result_file << "{\"version\": 3}"; } #endif if (capture_events) { rtc::tracing::StopInternalCapture(); } #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \ defined(UNDEFINED_SANITIZER) // We want the test flagged as failed only for sanitizer defects, // in which case the sanitizer will override exit code with 66. exit_code = 0; #endif return exit_code; } ~TestMainImpl() override = default; private: #if defined(WEBRTC_WIN) std::unique_ptr winsock_init_; #endif }; } // namespace std::unique_ptr TestMain::Create() { return std::make_unique(); } } // namespace webrtc