Wire up --force_fieldtrials for vie_auto_test and for test targets linking with test/test.gyp:{test_main|test_support_main}
This allows use of webrtc field trials and opens up the possibility to try the different code paths when running the unit tests by wiring them up to a --force_fieldtrials.
Tested: running a test target that links with the above with a flag --force_fieldtrials=invalid leads the test to crash.
BUG=crbug/367114
R=mflodman@webrtc.org, phoglund@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/19439004
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@6181 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/system_wrappers/interface/field_trial.h b/system_wrappers/interface/field_trial.h
index d38df26..f2cf880 100644
--- a/system_wrappers/interface/field_trial.h
+++ b/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/test/field_trial.cc b/test/field_trial.cc
new file mode 100644
index 0000000..6b3d83c
--- /dev/null
+++ b/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 <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <map>
+#include <string>
+
+#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<std::string, std::string> field_trials_;
+} // namespace
+
+namespace field_trial {
+std::string FindFullName(const std::string& trial_name) {
+ assert(field_trials_initiated_);
+ std::map<std::string, std::string>::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/test/field_trial.h b/test/field_trial.h
new file mode 100644
index 0000000..6503254
--- /dev/null
+++ b/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 <string>
+
+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/test/test.gyp b/test/test.gyp
index 5be3c10..feca0b2 100644
--- a/test/test.gyp
+++ b/test/test.gyp
@@ -64,14 +64,26 @@
],
},
{
+ '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',
'sources': [
'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/test/test_main.cc b/test/test_main.cc
index 64109d4..acce96f 100644
--- a/test/test_main.cc
+++ b/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/test/test_suite.cc b/test/test_suite.cc
index 7cfb856..e88b030 100644
--- a/test/test_suite.cc
+++ b/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 @@
// 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/video_engine/test/auto_test/source/vie_autotest_main.cc b/video_engine/test/auto_test/source/vie_autotest_main.cc
index a1e45c1..c688e2e 100644
--- a/video_engine/test/auto_test/source/vie_autotest_main.cc
+++ b/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 @@
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/video_engine/test/auto_test/vie_auto_test.gypi b/video_engine/test/auto_test/vie_auto_test.gypi
index fb611b0..9629166 100644
--- a/video_engine/test/auto_test/vie_auto_test.gypi
+++ b/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',
],