1 //===-- ReproducerTest.cpp --------------------------------------*- C++ -*-===//
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 "gmock/gmock.h"
10 #include "gtest/gtest.h"
11 
12 #include "llvm/Support/Error.h"
13 #include "llvm/Testing/Support/Error.h"
14 
15 #include "lldb/Utility/FileSpec.h"
16 #include "lldb/Utility/Reproducer.h"
17 
18 using namespace llvm;
19 using namespace lldb_private;
20 using namespace lldb_private::repro;
21 
22 class DummyProvider : public repro::Provider<DummyProvider> {
23 public:
24   struct Info {
25     static const char *name;
26     static const char *file;
27   };
28 
29   DummyProvider(const FileSpec &directory) : Provider(directory) {}
30 
31   static char ID;
32 };
33 
34 const char *DummyProvider::Info::name = "dummy";
35 const char *DummyProvider::Info::file = "dummy.yaml";
36 
37 class DummyReproducer : public Reproducer {
38 public:
39   DummyReproducer() : Reproducer(){};
40 
41   using Reproducer::SetCapture;
42   using Reproducer::SetReplay;
43 };
44 
45 char DummyProvider::ID = 0;
46 
47 TEST(ReproducerTest, SetCapture) {
48   DummyReproducer reproducer;
49 
50   // Initially both generator and loader are unset.
51   EXPECT_EQ(nullptr, reproducer.GetGenerator());
52   EXPECT_EQ(nullptr, reproducer.GetLoader());
53 
54   // Enable capture and check that means we have a generator.
55   EXPECT_THAT_ERROR(
56       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
57       Succeeded());
58   EXPECT_NE(nullptr, reproducer.GetGenerator());
59   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
60             reproducer.GetGenerator()->GetRoot());
61   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
62             reproducer.GetReproducerPath());
63 
64   // Ensure that we cannot enable replay.
65   EXPECT_THAT_ERROR(
66       reproducer.SetReplay(FileSpec("//bogus/path", FileSpec::Style::posix)),
67       Failed());
68   EXPECT_EQ(nullptr, reproducer.GetLoader());
69 
70   // Ensure we can disable the generator again.
71   EXPECT_THAT_ERROR(reproducer.SetCapture(llvm::None), Succeeded());
72   EXPECT_EQ(nullptr, reproducer.GetGenerator());
73   EXPECT_EQ(nullptr, reproducer.GetLoader());
74 }
75 
76 TEST(ReproducerTest, SetReplay) {
77   DummyReproducer reproducer;
78 
79   // Initially both generator and loader are unset.
80   EXPECT_EQ(nullptr, reproducer.GetGenerator());
81   EXPECT_EQ(nullptr, reproducer.GetLoader());
82 
83   // Expected to fail because we can't load the index.
84   EXPECT_THAT_ERROR(
85       reproducer.SetReplay(FileSpec("//bogus/path", FileSpec::Style::posix)),
86       Failed());
87   // However the loader should still be set, which we check here.
88   EXPECT_NE(nullptr, reproducer.GetLoader());
89 
90   // Make sure the bogus path is correctly set.
91   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
92             reproducer.GetLoader()->GetRoot());
93   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
94             reproducer.GetReproducerPath());
95 
96   // Ensure that we cannot enable replay.
97   EXPECT_THAT_ERROR(
98       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
99       Failed());
100   EXPECT_EQ(nullptr, reproducer.GetGenerator());
101 }
102 
103 TEST(GeneratorTest, Create) {
104   DummyReproducer reproducer;
105 
106   EXPECT_THAT_ERROR(
107       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
108       Succeeded());
109   auto &generator = *reproducer.GetGenerator();
110 
111   auto *provider = generator.Create<DummyProvider>();
112   EXPECT_NE(nullptr, provider);
113   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
114             provider->GetRoot());
115 }
116 
117 TEST(GeneratorTest, Get) {
118   DummyReproducer reproducer;
119 
120   EXPECT_THAT_ERROR(
121       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
122       Succeeded());
123   auto &generator = *reproducer.GetGenerator();
124 
125   auto *provider = generator.Create<DummyProvider>();
126   EXPECT_NE(nullptr, provider);
127 
128   auto *provider_alt = generator.Get<DummyProvider>();
129   EXPECT_EQ(provider, provider_alt);
130 }
131 
132 TEST(GeneratorTest, GetOrCreate) {
133   DummyReproducer reproducer;
134 
135   EXPECT_THAT_ERROR(
136       reproducer.SetCapture(FileSpec("//bogus/path", FileSpec::Style::posix)),
137       Succeeded());
138   auto &generator = *reproducer.GetGenerator();
139 
140   auto &provider = generator.GetOrCreate<DummyProvider>();
141   EXPECT_EQ(FileSpec("//bogus/path", FileSpec::Style::posix),
142             provider.GetRoot());
143 
144   auto &provider_alt = generator.GetOrCreate<DummyProvider>();
145   EXPECT_EQ(&provider, &provider_alt);
146 }
147