llvm-project/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp

138 lines
4.2 KiB
C++

#include "gtest/gtest.h"
#include "Core/Transform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclGroup.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Path.h"
using namespace clang;
class DummyTransform : public Transform {
public:
DummyTransform(llvm::StringRef Name, bool EnableTiming)
: Transform(Name, EnableTiming) {}
virtual int apply(const FileContentsByPath &,
RiskLevel ,
const tooling::CompilationDatabase &,
const std::vector<std::string> &,
FileContentsByPath &) { return 0; }
void setAcceptedChanges(unsigned Changes) {
Transform::setAcceptedChanges(Changes);
}
void setRejectedChanges(unsigned Changes) {
Transform::setRejectedChanges(Changes);
}
void setDeferredChanges(unsigned Changes) {
Transform::setDeferredChanges(Changes);
}
};
TEST(Transform, Interface) {
DummyTransform T("my_transform", /*EnableTiming=*/false);
ASSERT_EQ("my_transform", T.getName());
ASSERT_EQ(0u, T.getAcceptedChanges());
ASSERT_EQ(0u, T.getRejectedChanges());
ASSERT_EQ(0u, T.getDeferredChanges());
ASSERT_FALSE(T.getChangesMade());
ASSERT_FALSE(T.getChangesNotMade());
T.setAcceptedChanges(1);
ASSERT_TRUE(T.getChangesMade());
T.setDeferredChanges(1);
ASSERT_TRUE(T.getChangesNotMade());
T.setRejectedChanges(1);
ASSERT_TRUE(T.getChangesNotMade());
T.Reset();
ASSERT_EQ(0u, T.getAcceptedChanges());
ASSERT_EQ(0u, T.getRejectedChanges());
ASSERT_EQ(0u, T.getDeferredChanges());
T.setRejectedChanges(1);
ASSERT_TRUE(T.getChangesNotMade());
}
class FindTopLevelDeclConsumer : public ASTConsumer {
public:
FindTopLevelDeclConsumer(bool *Called) : Called(Called) {}
virtual bool HandleTopLevelDecl(DeclGroupRef DeclGroup) {
llvm::sys::TimeValue UserStart;
llvm::sys::TimeValue SystemStart;
llvm::sys::TimeValue UserNow;
llvm::sys::TimeValue SystemNow;
llvm::sys::TimeValue Wall;
// Busy-wait until the user/system time combined is more than 1ms
llvm::sys::TimeValue OneMS(0, 1000000);
llvm::sys::Process::GetTimeUsage(Wall, UserStart, SystemStart);
do {
llvm::sys::Process::GetTimeUsage(Wall, UserNow, SystemNow);
} while (UserNow - UserStart + SystemNow - SystemStart < OneMS);
*Called = true;
return true;
}
bool *Called;
};
struct ConsumerFactory {
ASTConsumer *newASTConsumer() {
return new FindTopLevelDeclConsumer(&Called);
}
bool Called;
};
TEST(Transform, Timings) {
DummyTransform T("timing_transform", /*EnableTiming=*/true);
// All the path stuff is to make the test work independently of OS.
// The directory used is not important since the path gets mapped to a virtual
// file anyway. What is important is that we have an absolute path with which
// to use with mapVirtualFile().
llvm::sys::Path FileA = llvm::sys::Path::GetCurrentDirectory();
std::string CurrentDir = FileA.str();
FileA.appendComponent("a.cc");
std::string FileAName = FileA.str();
llvm::sys::Path FileB = llvm::sys::Path::GetCurrentDirectory();
FileB.appendComponent("b.cc");
std::string FileBName = FileB.str();
tooling::FixedCompilationDatabase Compilations(CurrentDir, std::vector<std::string>());
std::vector<std::string> Sources;
Sources.push_back(FileAName);
Sources.push_back(FileBName);
tooling::ClangTool Tool(Compilations, Sources);
Tool.mapVirtualFile(FileAName, "void a() {}");
Tool.mapVirtualFile(FileBName, "void b() {}");
ConsumerFactory Factory;
Tool.run(newFrontendActionFactory(&Factory, &T));
EXPECT_TRUE(Factory.Called);
Transform::TimingVec::const_iterator I = T.timing_begin();
EXPECT_GT(I->second.getProcessTime(), 0.0);
// The success of the test shouldn't depend on the order of iteration through
// timers.
llvm::sys::Path FirstFile(I->first);
if (FileA == FirstFile) {
++I;
EXPECT_EQ(FileB, llvm::sys::Path(I->first));
EXPECT_GT(I->second.getProcessTime(), 0.0);
} else if (FileB == FirstFile) {
++I;
EXPECT_EQ(FileA, llvm::sys::Path(I->first));
EXPECT_GT(I->second.getProcessTime(), 0.0);
} else {
FAIL() << "Unexpected file name " << I->first << " in timing data.";
}
++I;
EXPECT_EQ(T.timing_end(), I);
}