1 //===-- JSON Tests --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
18 using testing::ExplainMatchResult
;
20 using testing::Pointwise
;
23 namespace libc_benchmarks
{
29 Runtime
{HostState
{"CpuName",
31 {CacheInfo
{"A", 1, 2, 3}, CacheInfo
{"B", 4, 5, 6}}},
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)}};
40 static std::string
serializeToString(const Study
&S
) {
42 raw_string_ostream
RSO(Buffer
);
43 json::OStream
JOS(RSO
);
44 serializeToJson(S
, JOS
);
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
)),
58 auto equals(const HostState
&H
) -> auto {
60 Field(&HostState::CpuName
, H
.CpuName
),
61 Field(&HostState::CpuFrequency
, H
.CpuFrequency
),
62 Field(&HostState::Caches
, Pointwise(EqualsCacheInfo(), H
.Caches
)));
65 auto equals(const StudyConfiguration
&SC
) -> auto {
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
));
76 auto equals(const BenchmarkOptions
&BO
) -> auto {
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
));
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
)));
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
));
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
);
114 TEST(JsonTest
, SupplementaryField
) {
115 auto Failure
= parseJsonStudy(R
"({
119 EXPECT_EQ(toString(Failure
.takeError()), "Unknown field: UnknownField");
122 TEST(JsonTest
, InvalidType
) {
123 auto Failure
= parseJsonStudy(R
"({
127 EXPECT_EQ(toString(Failure
.takeError()), "Expected JSON Object");
130 TEST(JsonTest
, InvalidDuration
) {
131 auto Failure
= parseJsonStudy(R
"({
133 "BenchmarkOptions
": {
134 "MinDuration
": "Duration should be a Number
"
139 EXPECT_EQ(toString(Failure
.takeError()), "Can't parse Duration");
142 TEST(JsonTest
, InvalidAlignType
) {
143 auto Failure
= parseJsonStudy(R
"({
145 "AccessAlignment
": "Align should be an Integer
"
149 EXPECT_EQ(toString(Failure
.takeError()), "Can't parse Align, not an Integer");
152 TEST(JsonTest
, InvalidAlign
) {
153 auto Failure
= parseJsonStudy(R
"({
159 EXPECT_EQ(toString(Failure
.takeError()),
160 "Can't parse Align, not a power of two");
163 TEST(JsonTest
, InvalidBenchmarkLogType
) {
164 auto Failure
= parseJsonStudy(R
"({
172 EXPECT_EQ(toString(Failure
.takeError()),
173 "Can't parse BenchmarkLog, not a String");
176 TEST(JsonTest
, InvalidBenchmarkLog
) {
177 auto Failure
= parseJsonStudy(R
"({
185 EXPECT_EQ(toString(Failure
.takeError()),
186 "Can't parse BenchmarkLog, invalid value 'Unknown'");
190 } // namespace libc_benchmarks