blob: e06841221e0d105331d34302a810af8eb27e1428 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_INSPECT_TESTING_CPP_INSPECT_H_
#define LIB_INSPECT_TESTING_CPP_INSPECT_H_
#include <lib/inspect/cpp/reader.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace inspect {
// Printers for inspect types.
void PrintTo(const PropertyValue& property, std::ostream* os);
void PrintTo(const NodeValue& node, std::ostream* os);
// Printer for Hierarchy wrapper.
void PrintTo(const Hierarchy& hierarchy, std::ostream* os);
namespace testing {
// Type for a matcher matching a Node.
using NodeMatcher = ::testing::Matcher<const NodeValue&>;
// Type for a matcher matching a vector of properties.
using PropertiesMatcher = ::testing::Matcher<const std::vector<PropertyValue>&>;
// Type for a matcher that matches a base path on an |Hierarchy|.
using PrefixPathMatcher = ::testing::Matcher<const std::vector<std::string>&>;
// Type for a matcher that matches a vector of |Hierarchy| children.
using ChildrenMatcher = ::testing::Matcher<const std::vector<Hierarchy>&>;
namespace internal {
// Matcher interface to check the name of an inspect Nodes.
class NameMatchesMatcher : public ::testing::MatcherInterface<const NodeValue&> {
public:
NameMatchesMatcher(std::string name);
bool MatchAndExplain(const NodeValue& obj,
::testing::MatchResultListener* listener) const override;
void DescribeTo(::std::ostream* os) const override;
void DescribeNegationTo(::std::ostream* os) const override;
private:
std::string name_;
};
// Matcher interface to check the list of Node properties.
class PropertyListMatcher : public ::testing::MatcherInterface<const NodeValue&> {
public:
PropertyListMatcher(PropertiesMatcher matcher);
bool MatchAndExplain(const NodeValue& obj,
::testing::MatchResultListener* listener) const override;
void DescribeTo(::std::ostream* os) const override;
void DescribeNegationTo(::std::ostream* os) const override;
private:
PropertiesMatcher matcher_;
};
} // namespace internal
// Matches against the name of an Inspect Node.
// Example:
// EXPECT_THAT(node, NameMatches("objects"));
::testing::Matcher<const NodeValue&> NameMatches(std::string name);
// Matches against the property list of an Inspect Node.
// Example:
// EXPECT_THAT(node, AllOf(PropertyList(::testing::IsEmpty())));
::testing::Matcher<const NodeValue&> PropertyList(PropertiesMatcher matcher);
// Matches a particular StringProperty with the given name using the given matcher.
::testing::Matcher<const PropertyValue&> StringIs(const std::string& name,
::testing::Matcher<std::string> matcher);
// Matches a particular ByteVectorProperty with the given name using the given matcher.
::testing::Matcher<const PropertyValue&> ByteVectorIs(
const std::string& name, ::testing::Matcher<std::vector<uint8_t>> matcher);
// Matches a particular IntProperty with the given name using the given matcher.
::testing::Matcher<const PropertyValue&> IntIs(const std::string& name,
::testing::Matcher<int64_t> matcher);
// Matches a particular UintProperty with the given name using the given matcher.
::testing::Matcher<const PropertyValue&> UintIs(const std::string& name,
::testing::Matcher<uint64_t> matcher);
// Matches a particular DoubleProperty with the given name using the given matcher.
::testing::Matcher<const PropertyValue&> DoubleIs(const std::string& name,
::testing::Matcher<double> matcher);
// Matches a particular BoolProperty with the given name using the given matcher.
::testing::Matcher<const PropertyValue&> BoolIs(const std::string& name,
::testing::Matcher<bool> matcher);
// Matches the values of an integer array.
::testing::Matcher<const PropertyValue&> IntArrayIs(const std::string& name,
::testing::Matcher<std::vector<int64_t>>);
// Matches the values of an unsigned integer array.
::testing::Matcher<const PropertyValue&> UintArrayIs(const std::string& name,
::testing::Matcher<std::vector<uint64_t>>);
// Matches the values of a double width floating point number array.
::testing::Matcher<const PropertyValue&> DoubleArrayIs(const std::string& name,
::testing::Matcher<std::vector<double>>);
// Matches the display format of a numeric array value.
::testing::Matcher<const PropertyValue&> ArrayDisplayFormatIs(ArrayDisplayFormat format);
// Matcher for the object inside an Hierarchy.
::testing::Matcher<const Hierarchy&> NodeMatches(NodeMatcher matcher);
// DEPRECATED: Compatibility for downstream clients.
// TODO(fxbug.dev/4582): Remove this.
::testing::Matcher<const Hierarchy&> ObjectMatches(NodeMatcher matcher);
// Matcher for the base path inside an Hierarchy.
::testing::Matcher<const Hierarchy&> PrefixPathMatches(PrefixPathMatcher matcher);
// Matcher for the children of the object in an Hierarchy.
::testing::Matcher<const Hierarchy&> ChildrenMatch(ChildrenMatcher matcher);
// Computes the bucket index for a value in a linear histogram.
// |total_buckets| is the number of buckets initially defined when the histogram
// property was created plus 2 (overflow and underflow).
template <typename T>
size_t ComputeLinearBucketIndex(T floor, T step_size, size_t total_buckets, T value) {
size_t ret = 0;
while (value >= floor && ret < total_buckets - 1) {
floor += step_size;
ret++;
}
return ret;
}
// Computes the bucket index for a value in an exponential histogram.
// |total_buckets| is the number of buckets initially defined when the histogram
// property was created plus 2 (overflow and underflow).
template <typename T>
size_t ComputeExponentialBucketIndex(T floor, T initial_step, T step_multiplier,
size_t total_buckets, T value) {
T current_floor = floor;
T current_step = initial_step;
size_t ret = 0;
while (value >= current_floor && ret < total_buckets - 1) {
current_floor = floor + current_step;
current_step *= step_multiplier;
ret++;
}
return ret;
}
// Creates the expected contents of a linear histogram given parameters and
// values.
template <typename T>
std::vector<T> CreateExpectedLinearHistogramContents(T floor, T step_size, size_t buckets,
const std::vector<T>& values) {
// Linear Histogram arrays contain 2 fields with metadata.
const size_t underflow_bucket_offset = 2;
// |buckets| + 1 underflow bucket + 1 overflow bucket
const size_t total_buckets = 2 + buckets;
const size_t array_size = underflow_bucket_offset + total_buckets;
std::vector<T> expected = {floor, step_size};
expected.resize(array_size);
for (T value : values) {
expected[underflow_bucket_offset +
ComputeLinearBucketIndex(floor, step_size, total_buckets, value)]++;
}
return expected;
}
// Creates the expected contents of an exponential histogram given parameters
// and values.
template <typename T>
std::vector<T> CreateExpectedExponentialHistogramContents(T floor, T initial_step,
T step_multiplier, size_t buckets,
const std::vector<T>& values) {
// Exp. Histogram arrays contain 3 fields with metadata.
const size_t underflow_bucket_offset = 3;
// |buckets| + 1 underflow bucket + 1 overflow bucket
const size_t total_buckets = 2 + buckets;
const size_t array_size = underflow_bucket_offset + total_buckets;
std::vector<T> expected = {floor, initial_step, step_multiplier};
expected.resize(array_size);
for (T value : values) {
expected[underflow_bucket_offset + ComputeExponentialBucketIndex(floor, initial_step,
step_multiplier, total_buckets,
value)]++;
}
return expected;
}
} // namespace testing
} // namespace inspect
#endif // LIB_INSPECT_TESTING_CPP_INSPECT_H_