• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/test/field_trial.h"
12 
13 #include <algorithm>
14 #include <cassert>
15 #include <cstdio>
16 #include <cstdlib>
17 #include <map>
18 #include <string>
19 
20 #include "webrtc/system_wrappers/include/field_trial.h"
21 #include "webrtc/system_wrappers/include/field_trial_default.h"
22 
23 namespace webrtc {
24 namespace {
25 bool field_trials_initiated_ = false;
26 }  // namespace
27 
28 namespace test {
29 // Note: this code is copied from src/base/metrics/field_trial.cc since the aim
30 // is to mimic chromium --force-fieldtrials.
InitFieldTrialsFromString(const std::string & trials_string)31 void InitFieldTrialsFromString(const std::string& trials_string) {
32   static const char kPersistentStringSeparator = '/';
33 
34   // Catch an error if this is called more than once.
35   assert(!field_trials_initiated_);
36   field_trials_initiated_ = true;
37 
38   if (trials_string.empty())
39     return;
40 
41   size_t next_item = 0;
42   std::map<std::string, std::string> field_trials;
43   while (next_item < trials_string.length()) {
44     size_t name_end = trials_string.find(kPersistentStringSeparator, next_item);
45     if (name_end == trials_string.npos || next_item == name_end)
46       break;
47     size_t group_name_end = trials_string.find(kPersistentStringSeparator,
48                                                name_end + 1);
49     if (group_name_end == trials_string.npos || name_end + 1 == group_name_end)
50       break;
51     std::string name(trials_string, next_item, name_end - next_item);
52     std::string group_name(trials_string, name_end + 1,
53                            group_name_end - name_end - 1);
54     next_item = group_name_end + 1;
55 
56     // Fail if duplicate with different group name.
57     if (field_trials.find(name) != field_trials.end() &&
58         field_trials.find(name)->second != group_name) {
59       break;
60     }
61 
62     field_trials[name] = group_name;
63 
64     // Successfully parsed all field trials from the string.
65     if (next_item == trials_string.length()) {
66       webrtc::field_trial::InitFieldTrialsFromString(trials_string.c_str());
67       return;
68     }
69   }
70   // Using fprintf as LOG does not print when this is called early in main.
71   fprintf(stderr, "Invalid field trials string.\n");
72 
73   // Using abort so it crashes in both debug and release mode.
74   abort();
75 }
76 
ScopedFieldTrials(const std::string & config)77 ScopedFieldTrials::ScopedFieldTrials(const std::string& config)
78   : previous_field_trials_(webrtc::field_trial::GetFieldTrialString()) {
79   assert(field_trials_initiated_);
80   field_trials_initiated_ = false;
81   current_field_trials_ = config;
82   InitFieldTrialsFromString(current_field_trials_);
83 }
84 
~ScopedFieldTrials()85 ScopedFieldTrials::~ScopedFieldTrials() {
86   // Should still be initialized, since InitFieldTrials is called from ctor.
87   // That's why we don't restore the flag.
88   assert(field_trials_initiated_);
89   webrtc::field_trial::InitFieldTrialsFromString(previous_field_trials_);
90 }
91 
92 }  // namespace test
93 }  // namespace webrtc
94