192 lines · cpp
1//===-- JSON Tests --------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "JSON.h"10#include "LibcBenchmark.h"11#include "LibcMemoryBenchmark.h"12#include "llvm/Support/JSON.h"13#include "llvm/Support/raw_ostream.h"14#include "gmock/gmock.h"15#include "gtest/gtest.h"16 17using testing::AllOf;18using testing::ExplainMatchResult;19using testing::Field;20using testing::Pointwise;21 22namespace llvm {23namespace libc_benchmarks {24namespace {25 26Study getStudy() {27 return Study{28 "StudyName",29 Runtime{HostState{"CpuName",30 123,31 {CacheInfo{"A", 1, 2, 3}, CacheInfo{"B", 4, 5, 6}}},32 456, 789,33 BenchmarkOptions{std::chrono::seconds(1), std::chrono::seconds(2),34 10, 100, 6, 100, 0.1, 2, BenchmarkLog::Full}},35 StudyConfiguration{std::string("Function"), 30U, false, 32U,36 std::string("Distribution"), Align(16), 3U},37 {std::chrono::seconds(3), std::chrono::seconds(4)}};38}39 40static std::string serializeToString(const Study &S) {41 std::string Buffer;42 raw_string_ostream RSO(Buffer);43 json::OStream JOS(RSO);44 serializeToJson(S, JOS);45 return Buffer;46}47 48MATCHER(EqualsCacheInfo, "") {49 const CacheInfo &A = ::testing::get<0>(arg);50 const CacheInfo &B = ::testing::get<1>(arg);51 return ExplainMatchResult(AllOf(Field(&CacheInfo::Type, B.Type),52 Field(&CacheInfo::Level, B.Level),53 Field(&CacheInfo::Size, B.Size),54 Field(&CacheInfo::NumSharing, B.NumSharing)),55 A, result_listener);56}57 58auto equals(const HostState &H) -> auto {59 return AllOf(60 Field(&HostState::CpuName, H.CpuName),61 Field(&HostState::CpuFrequency, H.CpuFrequency),62 Field(&HostState::Caches, Pointwise(EqualsCacheInfo(), H.Caches)));63}64 65auto equals(const StudyConfiguration &SC) -> auto {66 return AllOf(67 Field(&StudyConfiguration::Function, SC.Function),68 Field(&StudyConfiguration::NumTrials, SC.NumTrials),69 Field(&StudyConfiguration::IsSweepMode, SC.IsSweepMode),70 Field(&StudyConfiguration::SweepModeMaxSize, SC.SweepModeMaxSize),71 Field(&StudyConfiguration::SizeDistributionName, SC.SizeDistributionName),72 Field(&StudyConfiguration::AccessAlignment, SC.AccessAlignment),73 Field(&StudyConfiguration::MemcmpMismatchAt, SC.MemcmpMismatchAt));74}75 76auto equals(const BenchmarkOptions &BO) -> auto {77 return AllOf(78 Field(&BenchmarkOptions::MinDuration, BO.MinDuration),79 Field(&BenchmarkOptions::MaxDuration, BO.MaxDuration),80 Field(&BenchmarkOptions::InitialIterations, BO.InitialIterations),81 Field(&BenchmarkOptions::MaxIterations, BO.MaxIterations),82 Field(&BenchmarkOptions::MinSamples, BO.MinSamples),83 Field(&BenchmarkOptions::MaxSamples, BO.MaxSamples),84 Field(&BenchmarkOptions::Epsilon, BO.Epsilon),85 Field(&BenchmarkOptions::ScalingFactor, BO.ScalingFactor),86 Field(&BenchmarkOptions::Log, BO.Log));87}88 89auto equals(const Runtime &RI) -> auto {90 return AllOf(Field(&Runtime::Host, equals(RI.Host)),91 Field(&Runtime::BufferSize, RI.BufferSize),92 Field(&Runtime::BatchParameterCount, RI.BatchParameterCount),93 Field(&Runtime::BenchmarkOptions, equals(RI.BenchmarkOptions)));94}95 96auto equals(const Study &S) -> auto {97 return AllOf(Field(&Study::StudyName, S.StudyName),98 Field(&Study::Runtime, equals(S.Runtime)),99 Field(&Study::Configuration, equals(S.Configuration)),100 Field(&Study::Measurements, S.Measurements));101}102 103TEST(JsonTest, RoundTrip) {104 const Study S = getStudy();105 const auto Serialized = serializeToString(S);106 auto StudyOrError = parseJsonStudy(Serialized);107 if (auto Err = StudyOrError.takeError())108 EXPECT_FALSE(Err) << "Unexpected error : " << Err << "\n" << Serialized;109 const Study &Parsed = *StudyOrError;110 EXPECT_THAT(Parsed, equals(S)) << Serialized << "\n"111 << serializeToString(Parsed);112}113 114TEST(JsonTest, SupplementaryField) {115 auto Failure = parseJsonStudy(R"({116 "UnknownField": 10117 }118 )");119 EXPECT_EQ(toString(Failure.takeError()), "Unknown field: UnknownField");120}121 122TEST(JsonTest, InvalidType) {123 auto Failure = parseJsonStudy(R"({124 "Runtime": 1125 }126 )");127 EXPECT_EQ(toString(Failure.takeError()), "Expected JSON Object");128}129 130TEST(JsonTest, InvalidDuration) {131 auto Failure = parseJsonStudy(R"({132 "Runtime": {133 "BenchmarkOptions": {134 "MinDuration": "Duration should be a Number"135 }136 }137 }138 )");139 EXPECT_EQ(toString(Failure.takeError()), "Can't parse Duration");140}141 142TEST(JsonTest, InvalidAlignType) {143 auto Failure = parseJsonStudy(R"({144 "Configuration": {145 "AccessAlignment": "Align should be an Integer"146 }147 }148 )");149 EXPECT_EQ(toString(Failure.takeError()), "Can't parse Align, not an Integer");150}151 152TEST(JsonTest, InvalidAlign) {153 auto Failure = parseJsonStudy(R"({154 "Configuration": {155 "AccessAlignment": 3156 }157 }158 )");159 EXPECT_EQ(toString(Failure.takeError()),160 "Can't parse Align, not a power of two");161}162 163TEST(JsonTest, InvalidBenchmarkLogType) {164 auto Failure = parseJsonStudy(R"({165 "Runtime": {166 "BenchmarkOptions":{167 "Log": 3168 }169 }170 }171 )");172 EXPECT_EQ(toString(Failure.takeError()),173 "Can't parse BenchmarkLog, not a String");174}175 176TEST(JsonTest, InvalidBenchmarkLog) {177 auto Failure = parseJsonStudy(R"({178 "Runtime": {179 "BenchmarkOptions":{180 "Log": "Unknown"181 }182 }183 }184 )");185 EXPECT_EQ(toString(Failure.takeError()),186 "Can't parse BenchmarkLog, invalid value 'Unknown'");187}188 189} // namespace190} // namespace libc_benchmarks191} // namespace llvm192