diff --git a/webrtc/system_wrappers/interface/field_trial.h b/webrtc/system_wrappers/interface/field_trial.h index d38df26cc..f2cf88027 100644 --- a/webrtc/system_wrappers/interface/field_trial.h +++ b/webrtc/system_wrappers/interface/field_trial.h @@ -53,7 +53,6 @@ // needs to push a config with start_active:true or run a local finch // server. // -// TODO(andresp): support --force_fieldtirals from webrtc tests. // TODO(andresp): find out how to get bots to run tests with trials enabled. namespace webrtc { diff --git a/webrtc/test/field_trial.cc b/webrtc/test/field_trial.cc new file mode 100644 index 000000000..6b3d83cf5 --- /dev/null +++ b/webrtc/test/field_trial.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 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 "webrtc/test/field_trial.h" + +#include +#include +#include +#include +#include +#include + +#include "webrtc/system_wrappers/interface/field_trial.h" + +namespace webrtc { +namespace { +// Clients of this library have show a clear intent to setup field trials by +// linking with it. As so try to crash if they forget to call +// InitFieldTrialsFromString before webrtc tries to access a field trial. +bool field_trials_initiated_ = false; +std::map field_trials_; +} // namespace + +namespace field_trial { +std::string FindFullName(const std::string& trial_name) { + assert(field_trials_initiated_); + std::map::const_iterator it = + field_trials_.find(trial_name); + if (it == field_trials_.end()) + return std::string(); + return it->second; +} +} // namespace field_trial + +namespace test { +// Note: this code is copied from src/base/metrics/field_trial.cc since the aim +// is to mimic chromium --force-fieldtrials. +void InitFieldTrialsFromString(const std::string& trials_string) { + static const char kPersistentStringSeparator = '/'; + + // Catch an error if this is called more than once. + assert(field_trials_initiated_ == false); + field_trials_initiated_ = true; + + if (trials_string.empty()) return; + + size_t next_item = 0; + while (next_item < trials_string.length()) { + size_t name_end = trials_string.find(kPersistentStringSeparator, next_item); + if (name_end == trials_string.npos || next_item == name_end) + break; + size_t group_name_end = trials_string.find(kPersistentStringSeparator, + name_end + 1); + if (group_name_end == trials_string.npos || name_end + 1 == group_name_end) + break; + std::string name(trials_string, next_item, name_end - next_item); + std::string group_name(trials_string, name_end + 1, + group_name_end - name_end - 1); + next_item = group_name_end + 1; + + // Fail if duplicate with different group name. + if (field_trials_.find(name) != field_trials_.end() && + field_trials_.find(name)->second != group_name) + break; + + field_trials_[name] = group_name; + + // Successfully parsed all field trials from the string. + if (next_item == trials_string.length()) + return; + } + // LOG does not prints when this is called early on main. + fprintf(stderr, "Invalid field trials string.\n"); + + // Using abort so it crashs both in debug and release mode. + abort(); +} +} // namespace test +} // namespace webrtc diff --git a/webrtc/test/field_trial.h b/webrtc/test/field_trial.h new file mode 100644 index 000000000..650325472 --- /dev/null +++ b/webrtc/test/field_trial.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 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. + */ + +#ifndef WEBRTC_TEST_FIELD_TRIAL_H_ +#define WEBRTC_TEST_FIELD_TRIAL_H_ + +#include + +namespace webrtc { +namespace test { + +// Parses enabled field trials from a string config, such as the one passed +// to chrome's argument --force-fieldtrials and initializes webrtc::field_trial +// with such a config. +// E.g.: +// "WebRTC-experimentFoo/Enabled/WebRTC-experimentBar/Enabled100kbps/" +// Assigns the process to group "Enabled" on WebRTCExperimentFoo trial +// and to group "Enabled100kbps" on WebRTCExperimentBar. +// +// E.g. invalid config: +// "WebRTC-experiment1/Enabled" (note missing / separator at the end). +// +// Note: This method crashes with an error message if an invalid config is +// passed to it. That can be used to find out if a binary is parsing the flags. +void InitFieldTrialsFromString(const std::string& config); + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_TEST_FIELD_TRIAL_H_ diff --git a/webrtc/test/test.gyp b/webrtc/test/test.gyp index 5be3c1064..feca0b28e 100644 --- a/webrtc/test/test.gyp +++ b/webrtc/test/test.gyp @@ -63,6 +63,17 @@ '<(webrtc_root)/modules/modules.gyp:rtp_rtcp', ], }, + { + 'target_name': 'field_trial', + 'type': 'static_library', + 'sources': [ + 'field_trial.cc', + 'field_trial.h', + ], + 'dependencies': [ + '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', + ], + }, { 'target_name': 'test_main', 'type': 'static_library', @@ -70,8 +81,9 @@ 'test_main.cc', ], 'dependencies': [ - '<(DEPTH)/testing/gtest.gyp:gtest', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:field_trial_default', + 'field_trial', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', ], }, { @@ -80,12 +92,9 @@ 'dependencies': [ '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/testing/gmock.gyp:gmock', - '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers', ], 'sources': [ - 'test_suite.cc', - 'test_suite.h', 'testsupport/android/root_path_android.cc', 'testsupport/android/root_path_android_chromium.cc', 'testsupport/fileutils.cc', @@ -128,11 +137,16 @@ 'target_name': 'test_support_main', 'type': 'static_library', 'dependencies': [ + 'field_trial', 'test_support', - '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:field_trial_default', + '<(DEPTH)/testing/gmock.gyp:gmock', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/gflags/gflags.gyp:gflags', ], 'sources': [ 'run_all_unittests.cc', + 'test_suite.cc', + 'test_suite.h', ], }, { diff --git a/webrtc/test/test_main.cc b/webrtc/test/test_main.cc index 64109d433..acce96f2c 100644 --- a/webrtc/test/test_main.cc +++ b/webrtc/test/test_main.cc @@ -8,14 +8,26 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include "gflags/gflags.h" #include "testing/gtest/include/gtest/gtest.h" - +#include "webrtc/test/field_trial.h" #include "webrtc/test/run_tests.h" #include "webrtc/test/testsupport/fileutils.h" +DEFINE_string(force_fieldtrials, "", + "Field trials control experimental feature code which can be forced. " + "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" + " will assign the group Enable to field trial WebRTC-FooFeature."); + int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); - webrtc::test::SetExecutablePath(argv[0]); + // AllowCommandLineParsing allows us to ignore flags passed on to us by + // Chromium build bots without having to explicitly disable them. + google::AllowCommandLineReparsing(); + google::ParseCommandLineFlags(&argc, &argv, false); + + webrtc::test::SetExecutablePath(argv[0]); + webrtc::test::InitFieldTrialsFromString(FLAGS_force_fieldtrials); return webrtc::test::RunAllTests(); } diff --git a/webrtc/test/test_suite.cc b/webrtc/test/test_suite.cc index 7cfb856f3..e88b0301a 100644 --- a/webrtc/test/test_suite.cc +++ b/webrtc/test/test_suite.cc @@ -15,9 +15,15 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/test/testsupport/trace_to_stderr.h" +#include "webrtc/test/field_trial.h" DEFINE_bool(logs, false, "print logs to stderr"); +DEFINE_string(force_fieldtrials, "", + "Field trials control experimental feature code which can be forced. " + "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" + " will assign the group Enable to field trial WebRTC-FooFeature."); + namespace webrtc { namespace test { @@ -28,6 +34,8 @@ TestSuite::TestSuite(int argc, char** argv) { // Chromium build bots without having to explicitly disable them. google::AllowCommandLineReparsing(); google::ParseCommandLineFlags(&argc, &argv, true); + + webrtc::test::InitFieldTrialsFromString(FLAGS_force_fieldtrials); } TestSuite::~TestSuite() { diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_main.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_main.cc index a1e45c129..c688e2ef5 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_main.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_main.cc @@ -13,6 +13,7 @@ #include "gflags/gflags.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/test/field_trial.h" #include "webrtc/test/testsupport/fileutils.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h" #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_window_manager_interface.h" @@ -20,6 +21,10 @@ DEFINE_bool(automated, false, "Run Video engine tests in noninteractive mode."); DEFINE_bool(auto_custom_call, false, "Run custom call directly."); +DEFINE_string(force_fieldtrials, "", + "Field trials control experimental feature code which can be forced. " + "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" + " will assign the group Enable to field trial WebRTC-FooFeature."); static const std::string kStandardTest = "ViEStandardIntegrationTest"; static const std::string kExtendedTest = "ViEExtendedIntegrationTest"; @@ -48,6 +53,8 @@ int ViEAutoTestMain::RunTests(int argc, char** argv) { google::AllowCommandLineReparsing(); // Parse remaining flags: google::ParseCommandLineFlags(&argc, &argv, true); + // Initialize field trial + webrtc::test::InitFieldTrialsFromString(FLAGS_force_fieldtrials); int result; if (FLAGS_automated) { diff --git a/webrtc/video_engine/test/auto_test/vie_auto_test.gypi b/webrtc/video_engine/test/auto_test/vie_auto_test.gypi index fb611b00d..962916607 100644 --- a/webrtc/video_engine/test/auto_test/vie_auto_test.gypi +++ b/webrtc/video_engine/test/auto_test/vie_auto_test.gypi @@ -22,6 +22,7 @@ '<(webrtc_root)/test/metrics.gyp:metrics', '<(webrtc_root)/test/test.gyp:channel_transport', '<(webrtc_root)/test/test.gyp:test_support', + '<(webrtc_root)/test/test.gyp:field_trial', 'video_engine_core', 'libvietest', ],