This is part one of a mult-part change to revise some metrics. Several metrics are currently EventMetric type when they should be a simpler type. Test: Added unit tests for the new types. Also, re-ran existing tests. Verified playback works with Google Play, and re-ran Widevine GTS tests. Bug: 36220619 Change-Id: I2ec8fc355f66ad4834dd722aacd22541fb9c94ad
126 lines
4.4 KiB
C++
126 lines
4.4 KiB
C++
// Copyright 2017 Google Inc. All Rights Reserved.
|
|
//
|
|
// This file contains the helper classes and methods for using field tuples
|
|
// used by metrics classes to record variations of a single metric.
|
|
#ifndef WVCDM_METRICS_FIELD_TUPLES_H_
|
|
#define WVCDM_METRICS_FIELD_TUPLES_H_
|
|
|
|
#include <cstdarg>
|
|
#include <memory>
|
|
#include <ostream>
|
|
#include <sstream>
|
|
#include <stdint.h>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace wvcdm {
|
|
namespace metrics {
|
|
namespace util {
|
|
|
|
// This is a placeholder type for unused type parameters. It aids in supporting
|
|
// templated classes with "variable" type arguments.
|
|
struct Unused {
|
|
// Required for compilation. Should never be used.
|
|
inline friend std::ostream& operator<< (std::ostream& out, const Unused&)
|
|
{ return out; }
|
|
};
|
|
|
|
// This utility method formats the collection of field name/value pairs.
|
|
// The format of the string is:
|
|
//
|
|
// [{field:value[&field:value]*}]
|
|
//
|
|
// If there are no pairs, returns a blank string.
|
|
template<typename F1, typename F2, typename F3, typename F4>
|
|
std::string MakeFieldNameString(const std::vector<std::string>& field_names,
|
|
const F1 field1, const F2 field2,
|
|
const F3 field3, const F4 field4) {
|
|
std::stringstream field_name_and_values;
|
|
std::vector<std::string>::const_iterator field_name_iterator =
|
|
field_names.begin();
|
|
if (field_name_iterator == field_names.end()) {
|
|
return field_name_and_values.str();
|
|
}
|
|
// There is at least one name/value pair. Prepend open brace.
|
|
field_name_and_values << "{";
|
|
field_name_and_values << *field_name_iterator << ':' << field1;
|
|
if (++field_name_iterator == field_names.end()) {
|
|
field_name_and_values << "}";
|
|
return field_name_and_values.str();
|
|
}
|
|
field_name_and_values << '&' << *field_name_iterator << ':' << field2;
|
|
if (++field_name_iterator == field_names.end()) {
|
|
field_name_and_values << "}";
|
|
return field_name_and_values.str();
|
|
}
|
|
field_name_and_values << '&' << *field_name_iterator << ':' << field3;
|
|
if (++field_name_iterator == field_names.end()) {
|
|
field_name_and_values << "}";
|
|
return field_name_and_values.str();
|
|
}
|
|
field_name_and_values << '&' << *field_name_iterator << ':' << field4;
|
|
field_name_and_values << "}";
|
|
return field_name_and_values.str();
|
|
}
|
|
|
|
// This specialization of the helper method is a shortcut for class
|
|
// instances with no fields.
|
|
template<>
|
|
inline std::string MakeFieldNameString<Unused, Unused, Unused, Unused>(
|
|
const std::vector<std::string>& /* field_names */,
|
|
const Unused /* unused1 */, const Unused /* unused2 */,
|
|
const Unused /* unused3 */, const Unused /* unused4 */) {
|
|
return "";
|
|
}
|
|
|
|
// This helper function appends the field names to a vector of strings.
|
|
inline void AppendFieldNames(std::vector<std::string>* field_name_vector,
|
|
int field_count, ...) {
|
|
va_list field_names;
|
|
|
|
va_start(field_names, field_count);
|
|
for (int x = 0; x < field_count; x++) {
|
|
field_name_vector->push_back(va_arg(field_names, const char*));
|
|
}
|
|
va_end(field_names);
|
|
}
|
|
|
|
// These helper methods and FirstUnusedType assure that there is no mismatch
|
|
// between the specified types for metrics type parameters and the constructors
|
|
// and methods used for the specializations.
|
|
template <bool>
|
|
struct CompileAssert {};
|
|
#define COMPILE_ASSERT(expr, msg) \
|
|
typedef util::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
|
|
|
|
template <typename T> struct is_unused { static const bool value = false; };
|
|
template <> struct is_unused<Unused> { static const bool value = true; };
|
|
|
|
template <typename F1, typename F2, typename F3, typename F4>
|
|
class FirstUnusedType {
|
|
static const bool a = is_unused<F1>::value;
|
|
static const bool b = is_unused<F2>::value;
|
|
static const bool c = is_unused<F3>::value;
|
|
static const bool d = is_unused<F4>::value;
|
|
// Check that all types after the first Unused are also Unused.
|
|
COMPILE_ASSERT(a <= b, Invalid_Unused_At_Position_2);
|
|
COMPILE_ASSERT(b <= c, Invalid_Unused_At_Position_3);
|
|
COMPILE_ASSERT(c <= d, Invalid_Unused_At_Position_4);
|
|
|
|
public:
|
|
static const int value = 5 - (a + b + c + d);
|
|
};
|
|
|
|
// Asserts that no Unused types exist before N; after N, are all Unused types.
|
|
#define ASSERT_METRIC_UNUSED_START_FROM(N) \
|
|
COMPILE_ASSERT((\
|
|
util::FirstUnusedType<F1, F2, F3, F4>::value) == N, \
|
|
Unused_Start_From_##N)
|
|
|
|
} // namespace util
|
|
} // namespace metrics
|
|
} // namespace wvcdm
|
|
|
|
#endif // WVCDM_METRICS_FIELD_TUPLES_H_
|
|
|