[Lldb-commits] [PATCH] D83441: [ldb/Reproducers] Add YamlRecorder and MultiProvider
This revision was automatically updated to reflect the committed changes. JDevlieghere marked 5 inline comments as done. Closed by commit rG169c83208f37: [ldb/Reproducers] Add YamlRecorder and MultiProvider (authored by JDevlieghere). Herald added a project: LLDB. Changed prior to commit: https://reviews.llvm.org/D83441?vs=276597=277133#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83441/new/ https://reviews.llvm.org/D83441 Files: lldb/include/lldb/Utility/Reproducer.h lldb/source/API/SBDebugger.cpp lldb/source/Utility/Reproducer.cpp lldb/unittests/Utility/ReproducerTest.cpp Index: lldb/unittests/Utility/ReproducerTest.cpp === --- lldb/unittests/Utility/ReproducerTest.cpp +++ lldb/unittests/Utility/ReproducerTest.cpp @@ -9,6 +9,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/Error.h" #include "llvm/Testing/Support/Error.h" @@ -31,8 +32,25 @@ static char ID; }; +class YamlMultiProvider +: public MultiProvider { +public: + struct Info { +static const char *name; +static const char *file; + }; + + YamlMultiProvider(const FileSpec ) : MultiProvider(directory) {} + + static char ID; +}; + const char *DummyProvider::Info::name = "dummy"; const char *DummyProvider::Info::file = "dummy.yaml"; +const char *YamlMultiProvider::Info::name = "mutli"; +const char *YamlMultiProvider::Info::file = "mutli.yaml"; +char DummyProvider::ID = 0; +char YamlMultiProvider::ID = 0; class DummyReproducer : public Reproducer { public: @@ -42,7 +60,25 @@ using Reproducer::SetReplay; }; -char DummyProvider::ID = 0; +struct YamlData { + YamlData() : i(-1) {} + YamlData(int i) : i(i) {} + int i; +}; + +inline bool operator==(const YamlData , const YamlData ) { + return LHS.i == RHS.i; +} + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(YamlData) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO , YamlData ) { io.mapRequired("i", Y.i); }; +}; +} // namespace yaml +} // namespace llvm TEST(ReproducerTest, SetCapture) { DummyReproducer reproducer; @@ -144,3 +180,83 @@ auto _alt = generator.GetOrCreate(); EXPECT_EQ(, _alt); } + +TEST(GeneratorTest, YamlMultiProvider) { + SmallString<128> root; + std::error_code ec = llvm::sys::fs::createUniqueDirectory("reproducer", root); + ASSERT_FALSE(static_cast(ec)); + + auto cleanup = llvm::make_scope_exit( + [&] { EXPECT_FALSE(llvm::sys::fs::remove_directories(root.str())); }); + + YamlData data0(0); + YamlData data1(1); + YamlData data2(2); + YamlData data3(3); + + { +DummyReproducer reproducer; +EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec(root.str())), Succeeded()); + +auto = *reproducer.GetGenerator(); +auto *provider = generator.Create(); +ASSERT_NE(nullptr, provider); + +auto *recorder = provider->GetNewRecorder(); +ASSERT_NE(nullptr, recorder); +recorder->Record(data0); +recorder->Record(data1); + +recorder = provider->GetNewRecorder(); +ASSERT_NE(nullptr, recorder); +recorder->Record(data2); +recorder->Record(data3); + +generator.Keep(); + } + + { +DummyReproducer reproducer; +EXPECT_THAT_ERROR(reproducer.SetReplay(FileSpec(root.str())), Succeeded()); + +auto = *reproducer.GetLoader(); +std::unique_ptr> multi_loader = +repro::MultiLoader::Create(); + +// Read the first file. +{ + llvm::Optional file = multi_loader->GetNextFile(); + EXPECT_TRUE(static_cast(file)); + + auto buffer = llvm::MemoryBuffer::getFile(*file); + EXPECT_TRUE(static_cast(buffer)); + + yaml::Input yin((*buffer)->getBuffer()); + std::vector data; + yin >> data; + + ASSERT_EQ(data.size(), 2U); + EXPECT_THAT(data, testing::ElementsAre(data0, data1)); +} + +// Read the second file. +{ + llvm::Optional file = multi_loader->GetNextFile(); + EXPECT_TRUE(static_cast(file)); + + auto buffer = llvm::MemoryBuffer::getFile(*file); + EXPECT_TRUE(static_cast(buffer)); + + yaml::Input yin((*buffer)->getBuffer()); + std::vector data; + yin >> data; + + ASSERT_EQ(data.size(), 2U); + EXPECT_THAT(data, testing::ElementsAre(data2, data3)); +} + +// There is no third file. +llvm::Optional file = multi_loader->GetNextFile(); +EXPECT_FALSE(static_cast(file)); + } +} Index: lldb/source/Utility/Reproducer.cpp === --- lldb/source/Utility/Reproducer.cpp +++ lldb/source/Utility/Reproducer.cpp @@ -272,40 +272,15 @@ return std::move(recorder); } -DataRecorder *CommandProvider::GetNewDataRecorder() { - std::size_t i = m_data_recorders.size() + 1; - std::string filename = (llvm::Twine(Info::name) + llvm::Twine("-") + - llvm::Twine(i) +
[Lldb-commits] [PATCH] D83441: [ldb/Reproducers] Add YamlRecorder and MultiProvider
labath accepted this revision. labath added a comment. This revision is now accepted and ready to land. This seems fine. A bit more doxygen wouldn't hurt... Comment at: lldb/source/Utility/Reproducer.cpp:10 #include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBAssert.h" It doesn't look like this is actually needed. Comment at: lldb/unittests/Utility/ReproducerTest.cpp:65-66 +struct YamlData { + YamlData() : i(-1){}; + YamlData(int i) : i(i){}; + int i; superfluous semicolons Comment at: lldb/unittests/Utility/ReproducerTest.cpp:74-75 + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(YamlData) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(std::vector) + Are both of these needed? I would expect the first one to be enough... Comment at: lldb/unittests/Utility/ReproducerTest.cpp:240-242 + ASSERT_EQ(data.size(), 2U); + EXPECT_EQ(data[0], data0); + EXPECT_EQ(data[1], data1); `EXPECT_THAT(data, testing::ElementsAre(data0, data1));` CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83441/new/ https://reviews.llvm.org/D83441 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D83441: [ldb/Reproducers] Add YamlRecorder and MultiProvider
JDevlieghere updated this revision to Diff 276597. JDevlieghere added a comment. Use `ScopeExit` to cleanup reproducer after test completes. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D83441/new/ https://reviews.llvm.org/D83441 Files: lldb/include/lldb/Utility/Reproducer.h lldb/source/API/SBDebugger.cpp lldb/source/Utility/Reproducer.cpp lldb/unittests/Utility/ReproducerTest.cpp Index: lldb/unittests/Utility/ReproducerTest.cpp === --- lldb/unittests/Utility/ReproducerTest.cpp +++ lldb/unittests/Utility/ReproducerTest.cpp @@ -9,6 +9,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/Error.h" #include "llvm/Testing/Support/Error.h" @@ -31,8 +32,26 @@ static char ID; }; +class YamlMultiProvider +: public MultiProvider { +public: + struct Info { +static const char *name; +static const char *file; + }; + + YamlMultiProvider(const FileSpec ) + : MultiProvider(directory) {} + + static char ID; +}; + const char *DummyProvider::Info::name = "dummy"; const char *DummyProvider::Info::file = "dummy.yaml"; +const char *YamlMultiProvider::Info::name = "mutli"; +const char *YamlMultiProvider::Info::file = "mutli.yaml"; +char DummyProvider::ID = 0; +char YamlMultiProvider::ID = 0; class DummyReproducer : public Reproducer { public: @@ -42,7 +61,26 @@ using Reproducer::SetReplay; }; -char DummyProvider::ID = 0; +struct YamlData { + YamlData() : i(-1){}; + YamlData(int i) : i(i){}; + int i; +}; + +inline bool operator==(const YamlData , const YamlData ) { + return LHS.i == RHS.i; +} + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(YamlData) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(std::vector) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO , YamlData ) { io.mapRequired("i", Y.i); }; +}; +} // namespace yaml +} // namespace llvm TEST(ReproducerTest, SetCapture) { DummyReproducer reproducer; @@ -144,3 +182,85 @@ auto _alt = generator.GetOrCreate(); EXPECT_EQ(, _alt); } + +TEST(GeneratorTest, YamlMultiProvider) { + SmallString<128> root; + std::error_code ec = llvm::sys::fs::createUniqueDirectory("reproducer", root); + ASSERT_FALSE(static_cast(ec)); + + auto cleanup = llvm::make_scope_exit( + [&] { EXPECT_FALSE(llvm::sys::fs::remove_directories(root.str())); }); + + YamlData data0(0); + YamlData data1(1); + YamlData data2(2); + YamlData data3(3); + + { +DummyReproducer reproducer; +EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec(root.str())), Succeeded()); + +auto = *reproducer.GetGenerator(); +auto *provider = generator.Create(); +ASSERT_NE(nullptr, provider); + +auto *recorder = provider->GetNewRecorder(); +ASSERT_NE(nullptr, recorder); +recorder->Record(data0); +recorder->Record(data1); + +recorder = provider->GetNewRecorder(); +ASSERT_NE(nullptr, recorder); +recorder->Record(data2); +recorder->Record(data3); + +generator.Keep(); + } + + { +DummyReproducer reproducer; +EXPECT_THAT_ERROR(reproducer.SetReplay(FileSpec(root.str())), Succeeded()); + +auto = *reproducer.GetLoader(); +std::unique_ptr> multi_loader = +repro::MultiLoader::Create(); + +// Read the first file. +{ + llvm::Optional file = multi_loader->GetNextFile(); + EXPECT_TRUE(static_cast(file)); + + auto buffer = llvm::MemoryBuffer::getFile(*file); + EXPECT_TRUE(static_cast(buffer)); + + yaml::Input yin((*buffer)->getBuffer()); + std::vector data; + yin >> data; + + ASSERT_EQ(data.size(), 2U); + EXPECT_EQ(data[0], data0); + EXPECT_EQ(data[1], data1); +} + +// Read the second file. +{ + llvm::Optional file = multi_loader->GetNextFile(); + EXPECT_TRUE(static_cast(file)); + + auto buffer = llvm::MemoryBuffer::getFile(*file); + EXPECT_TRUE(static_cast(buffer)); + + yaml::Input yin((*buffer)->getBuffer()); + std::vector data; + yin >> data; + + ASSERT_EQ(data.size(), 2U); + EXPECT_EQ(data[0], data2); + EXPECT_EQ(data[1], data3); +} + +// There is no third file. +llvm::Optional file = multi_loader->GetNextFile(); +EXPECT_FALSE(static_cast(file)); + } +} Index: lldb/source/Utility/Reproducer.cpp === --- lldb/source/Utility/Reproducer.cpp +++ lldb/source/Utility/Reproducer.cpp @@ -7,6 +7,7 @@ //===--===// #include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBAssert.h" #include "llvm/Support/FileSystem.h" @@ -272,40 +273,15 @@ return std::move(recorder); } -DataRecorder *CommandProvider::GetNewDataRecorder() { - std::size_t i = m_data_recorders.size() + 1; - std::string filename = (llvm::Twine(Info::name) +
[Lldb-commits] [PATCH] D83441: [ldb/Reproducers] Add YamlRecorder and MultiProvider
JDevlieghere created this revision. JDevlieghere added reviewers: labath, teemperor. This patch does several things that are all closely related: - It introduces a new `YamlRecorder` as a counterpart to the existing `DataRecorder`. As the name suggests the former serializes data as yaml while the latter uses raw texts or bytes. - It introduces a new `MultiProvider` base class which can be backed by either a `DataRecorder` or a `YamlRecorder`. - It reimplements the `CommandProvider` in terms of the new `MultiProvider`. - Finally, it adds unit testing coverage for the `MultiProvider`, a naive `YamlProvider` built on top of the new `YamlRecorder` and the existing `MutliLoader`. This is the basis of a future patch that I'm working on which will implement a Provider through the `YamlRecorder`. Repository: rLLDB LLDB https://reviews.llvm.org/D83441 Files: lldb/include/lldb/Utility/Reproducer.h lldb/source/API/SBDebugger.cpp lldb/source/Utility/Reproducer.cpp lldb/unittests/Utility/ReproducerTest.cpp Index: lldb/unittests/Utility/ReproducerTest.cpp === --- lldb/unittests/Utility/ReproducerTest.cpp +++ lldb/unittests/Utility/ReproducerTest.cpp @@ -31,8 +31,26 @@ static char ID; }; +class YamlMultiProvider +: public MultiProvider { +public: + struct Info { +static const char *name; +static const char *file; + }; + + YamlMultiProvider(const FileSpec ) + : MultiProvider(directory) {} + + static char ID; +}; + const char *DummyProvider::Info::name = "dummy"; const char *DummyProvider::Info::file = "dummy.yaml"; +const char *YamlMultiProvider::Info::name = "mutli"; +const char *YamlMultiProvider::Info::file = "mutli.yaml"; +char DummyProvider::ID = 0; +char YamlMultiProvider::ID = 0; class DummyReproducer : public Reproducer { public: @@ -42,7 +60,26 @@ using Reproducer::SetReplay; }; -char DummyProvider::ID = 0; +struct YamlData { + YamlData() : i(-1){}; + YamlData(int i) : i(i){}; + int i; +}; + +inline bool operator==(const YamlData , const YamlData ) { + return LHS.i == RHS.i; +} + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(YamlData) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(std::vector) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits { + static void mapping(IO , YamlData ) { io.mapRequired("i", Y.i); }; +}; +} // namespace yaml +} // namespace llvm TEST(ReproducerTest, SetCapture) { DummyReproducer reproducer; @@ -144,3 +181,82 @@ auto _alt = generator.GetOrCreate(); EXPECT_EQ(, _alt); } + +TEST(GeneratorTest, YamlMultiProvider) { + SmallString<128> root; + std::error_code ec = llvm::sys::fs::createUniqueDirectory("reproducer", root); + ASSERT_FALSE(static_cast(ec)); + + YamlData data0(0); + YamlData data1(1); + YamlData data2(2); + YamlData data3(3); + + { +DummyReproducer reproducer; +EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec(root.str())), Succeeded()); + +auto = *reproducer.GetGenerator(); +auto *provider = generator.Create(); +ASSERT_NE(nullptr, provider); + +auto *recorder = provider->GetNewRecorder(); +ASSERT_NE(nullptr, recorder); +recorder->Record(data0); +recorder->Record(data1); + +recorder = provider->GetNewRecorder(); +ASSERT_NE(nullptr, recorder); +recorder->Record(data2); +recorder->Record(data3); + +generator.Keep(); + } + + { +DummyReproducer reproducer; +EXPECT_THAT_ERROR(reproducer.SetReplay(FileSpec(root.str())), Succeeded()); + +auto = *reproducer.GetLoader(); +std::unique_ptr> multi_loader = +repro::MultiLoader::Create(); + +// Read the first file. +{ + llvm::Optional file = multi_loader->GetNextFile(); + EXPECT_TRUE(static_cast(file)); + + auto buffer = llvm::MemoryBuffer::getFile(*file); + EXPECT_TRUE(static_cast(buffer)); + + yaml::Input yin((*buffer)->getBuffer()); + std::vector data; + yin >> data; + + ASSERT_EQ(data.size(), 2U); + EXPECT_EQ(data[0], data0); + EXPECT_EQ(data[1], data1); +} + +// Read the second file. +{ + llvm::Optional file = multi_loader->GetNextFile(); + EXPECT_TRUE(static_cast(file)); + + auto buffer = llvm::MemoryBuffer::getFile(*file); + EXPECT_TRUE(static_cast(buffer)); + + yaml::Input yin((*buffer)->getBuffer()); + std::vector data; + yin >> data; + + ASSERT_EQ(data.size(), 2U); + EXPECT_EQ(data[0], data2); + EXPECT_EQ(data[1], data3); +} + +// There is no third file. +llvm::Optional file = multi_loader->GetNextFile(); +EXPECT_FALSE(static_cast(file)); + } +} Index: lldb/source/Utility/Reproducer.cpp === --- lldb/source/Utility/Reproducer.cpp +++ lldb/source/Utility/Reproducer.cpp @@ -7,6 +7,7 @@ //===--===// #include "lldb/Utility/Reproducer.h"