Home | History | Annotate | Download | only in test
      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.
     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 
     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 
     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