180814287SRaphael Isemann //===-- ReproducerTest.cpp ------------------------------------------------===//
268ed93d2SJonas Devlieghere //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668ed93d2SJonas Devlieghere //
768ed93d2SJonas Devlieghere //===----------------------------------------------------------------------===//
868ed93d2SJonas Devlieghere 
968ed93d2SJonas Devlieghere #include "gmock/gmock.h"
1068ed93d2SJonas Devlieghere #include "gtest/gtest.h"
1168ed93d2SJonas Devlieghere 
12*bb894b97SJonas Devlieghere #include "lldb/Utility/FileSpec.h"
13*bb894b97SJonas Devlieghere #include "lldb/Utility/Reproducer.h"
14*bb894b97SJonas Devlieghere #include "lldb/Utility/ReproducerProvider.h"
15169c8320SJonas Devlieghere #include "llvm/ADT/ScopeExit.h"
1668ed93d2SJonas Devlieghere #include "llvm/Support/Error.h"
1768ed93d2SJonas Devlieghere #include "llvm/Testing/Support/Error.h"
1868ed93d2SJonas Devlieghere 
1968ed93d2SJonas Devlieghere using namespace llvm;
2068ed93d2SJonas Devlieghere using namespace lldb_private;
2168ed93d2SJonas Devlieghere using namespace lldb_private::repro;
2268ed93d2SJonas Devlieghere 
23ef96e985SJonas Devlieghere class DummyProvider : public repro::Provider<DummyProvider> {
24ef96e985SJonas Devlieghere public:
25ef96e985SJonas Devlieghere   struct Info {
2617f277d7SJonas Devlieghere     static const char *name;
2717f277d7SJonas Devlieghere     static const char *file;
2817f277d7SJonas Devlieghere   };
2917f277d7SJonas Devlieghere 
DummyProvider(const FileSpec & directory)3017f277d7SJonas Devlieghere   DummyProvider(const FileSpec &directory) : Provider(directory) {}
3168ed93d2SJonas Devlieghere 
3268ed93d2SJonas Devlieghere   static char ID;
3368ed93d2SJonas Devlieghere };
3468ed93d2SJonas Devlieghere 
35169c8320SJonas Devlieghere class YamlMultiProvider
36169c8320SJonas Devlieghere     : public MultiProvider<YamlRecorder, YamlMultiProvider> {
37169c8320SJonas Devlieghere public:
38169c8320SJonas Devlieghere   struct Info {
39169c8320SJonas Devlieghere     static const char *name;
40169c8320SJonas Devlieghere     static const char *file;
41169c8320SJonas Devlieghere   };
42169c8320SJonas Devlieghere 
YamlMultiProvider(const FileSpec & directory)43169c8320SJonas Devlieghere   YamlMultiProvider(const FileSpec &directory) : MultiProvider(directory) {}
44169c8320SJonas Devlieghere 
45169c8320SJonas Devlieghere   static char ID;
46169c8320SJonas Devlieghere };
47169c8320SJonas Devlieghere 
48ef96e985SJonas Devlieghere const char *DummyProvider::Info::name = "dummy";
49ef96e985SJonas Devlieghere const char *DummyProvider::Info::file = "dummy.yaml";
50169c8320SJonas Devlieghere const char *YamlMultiProvider::Info::name = "mutli";
51169c8320SJonas Devlieghere const char *YamlMultiProvider::Info::file = "mutli.yaml";
52169c8320SJonas Devlieghere char DummyProvider::ID = 0;
53169c8320SJonas Devlieghere char YamlMultiProvider::ID = 0;
54ef96e985SJonas Devlieghere 
5515eacd74SJonas Devlieghere class DummyReproducer : public Reproducer {
5615eacd74SJonas Devlieghere public:
DummyReproducer()5715eacd74SJonas Devlieghere   DummyReproducer() : Reproducer(){};
5815eacd74SJonas Devlieghere 
5915eacd74SJonas Devlieghere   using Reproducer::SetCapture;
6015eacd74SJonas Devlieghere };
6115eacd74SJonas Devlieghere 
62169c8320SJonas Devlieghere struct YamlData {
YamlDataYamlData63169c8320SJonas Devlieghere   YamlData() : i(-1) {}
YamlDataYamlData64169c8320SJonas Devlieghere   YamlData(int i) : i(i) {}
65169c8320SJonas Devlieghere   int i;
66169c8320SJonas Devlieghere };
67169c8320SJonas Devlieghere 
operator ==(const YamlData & LHS,const YamlData & RHS)68169c8320SJonas Devlieghere inline bool operator==(const YamlData &LHS, const YamlData &RHS) {
69169c8320SJonas Devlieghere   return LHS.i == RHS.i;
70169c8320SJonas Devlieghere }
71169c8320SJonas Devlieghere 
72169c8320SJonas Devlieghere LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(YamlData)
73169c8320SJonas Devlieghere 
74169c8320SJonas Devlieghere namespace llvm {
75169c8320SJonas Devlieghere namespace yaml {
76169c8320SJonas Devlieghere template <> struct MappingTraits<YamlData> {
mappingllvm::yaml::MappingTraits77169c8320SJonas Devlieghere   static void mapping(IO &io, YamlData &Y) { io.mapRequired("i", Y.i); };
78169c8320SJonas Devlieghere };
79169c8320SJonas Devlieghere } // namespace yaml
80169c8320SJonas Devlieghere } // namespace llvm
8168ed93d2SJonas Devlieghere 
TEST(ReproducerTest,SetCapture)8268ed93d2SJonas Devlieghere TEST(ReproducerTest, SetCapture) {
8315eacd74SJonas Devlieghere   DummyReproducer reproducer;
8468ed93d2SJonas Devlieghere 
8568ed93d2SJonas Devlieghere   // Initially both generator and loader are unset.
8668ed93d2SJonas Devlieghere   EXPECT_EQ(nullptr, reproducer.GetGenerator());
8768ed93d2SJonas Devlieghere   EXPECT_EQ(nullptr, reproducer.GetLoader());
8868ed93d2SJonas Devlieghere 
8968ed93d2SJonas Devlieghere   // Enable capture and check that means we have a generator.
90097ba759SJonas Devlieghere   EXPECT_THAT_ERROR(
91b0921dafSJonas Devlieghere       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
9268ed93d2SJonas Devlieghere       Succeeded());
9368ed93d2SJonas Devlieghere   EXPECT_NE(nullptr, reproducer.GetGenerator());
94b0921dafSJonas Devlieghere   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
95097ba759SJonas Devlieghere             reproducer.GetGenerator()->GetRoot());
96b0921dafSJonas Devlieghere   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
97097ba759SJonas Devlieghere             reproducer.GetReproducerPath());
9868ed93d2SJonas Devlieghere 
9968ed93d2SJonas Devlieghere   // Ensure that we cannot enable replay.
10068ed93d2SJonas Devlieghere   EXPECT_EQ(nullptr, reproducer.GetLoader());
10168ed93d2SJonas Devlieghere 
10268ed93d2SJonas Devlieghere   // Ensure we can disable the generator again.
10368ed93d2SJonas Devlieghere   EXPECT_THAT_ERROR(reproducer.SetCapture(llvm::None), Succeeded());
10468ed93d2SJonas Devlieghere   EXPECT_EQ(nullptr, reproducer.GetGenerator());
10568ed93d2SJonas Devlieghere   EXPECT_EQ(nullptr, reproducer.GetLoader());
10668ed93d2SJonas Devlieghere }
10768ed93d2SJonas Devlieghere 
TEST(GeneratorTest,Create)10868ed93d2SJonas Devlieghere TEST(GeneratorTest, Create) {
10915eacd74SJonas Devlieghere   DummyReproducer reproducer;
11068ed93d2SJonas Devlieghere 
111097ba759SJonas Devlieghere   EXPECT_THAT_ERROR(
112b0921dafSJonas Devlieghere       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
11368ed93d2SJonas Devlieghere       Succeeded());
11468ed93d2SJonas Devlieghere   auto &generator = *reproducer.GetGenerator();
11568ed93d2SJonas Devlieghere 
11668ed93d2SJonas Devlieghere   auto *provider = generator.Create<DummyProvider>();
11768ed93d2SJonas Devlieghere   EXPECT_NE(nullptr, provider);
118b0921dafSJonas Devlieghere   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
119097ba759SJonas Devlieghere             provider->GetRoot());
12068ed93d2SJonas Devlieghere }
12168ed93d2SJonas Devlieghere 
TEST(GeneratorTest,Get)12268ed93d2SJonas Devlieghere TEST(GeneratorTest, Get) {
12315eacd74SJonas Devlieghere   DummyReproducer reproducer;
12468ed93d2SJonas Devlieghere 
125097ba759SJonas Devlieghere   EXPECT_THAT_ERROR(
126b0921dafSJonas Devlieghere       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
12768ed93d2SJonas Devlieghere       Succeeded());
12868ed93d2SJonas Devlieghere   auto &generator = *reproducer.GetGenerator();
12968ed93d2SJonas Devlieghere 
13068ed93d2SJonas Devlieghere   auto *provider = generator.Create<DummyProvider>();
13168ed93d2SJonas Devlieghere   EXPECT_NE(nullptr, provider);
13268ed93d2SJonas Devlieghere 
13368ed93d2SJonas Devlieghere   auto *provider_alt = generator.Get<DummyProvider>();
13468ed93d2SJonas Devlieghere   EXPECT_EQ(provider, provider_alt);
13568ed93d2SJonas Devlieghere }
13668ed93d2SJonas Devlieghere 
TEST(GeneratorTest,GetOrCreate)13768ed93d2SJonas Devlieghere TEST(GeneratorTest, GetOrCreate) {
13815eacd74SJonas Devlieghere   DummyReproducer reproducer;
13968ed93d2SJonas Devlieghere 
140097ba759SJonas Devlieghere   EXPECT_THAT_ERROR(
141b0921dafSJonas Devlieghere       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
14268ed93d2SJonas Devlieghere       Succeeded());
14368ed93d2SJonas Devlieghere   auto &generator = *reproducer.GetGenerator();
14468ed93d2SJonas Devlieghere 
14568ed93d2SJonas Devlieghere   auto &provider = generator.GetOrCreate<DummyProvider>();
146b0921dafSJonas Devlieghere   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
147097ba759SJonas Devlieghere             provider.GetRoot());
14868ed93d2SJonas Devlieghere 
14968ed93d2SJonas Devlieghere   auto &provider_alt = generator.GetOrCreate<DummyProvider>();
15068ed93d2SJonas Devlieghere   EXPECT_EQ(&provider, &provider_alt);
15168ed93d2SJonas Devlieghere }
152169c8320SJonas Devlieghere 
TEST(GeneratorTest,YamlMultiProvider)153169c8320SJonas Devlieghere TEST(GeneratorTest, YamlMultiProvider) {
154169c8320SJonas Devlieghere   SmallString<128> root;
155169c8320SJonas Devlieghere   std::error_code ec = llvm::sys::fs::createUniqueDirectory("reproducer", root);
156169c8320SJonas Devlieghere   ASSERT_FALSE(static_cast<bool>(ec));
157169c8320SJonas Devlieghere 
158169c8320SJonas Devlieghere   auto cleanup = llvm::make_scope_exit(
159169c8320SJonas Devlieghere       [&] { EXPECT_FALSE(llvm::sys::fs::remove_directories(root.str())); });
160169c8320SJonas Devlieghere 
161169c8320SJonas Devlieghere   YamlData data0(0);
162169c8320SJonas Devlieghere   YamlData data1(1);
163169c8320SJonas Devlieghere   YamlData data2(2);
164169c8320SJonas Devlieghere   YamlData data3(3);
165169c8320SJonas Devlieghere 
166169c8320SJonas Devlieghere   {
167169c8320SJonas Devlieghere     DummyReproducer reproducer;
168169c8320SJonas Devlieghere     EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec(root.str())), Succeeded());
169169c8320SJonas Devlieghere 
170169c8320SJonas Devlieghere     auto &generator = *reproducer.GetGenerator();
171169c8320SJonas Devlieghere     auto *provider = generator.Create<YamlMultiProvider>();
172169c8320SJonas Devlieghere     ASSERT_NE(nullptr, provider);
173169c8320SJonas Devlieghere 
174169c8320SJonas Devlieghere     auto *recorder = provider->GetNewRecorder();
175169c8320SJonas Devlieghere     ASSERT_NE(nullptr, recorder);
176169c8320SJonas Devlieghere     recorder->Record(data0);
177169c8320SJonas Devlieghere     recorder->Record(data1);
178169c8320SJonas Devlieghere 
179169c8320SJonas Devlieghere     recorder = provider->GetNewRecorder();
180169c8320SJonas Devlieghere     ASSERT_NE(nullptr, recorder);
181169c8320SJonas Devlieghere     recorder->Record(data2);
182169c8320SJonas Devlieghere     recorder->Record(data3);
183169c8320SJonas Devlieghere 
184169c8320SJonas Devlieghere     generator.Keep();
185169c8320SJonas Devlieghere   }
186169c8320SJonas Devlieghere }
187