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