1 //===-- ReproducerTest.cpp ------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
12 #include "lldb/Utility/FileSpec.h"
13 #include "lldb/Utility/Reproducer.h"
14 #include "lldb/Utility/ReproducerProvider.h"
15 #include "llvm/ADT/ScopeExit.h"
16 #include "llvm/Support/Error.h"
17 #include "llvm/Testing/Support/Error.h"
20 using namespace lldb_private
;
21 using namespace lldb_private::repro
;
23 class DummyProvider
: public repro::Provider
<DummyProvider
> {
26 static const char *name
;
27 static const char *file
;
30 DummyProvider(const FileSpec
&directory
) : Provider(directory
) {}
35 class YamlMultiProvider
36 : public MultiProvider
<YamlRecorder
, YamlMultiProvider
> {
39 static const char *name
;
40 static const char *file
;
43 YamlMultiProvider(const FileSpec
&directory
) : MultiProvider(directory
) {}
48 const char *DummyProvider::Info::name
= "dummy";
49 const char *DummyProvider::Info::file
= "dummy.yaml";
50 const char *YamlMultiProvider::Info::name
= "mutli";
51 const char *YamlMultiProvider::Info::file
= "mutli.yaml";
52 char DummyProvider::ID
= 0;
53 char YamlMultiProvider::ID
= 0;
55 class DummyReproducer
: public Reproducer
{
57 DummyReproducer() : Reproducer(){};
59 using Reproducer::SetCapture
;
64 YamlData(int i
) : i(i
) {}
68 inline bool operator==(const YamlData
&LHS
, const YamlData
&RHS
) {
69 return LHS
.i
== RHS
.i
;
72 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(YamlData
)
76 template <> struct MappingTraits
<YamlData
> {
77 static void mapping(IO
&io
, YamlData
&Y
) { io
.mapRequired("i", Y
.i
); };
82 TEST(ReproducerTest
, SetCapture
) {
83 DummyReproducer reproducer
;
85 // Initially both generator and loader are unset.
86 EXPECT_EQ(nullptr, reproducer
.GetGenerator());
87 EXPECT_EQ(nullptr, reproducer
.GetLoader());
89 // Enable capture and check that means we have a generator.
91 reproducer
.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix
)),
93 EXPECT_NE(nullptr, reproducer
.GetGenerator());
94 EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix
),
95 reproducer
.GetGenerator()->GetRoot());
96 EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix
),
97 reproducer
.GetReproducerPath());
99 // Ensure that we cannot enable replay.
100 EXPECT_EQ(nullptr, reproducer
.GetLoader());
102 // Ensure we can disable the generator again.
103 EXPECT_THAT_ERROR(reproducer
.SetCapture(llvm::None
), Succeeded());
104 EXPECT_EQ(nullptr, reproducer
.GetGenerator());
105 EXPECT_EQ(nullptr, reproducer
.GetLoader());
108 TEST(GeneratorTest
, Create
) {
109 DummyReproducer reproducer
;
112 reproducer
.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix
)),
114 auto &generator
= *reproducer
.GetGenerator();
116 auto *provider
= generator
.Create
<DummyProvider
>();
117 EXPECT_NE(nullptr, provider
);
118 EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix
),
119 provider
->GetRoot());
122 TEST(GeneratorTest
, Get
) {
123 DummyReproducer reproducer
;
126 reproducer
.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix
)),
128 auto &generator
= *reproducer
.GetGenerator();
130 auto *provider
= generator
.Create
<DummyProvider
>();
131 EXPECT_NE(nullptr, provider
);
133 auto *provider_alt
= generator
.Get
<DummyProvider
>();
134 EXPECT_EQ(provider
, provider_alt
);
137 TEST(GeneratorTest
, GetOrCreate
) {
138 DummyReproducer reproducer
;
141 reproducer
.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix
)),
143 auto &generator
= *reproducer
.GetGenerator();
145 auto &provider
= generator
.GetOrCreate
<DummyProvider
>();
146 EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix
),
149 auto &provider_alt
= generator
.GetOrCreate
<DummyProvider
>();
150 EXPECT_EQ(&provider
, &provider_alt
);
153 TEST(GeneratorTest
, YamlMultiProvider
) {
154 SmallString
<128> root
;
155 std::error_code ec
= llvm::sys::fs::createUniqueDirectory("reproducer", root
);
156 ASSERT_FALSE(static_cast<bool>(ec
));
158 auto cleanup
= llvm::make_scope_exit(
159 [&] { EXPECT_FALSE(llvm::sys::fs::remove_directories(root
.str())); });
167 DummyReproducer reproducer
;
168 EXPECT_THAT_ERROR(reproducer
.SetCapture(FileSpec(root
.str())), Succeeded());
170 auto &generator
= *reproducer
.GetGenerator();
171 auto *provider
= generator
.Create
<YamlMultiProvider
>();
172 ASSERT_NE(nullptr, provider
);
174 auto *recorder
= provider
->GetNewRecorder();
175 ASSERT_NE(nullptr, recorder
);
176 recorder
->Record(data0
);
177 recorder
->Record(data1
);
179 recorder
= provider
->GetNewRecorder();
180 ASSERT_NE(nullptr, recorder
);
181 recorder
->Record(data2
);
182 recorder
->Record(data3
);