Skip to content

Commit

Permalink
Adds enum field trial parser.
Browse files Browse the repository at this point in the history
Removed the need to create a custom parser function and reuses some of
the code to reduce binary overhead of enums.

Bug: webrtc:9346
Change-Id: I51c9da713ed5456a86a2afbcf0991477bb83b894
Reviewed-on: https://webrtc-review.googlesource.com/83623
Reviewed-by: Stefan Holmer <[email protected]>
Commit-Queue: Sebastian Jansson <[email protected]>
Cr-Commit-Position: refs/heads/master@{#23752}
  • Loading branch information
jonex authored and Commit Bot committed Jun 27, 2018
1 parent b3f5aed commit 2c74d85
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 17 deletions.
31 changes: 31 additions & 0 deletions rtc_base/experiments/field_trial_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,37 @@ bool FieldTrialFlag::Parse(absl::optional<std::string> str_value) {
return true;
}

AbstractFieldTrialEnum::AbstractFieldTrialEnum(
std::string key,
int default_value,
std::map<std::string, int> mapping)
: FieldTrialParameterInterface(key),
value_(default_value),
enum_mapping_(mapping) {
for (auto& key_val : enum_mapping_)
valid_values_.insert(key_val.second);
}
AbstractFieldTrialEnum::AbstractFieldTrialEnum(const AbstractFieldTrialEnum&) =
default;
AbstractFieldTrialEnum::~AbstractFieldTrialEnum() = default;

bool AbstractFieldTrialEnum::Parse(absl::optional<std::string> str_value) {
if (str_value) {
auto it = enum_mapping_.find(*str_value);
if (it != enum_mapping_.end()) {
value_ = it->second;
return true;
}
absl::optional<int> value = ParseTypedParameter<int>(*str_value);
if (value.has_value() &&
(valid_values_.find(*value) != valid_values_.end())) {
value_ = *value;
return true;
}
}
return false;
}

template class FieldTrialParameter<bool>;
template class FieldTrialParameter<double>;
template class FieldTrialParameter<int>;
Expand Down
43 changes: 43 additions & 0 deletions rtc_base/experiments/field_trial_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include <stdint.h>
#include <initializer_list>
#include <map>
#include <set>
#include <string>
#include "absl/types/optional.h"

Expand Down Expand Up @@ -83,6 +85,47 @@ class FieldTrialParameter : public FieldTrialParameterInterface {
T value_;
};

class AbstractFieldTrialEnum : public FieldTrialParameterInterface {
public:
AbstractFieldTrialEnum(std::string key,
int default_value,
std::map<std::string, int> mapping);
~AbstractFieldTrialEnum() override;
AbstractFieldTrialEnum(const AbstractFieldTrialEnum&);

protected:
bool Parse(absl::optional<std::string> str_value) override;

protected:
int value_;
std::map<std::string, int> enum_mapping_;
std::set<int> valid_values_;
};

// The FieldTrialEnum class can be used to quickly define a parser for a
// specific enum. It handles values provided as integers and as strings if a
// mapping is provided.
template <typename T>
class FieldTrialEnum : public AbstractFieldTrialEnum {
public:
FieldTrialEnum(std::string key,
T default_value,
std::map<std::string, T> mapping)
: AbstractFieldTrialEnum(key,
static_cast<int>(default_value),
ToIntMap(mapping)) {}
T Get() const { return static_cast<T>(value_); }
operator T() const { return Get(); }

private:
static std::map<std::string, int> ToIntMap(std::map<std::string, T> mapping) {
std::map<std::string, int> res;
for (const auto& it : mapping)
res[it.first] = static_cast<int>(it.second);
return res;
}
};

// This class uses the ParseTypedParameter function to implement an optional
// parameter implementation that can default to absl::nullopt.
template <typename T>
Expand Down
28 changes: 11 additions & 17 deletions rtc_base/experiments/field_trial_parser_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,12 @@ struct DummyExperiment {
};

enum class CustomEnum {
kDefault,
kRed,
kBlue,
kDefault = 0,
kRed = 1,
kBlue = 2,
};
} // namespace

// Providing a custom parser for an enum can make the trial string easier to
// read, but also adds more code and makes the string more verbose.
template <>
absl::optional<CustomEnum> ParseTypedParameter<CustomEnum>(std::string str) {
if (str == "default")
return CustomEnum::kDefault;
else if (str == "red")
return CustomEnum::kRed;
else if (str == "blue")
return CustomEnum::kBlue;
return absl::nullopt;
}

TEST(FieldTrialParserTest, ParsesValidParameters) {
DummyExperiment exp("Enabled,f:-1.7,r:2,p:1,h:x7c");
EXPECT_TRUE(exp.enabled.Get());
Expand Down Expand Up @@ -122,10 +109,17 @@ TEST(FieldTrialParserTest, ParsesOptionalParameters) {
EXPECT_FALSE(optional_string.Get().has_value());
}
TEST(FieldTrialParserTest, ParsesCustomEnumParameter) {
FieldTrialParameter<CustomEnum> my_enum("e", CustomEnum::kDefault);
FieldTrialEnum<CustomEnum> my_enum("e", CustomEnum::kDefault,
{{"default", CustomEnum::kDefault},
{"red", CustomEnum::kRed},
{"blue", CustomEnum::kBlue}});
ParseFieldTrial({&my_enum}, "");
EXPECT_EQ(my_enum.Get(), CustomEnum::kDefault);
ParseFieldTrial({&my_enum}, "e:red");
EXPECT_EQ(my_enum.Get(), CustomEnum::kRed);
ParseFieldTrial({&my_enum}, "e:2");
EXPECT_EQ(my_enum.Get(), CustomEnum::kBlue);
ParseFieldTrial({&my_enum}, "e:5");
EXPECT_EQ(my_enum.Get(), CustomEnum::kBlue);
}
} // namespace webrtc

0 comments on commit 2c74d85

Please sign in to comment.