forked from OSchip/llvm-project
199 lines
6.2 KiB
C++
199 lines
6.2 KiB
C++
|
//===-- JSON Tests --------------------------------------------------------===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "JSON.h"
|
||
|
#include "LibcBenchmark.h"
|
||
|
#include "LibcMemoryBenchmark.h"
|
||
|
#include "llvm/Support/JSON.h"
|
||
|
#include "llvm/Support/raw_ostream.h"
|
||
|
#include "gmock/gmock.h"
|
||
|
#include "gtest/gtest.h"
|
||
|
|
||
|
using testing::AllOf;
|
||
|
using testing::ExplainMatchResult;
|
||
|
using testing::Field;
|
||
|
using testing::Pointwise;
|
||
|
|
||
|
namespace llvm {
|
||
|
namespace libc_benchmarks {
|
||
|
namespace {
|
||
|
|
||
|
Study getStudy() {
|
||
|
return Study{
|
||
|
HostState{
|
||
|
"CpuName", 123, {CacheInfo{"A", 1, 2, 3}, CacheInfo{"B", 4, 5, 6}}},
|
||
|
BenchmarkOptions{std::chrono::seconds(1), std::chrono::seconds(2), 10,
|
||
|
100, 6, 100, 0.1, 2, BenchmarkLog::Full},
|
||
|
StudyConfiguration{2, 3, SizeRange{4, 5, 6}, Align(8), 9, 10},
|
||
|
{FunctionMeasurements{"A",
|
||
|
{Measurement{3, std::chrono::seconds(3)},
|
||
|
Measurement{3, std::chrono::seconds(4)}}},
|
||
|
FunctionMeasurements{"B", {}}}};
|
||
|
}
|
||
|
|
||
|
static std::string SerializeToString(const Study &S) {
|
||
|
std::string Buffer;
|
||
|
raw_string_ostream RSO(Buffer);
|
||
|
json::OStream JOS(RSO);
|
||
|
SerializeToJson(S, JOS);
|
||
|
return Buffer;
|
||
|
}
|
||
|
|
||
|
MATCHER(EqualsCacheInfo, "") {
|
||
|
const CacheInfo &A = ::testing::get<0>(arg);
|
||
|
const CacheInfo &B = ::testing::get<1>(arg);
|
||
|
return ExplainMatchResult(AllOf(Field(&CacheInfo::Type, B.Type),
|
||
|
Field(&CacheInfo::Level, B.Level),
|
||
|
Field(&CacheInfo::Size, B.Size),
|
||
|
Field(&CacheInfo::NumSharing, B.NumSharing)),
|
||
|
A, result_listener);
|
||
|
}
|
||
|
|
||
|
auto Equals(const HostState &H) -> auto {
|
||
|
return AllOf(
|
||
|
Field(&HostState::CpuName, H.CpuName),
|
||
|
Field(&HostState::CpuFrequency, H.CpuFrequency),
|
||
|
Field(&HostState::Caches, Pointwise(EqualsCacheInfo(), H.Caches)));
|
||
|
}
|
||
|
|
||
|
auto Equals(const BenchmarkOptions &BO) -> auto {
|
||
|
return AllOf(
|
||
|
Field(&BenchmarkOptions::MinDuration, BO.MinDuration),
|
||
|
Field(&BenchmarkOptions::MaxDuration, BO.MaxDuration),
|
||
|
Field(&BenchmarkOptions::InitialIterations, BO.InitialIterations),
|
||
|
Field(&BenchmarkOptions::MaxIterations, BO.MaxIterations),
|
||
|
Field(&BenchmarkOptions::MinSamples, BO.MinSamples),
|
||
|
Field(&BenchmarkOptions::MaxSamples, BO.MaxSamples),
|
||
|
Field(&BenchmarkOptions::Epsilon, BO.Epsilon),
|
||
|
Field(&BenchmarkOptions::ScalingFactor, BO.ScalingFactor),
|
||
|
Field(&BenchmarkOptions::Log, BO.Log));
|
||
|
}
|
||
|
|
||
|
auto Equals(const SizeRange &SR) -> auto {
|
||
|
return AllOf(Field(&SizeRange::From, SR.From), Field(&SizeRange::To, SR.To),
|
||
|
Field(&SizeRange::Step, SR.Step));
|
||
|
}
|
||
|
|
||
|
auto Equals(const StudyConfiguration &SC) -> auto {
|
||
|
return AllOf(
|
||
|
Field(&StudyConfiguration::Runs, SC.Runs),
|
||
|
Field(&StudyConfiguration::BufferSize, SC.BufferSize),
|
||
|
Field(&StudyConfiguration::Size, Equals(SC.Size)),
|
||
|
Field(&StudyConfiguration::AddressAlignment, SC.AddressAlignment),
|
||
|
Field(&StudyConfiguration::MemsetValue, SC.MemsetValue),
|
||
|
Field(&StudyConfiguration::MemcmpMismatchAt, SC.MemcmpMismatchAt));
|
||
|
}
|
||
|
|
||
|
MATCHER(EqualsMeasurement, "") {
|
||
|
const Measurement &A = ::testing::get<0>(arg);
|
||
|
const Measurement &B = ::testing::get<1>(arg);
|
||
|
return ExplainMatchResult(AllOf(Field(&Measurement::Size, B.Size),
|
||
|
Field(&Measurement::Runtime, B.Runtime)),
|
||
|
A, result_listener);
|
||
|
}
|
||
|
|
||
|
MATCHER(EqualsFunctions, "") {
|
||
|
const FunctionMeasurements &A = ::testing::get<0>(arg);
|
||
|
const FunctionMeasurements &B = ::testing::get<1>(arg);
|
||
|
return ExplainMatchResult(
|
||
|
AllOf(Field(&FunctionMeasurements::Name, B.Name),
|
||
|
Field(&FunctionMeasurements::Measurements,
|
||
|
Pointwise(EqualsMeasurement(), B.Measurements))),
|
||
|
A, result_listener);
|
||
|
}
|
||
|
|
||
|
auto Equals(const Study &S) -> auto {
|
||
|
return AllOf(
|
||
|
Field(&Study::Host, Equals(S.Host)),
|
||
|
Field(&Study::Options, Equals(S.Options)),
|
||
|
Field(&Study::Configuration, Equals(S.Configuration)),
|
||
|
Field(&Study::Functions, Pointwise(EqualsFunctions(), S.Functions)));
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, RoundTrip) {
|
||
|
const Study S = getStudy();
|
||
|
auto StudyOrError = ParseJsonStudy(SerializeToString(S));
|
||
|
if (auto Err = StudyOrError.takeError())
|
||
|
EXPECT_FALSE(Err) << "Unexpected error";
|
||
|
const Study &Parsed = *StudyOrError;
|
||
|
EXPECT_THAT(Parsed, Equals(S));
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, SupplementaryField) {
|
||
|
auto Failure = ParseJsonStudy(R"({
|
||
|
"UnknownField": 10
|
||
|
}
|
||
|
)");
|
||
|
EXPECT_EQ(toString(Failure.takeError()), "Unknown field: UnknownField");
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, InvalidType) {
|
||
|
auto Failure = ParseJsonStudy(R"({
|
||
|
"Options": 1
|
||
|
}
|
||
|
)");
|
||
|
EXPECT_EQ(toString(Failure.takeError()), "Expected JSON Object");
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, InvalidDuration) {
|
||
|
auto Failure = ParseJsonStudy(R"({
|
||
|
"Options": {
|
||
|
"MinDuration": "Duration should be a Number"
|
||
|
}
|
||
|
}
|
||
|
)");
|
||
|
EXPECT_EQ(toString(Failure.takeError()), "Can't parse Duration");
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, InvalidAlignType) {
|
||
|
auto Failure = ParseJsonStudy(R"({
|
||
|
"Configuration":{
|
||
|
"AddressAlignment": "Align should be an Integer"
|
||
|
}
|
||
|
}
|
||
|
)");
|
||
|
EXPECT_EQ(toString(Failure.takeError()), "Can't parse Align, not an Integer");
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, InvalidAlign) {
|
||
|
auto Failure = ParseJsonStudy(R"({
|
||
|
"Configuration":{
|
||
|
"AddressAlignment":3
|
||
|
}
|
||
|
}
|
||
|
)");
|
||
|
EXPECT_EQ(toString(Failure.takeError()),
|
||
|
"Can't parse Align, not a power of two");
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, InvalidBenchmarkLogType) {
|
||
|
auto Failure = ParseJsonStudy(R"({
|
||
|
"Options":{
|
||
|
"Log": 3
|
||
|
}
|
||
|
}
|
||
|
)");
|
||
|
EXPECT_EQ(toString(Failure.takeError()),
|
||
|
"Can't parse BenchmarkLog, not a String");
|
||
|
}
|
||
|
|
||
|
TEST(JsonTest, InvalidBenchmarkLog) {
|
||
|
auto Failure = ParseJsonStudy(R"({
|
||
|
"Options":{
|
||
|
"Log": "Unknown"
|
||
|
}
|
||
|
}
|
||
|
)");
|
||
|
EXPECT_EQ(toString(Failure.takeError()),
|
||
|
"Can't parse BenchmarkLog, invalid value 'Unknown'");
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
} // namespace libc_benchmarks
|
||
|
} // namespace llvm
|