diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
commit | 7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch) | |
tree | c72b9241553fc9966179aba84f90f17bfa9235c3 /unittests/Tooling/RefactoringTest.cpp | |
parent | b52119637f743680a99710ce5fdb6646da2772af (diff) |
Diffstat (limited to 'unittests/Tooling/RefactoringTest.cpp')
-rw-r--r-- | unittests/Tooling/RefactoringTest.cpp | 210 |
1 files changed, 206 insertions, 4 deletions
diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp index c29f8d7d71230..495ac755b39d9 100644 --- a/unittests/Tooling/RefactoringTest.cpp +++ b/unittests/Tooling/RefactoringTest.cpp @@ -26,6 +26,7 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Refactoring/AtomicChange.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/SmallString.h" #include "gtest/gtest.h" @@ -102,10 +103,10 @@ TEST_F(ReplacementTest, ReturnsInvalidPath) { // Checks that an llvm::Error instance contains a ReplacementError with expected // error code, expected new replacement, and expected existing replacement. -static bool checkReplacementError( - llvm::Error&& Error, replacement_error ExpectedErr, - llvm::Optional<Replacement> ExpectedExisting, - llvm::Optional<Replacement> ExpectedNew) { +static bool checkReplacementError(llvm::Error &&Error, + replacement_error ExpectedErr, + llvm::Optional<Replacement> ExpectedExisting, + llvm::Optional<Replacement> ExpectedNew) { if (!Error) { llvm::errs() << "Error is a success."; return false; @@ -1089,5 +1090,206 @@ TEST(DeduplicateByFileTest, NonExistingFilePath) { EXPECT_TRUE(FileToReplaces.empty()); } +class AtomicChangeTest : public ::testing::Test { + protected: + void SetUp() override { + DefaultFileID = Context.createInMemoryFile("input.cpp", DefaultCode); + DefaultLoc = Context.Sources.getLocForStartOfFile(DefaultFileID) + .getLocWithOffset(20); + assert(DefaultLoc.isValid() && "Default location must be valid."); + } + + RewriterTestContext Context; + std::string DefaultCode = std::string(100, 'a'); + unsigned DefaultOffset = 20; + SourceLocation DefaultLoc; + FileID DefaultFileID; +}; + +TEST_F(AtomicChangeTest, AtomicChangeToYAML) { + AtomicChange Change(Context.Sources, DefaultLoc); + llvm::Error Err = + Change.insert(Context.Sources, DefaultLoc, "aa", /*InsertAfter=*/false); + ASSERT_TRUE(!Err); + Err = Change.insert(Context.Sources, DefaultLoc.getLocWithOffset(10), "bb", + /*InsertAfter=*/false); + ASSERT_TRUE(!Err); + Change.addHeader("a.h"); + Change.removeHeader("b.h"); + std::string YAMLString = Change.toYAMLString(); + + // NOTE: If this test starts to fail for no obvious reason, check whitespace. + ASSERT_STREQ("---\n" + "Key: 'input.cpp:20'\n" + "FilePath: input.cpp\n" + "Error: ''\n" + "InsertedHeaders: [ a.h ]\n" + "RemovedHeaders: [ b.h ]\n" + "Replacements: \n" // Extra whitespace here! + " - FilePath: input.cpp\n" + " Offset: 20\n" + " Length: 0\n" + " ReplacementText: aa\n" + " - FilePath: input.cpp\n" + " Offset: 30\n" + " Length: 0\n" + " ReplacementText: bb\n" + "...\n", + YAMLString.c_str()); +} + +TEST_F(AtomicChangeTest, YAMLToAtomicChange) { + std::string YamlContent = "---\n" + "Key: 'input.cpp:20'\n" + "FilePath: input.cpp\n" + "Error: 'ok'\n" + "InsertedHeaders: [ a.h ]\n" + "RemovedHeaders: [ b.h ]\n" + "Replacements: \n" // Extra whitespace here! + " - FilePath: input.cpp\n" + " Offset: 20\n" + " Length: 0\n" + " ReplacementText: aa\n" + " - FilePath: input.cpp\n" + " Offset: 30\n" + " Length: 0\n" + " ReplacementText: bb\n" + "...\n"; + AtomicChange ExpectedChange(Context.Sources, DefaultLoc); + llvm::Error Err = ExpectedChange.insert(Context.Sources, DefaultLoc, "aa", + /*InsertAfter=*/false); + ASSERT_TRUE(!Err); + Err = ExpectedChange.insert(Context.Sources, DefaultLoc.getLocWithOffset(10), + "bb", /*InsertAfter=*/false); + ASSERT_TRUE(!Err); + + ExpectedChange.addHeader("a.h"); + ExpectedChange.removeHeader("b.h"); + ExpectedChange.setError("ok"); + + AtomicChange ActualChange = AtomicChange::convertFromYAML(YamlContent); + EXPECT_EQ(ExpectedChange.getKey(), ActualChange.getKey()); + EXPECT_EQ(ExpectedChange.getFilePath(), ActualChange.getFilePath()); + EXPECT_EQ(ExpectedChange.getError(), ActualChange.getError()); + EXPECT_EQ(ExpectedChange.getInsertedHeaders(), + ActualChange.getInsertedHeaders()); + EXPECT_EQ(ExpectedChange.getRemovedHeaders(), + ActualChange.getRemovedHeaders()); + EXPECT_EQ(ExpectedChange.getReplacements().size(), + ActualChange.getReplacements().size()); + EXPECT_EQ(2u, ActualChange.getReplacements().size()); + EXPECT_EQ(*ExpectedChange.getReplacements().begin(), + *ActualChange.getReplacements().begin()); + EXPECT_EQ(*(++ExpectedChange.getReplacements().begin()), + *(++ActualChange.getReplacements().begin())); +} + +TEST_F(AtomicChangeTest, CheckKeyAndKeyFile) { + AtomicChange Change(Context.Sources, DefaultLoc); + EXPECT_EQ("input.cpp:20", Change.getKey()); + EXPECT_EQ("input.cpp", Change.getFilePath()); +} + +TEST_F(AtomicChangeTest, Replace) { + AtomicChange Change(Context.Sources, DefaultLoc); + llvm::Error Err = Change.replace(Context.Sources, DefaultLoc, 2, "aa"); + ASSERT_TRUE(!Err); + EXPECT_EQ(Change.getReplacements().size(), 1u); + EXPECT_EQ(*Change.getReplacements().begin(), + Replacement(Context.Sources, DefaultLoc, 2, "aa")); + + // Add a new replacement that conflicts with the existing one. + Err = Change.replace(Context.Sources, DefaultLoc, 3, "ab"); + EXPECT_TRUE((bool)Err); + llvm::consumeError(std::move(Err)); + EXPECT_EQ(Change.getReplacements().size(), 1u); +} + +TEST_F(AtomicChangeTest, ReplaceWithRange) { + AtomicChange Change(Context.Sources, DefaultLoc); + SourceLocation End = DefaultLoc.getLocWithOffset(20); + llvm::Error Err = Change.replace( + Context.Sources, CharSourceRange::getCharRange(DefaultLoc, End), "aa"); + ASSERT_TRUE(!Err); + EXPECT_EQ(Change.getReplacements().size(), 1u); + EXPECT_EQ(*Change.getReplacements().begin(), + Replacement(Context.Sources, DefaultLoc, 20, "aa")); +} + +TEST_F(AtomicChangeTest, InsertBefore) { + AtomicChange Change(Context.Sources, DefaultLoc); + llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa"); + ASSERT_TRUE(!Err); + EXPECT_EQ(Change.getReplacements().size(), 1u); + EXPECT_EQ(*Change.getReplacements().begin(), + Replacement(Context.Sources, DefaultLoc, 0, "aa")); + Err = Change.insert(Context.Sources, DefaultLoc, "b", /*InsertAfter=*/false); + ASSERT_TRUE(!Err); + EXPECT_EQ(Change.getReplacements().size(), 1u); + EXPECT_EQ(*Change.getReplacements().begin(), + Replacement(Context.Sources, DefaultLoc, 0, "baa")); +} + +TEST_F(AtomicChangeTest, InsertAfter) { + AtomicChange Change(Context.Sources, DefaultLoc); + llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa"); + ASSERT_TRUE(!Err); + EXPECT_EQ(Change.getReplacements().size(), 1u); + EXPECT_EQ(*Change.getReplacements().begin(), + Replacement(Context.Sources, DefaultLoc, 0, "aa")); + Err = Change.insert(Context.Sources, DefaultLoc, "b"); + ASSERT_TRUE(!Err); + EXPECT_EQ(Change.getReplacements().size(), 1u); + EXPECT_EQ(*Change.getReplacements().begin(), + Replacement(Context.Sources, DefaultLoc, 0, "aab")); +} + +TEST_F(AtomicChangeTest, InsertBeforeWithInvalidLocation) { + AtomicChange Change(Context.Sources, DefaultLoc); + llvm::Error Err = + Change.insert(Context.Sources, DefaultLoc, "a", /*InsertAfter=*/false); + ASSERT_TRUE(!Err); + + // Invalid location. + Err = Change.insert(Context.Sources, SourceLocation(), "a", + /*InsertAfter=*/false); + ASSERT_TRUE((bool)Err); + EXPECT_TRUE(checkReplacementError( + std::move(Err), replacement_error::wrong_file_path, + Replacement(Context.Sources, DefaultLoc, 0, "a"), + Replacement(Context.Sources, SourceLocation(), 0, "a"))); +} + +TEST_F(AtomicChangeTest, InsertBeforeToWrongFile) { + AtomicChange Change(Context.Sources, DefaultLoc); + llvm::Error Err = + Change.insert(Context.Sources, DefaultLoc, "a", /*InsertAfter=*/false); + ASSERT_TRUE(!Err); + + // Inserting at a different file. + FileID NewID = Context.createInMemoryFile("extra.cpp", DefaultCode); + SourceLocation NewLoc = Context.Sources.getLocForStartOfFile(NewID); + Err = Change.insert(Context.Sources, NewLoc, "b", /*InsertAfter=*/false); + ASSERT_TRUE((bool)Err); + EXPECT_TRUE( + checkReplacementError(std::move(Err), replacement_error::wrong_file_path, + Replacement(Context.Sources, DefaultLoc, 0, "a"), + Replacement(Context.Sources, NewLoc, 0, "b"))); +} + +TEST_F(AtomicChangeTest, InsertAfterWithInvalidLocation) { + AtomicChange Change(Context.Sources, DefaultLoc); + llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "a"); + ASSERT_TRUE(!Err); + + // Invalid location. + Err = Change.insert(Context.Sources, SourceLocation(), "b"); + ASSERT_TRUE((bool)Err); + EXPECT_TRUE(checkReplacementError( + std::move(Err), replacement_error::wrong_file_path, + Replacement(Context.Sources, DefaultLoc, 0, "a"), + Replacement(Context.Sources, SourceLocation(), 0, "b"))); +} + } // end namespace tooling } // end namespace clang |