xref: /llvm-project/libc/benchmarks/JSONTest.cpp (revision deae7e982a3b08996455e2cdfdc5062bf37895a3)
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-exception
6 //
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 
17 using testing::AllOf;
18 using testing::ExplainMatchResult;
19 using testing::Field;
20 using testing::Pointwise;
21 
22 namespace llvm {
23 namespace libc_benchmarks {
24 namespace {
25 
getStudy()26 Study 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 
serializeToString(const Study & S)40 static 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 
48 MATCHER(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 
equals(const HostState & H)58 auto 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 
equals(const StudyConfiguration & SC)65 auto 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 
equals(const BenchmarkOptions & BO)76 auto 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 
equals(const Runtime & RI)89 auto 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 
equals(const Study & S)96 auto 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 
TEST(JsonTest,RoundTrip)103 TEST(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 
TEST(JsonTest,SupplementaryField)114 TEST(JsonTest, SupplementaryField) {
115   auto Failure = parseJsonStudy(R"({
116       "UnknownField": 10
117     }
118   )");
119   EXPECT_EQ(toString(Failure.takeError()), "Unknown field: UnknownField");
120 }
121 
TEST(JsonTest,InvalidType)122 TEST(JsonTest, InvalidType) {
123   auto Failure = parseJsonStudy(R"({
124       "Runtime": 1
125     }
126   )");
127   EXPECT_EQ(toString(Failure.takeError()), "Expected JSON Object");
128 }
129 
TEST(JsonTest,InvalidDuration)130 TEST(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 
TEST(JsonTest,InvalidAlignType)142 TEST(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 
TEST(JsonTest,InvalidAlign)152 TEST(JsonTest, InvalidAlign) {
153   auto Failure = parseJsonStudy(R"({
154       "Configuration": {
155         "AccessAlignment": 3
156       }
157     }
158   )");
159   EXPECT_EQ(toString(Failure.takeError()),
160             "Can't parse Align, not a power of two");
161 }
162 
TEST(JsonTest,InvalidBenchmarkLogType)163 TEST(JsonTest, InvalidBenchmarkLogType) {
164   auto Failure = parseJsonStudy(R"({
165       "Runtime": {
166         "BenchmarkOptions":{
167           "Log": 3
168         }
169       }
170     }
171   )");
172   EXPECT_EQ(toString(Failure.takeError()),
173             "Can't parse BenchmarkLog, not a String");
174 }
175 
TEST(JsonTest,InvalidBenchmarkLog)176 TEST(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 } // namespace
190 } // namespace libc_benchmarks
191 } // namespace llvm
192