diff options
author | Ted Kremenek <kremenek@apple.com> | 2007-11-28 19:21:47 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2007-11-28 19:21:47 +0000 |
commit | 79a2a261632b8d09971326882bff351b6c26c184 (patch) | |
tree | bc282c44a6b85bb2f4280d3a74d711a7265e3725 /Driver/SerializationTest.cpp | |
parent | 6a18c7689bf05279feb42adca9f943d78e15a25b (diff) |
Modified --test-pickling to perform an actual cross-check of serialized ASTs:
(1) Parsed ASTs are pretty-printed to a text file.
(2) The ASTs are serialized to disk.
(3) The ASTs are deserialized from disk.
(4) The deserialized ASTs are pretty-printed to a text file.
(5) The two pretty-printed files are compared. If they are different, the test
fails.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44411 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Driver/SerializationTest.cpp')
-rw-r--r-- | Driver/SerializationTest.cpp | 192 |
1 files changed, 144 insertions, 48 deletions
diff --git a/Driver/SerializationTest.cpp b/Driver/SerializationTest.cpp index b431fb3a15..c0ebff7801 100644 --- a/Driver/SerializationTest.cpp +++ b/Driver/SerializationTest.cpp @@ -26,21 +26,42 @@ #include <stdio.h> #include <list> -//===----------------------------------------------------------------------===// -// Driver code. -//===----------------------------------------------------------------------===// - using namespace clang; using llvm::sys::TimeValue; +//===----------------------------------------------------------------------===// +// Utility classes +//===----------------------------------------------------------------------===// + namespace { -template<typename T> struct Janitor { +template<typename T> class Janitor { T* Obj; - Janitor(T* obj) : Obj(obj) {} +public: + explicit Janitor(T* obj) : Obj(obj) {} ~Janitor() { delete Obj; } + operator T*() const { return Obj; } + T* operator->() { return Obj; } }; +class FileSP { + FILE* f; +public: + FileSP(const llvm::sys::Path& fname, const char* mode = "wb") + : f(fopen(fname.c_str(),mode)) {} + + ~FileSP() { if (f) fclose(f); } + + operator FILE*() const { return f; } +private: + void operator=(const FileSP& RHS) {} + FileSP(const FileSP& RHS) {} +}; + +//===----------------------------------------------------------------------===// +// Driver code. +//===----------------------------------------------------------------------===// + class SerializationTest : public ASTConsumer { ASTContext* Context; std::list<Decl*> Decls; @@ -62,8 +83,8 @@ public: } private: - void Serialize(llvm::sys::Path& Filename); - void Deserialize(llvm::sys::Path& Filename); + void Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint); + void Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint); }; } // end anonymous namespace @@ -90,7 +111,8 @@ static bool ReadPreamble(llvm::BitstreamReader& Stream) { Stream.Read(4) != 0x0; } -void SerializationTest::Serialize(llvm::sys::Path& Filename) { +void SerializationTest::Serialize(llvm::sys::Path& Filename, + llvm::sys::Path& FNameDeclPrint) { // Reserve 256K for bitstream buffer. std::vector<unsigned char> Buffer; @@ -108,17 +130,22 @@ void SerializationTest::Serialize(llvm::sys::Path& Filename) { // ===---------------------------------------------------===/ Sezr.EnterBlock(DeclsBlock); - - // Create a printer to "consume" our deserialized ASTS. - ASTConsumer* Printer = CreateASTPrinter(); - Janitor<ASTConsumer> PrinterJanitor(Printer); - - for (std::list<Decl*>::iterator I=Decls.begin(), E=Decls.end(); I!=E; ++I) { - llvm::cerr << "Serializing: Decl.\n"; - Printer->HandleTopLevelDecl(*I); + { // Create a printer to "consume" our deserialized ASTS. + + Janitor<ASTConsumer> Printer(CreateASTPrinter()); + FileSP DeclFP(FNameDeclPrint,"w"); + assert (DeclFP && "Could not open file for printing out decls."); + Janitor<ASTConsumer> FilePrinter(CreateASTPrinter(DeclFP)); - Sezr.EmitOwnedPtr(*I); + for (std::list<Decl*>::iterator I=Decls.begin(), E=Decls.end(); I!=E; ++I) { + llvm::cerr << "Serializing: Decl.\n"; + + Printer->HandleTopLevelDecl(*I); + FilePrinter->HandleTopLevelDecl(*I); + + Sezr.EmitOwnedPtr(*I); + } } Sezr.ExitBlock(); @@ -155,40 +182,37 @@ void SerializationTest::Serialize(llvm::sys::Path& Filename) { Sezr.ExitBlock(); // ===---------------------------------------------------===/ - // Finalize serialization: write the bits to disk. - // ===---------------------------------------------------===/ - - if (FILE *fp = fopen(Filename.c_str(),"wb")) { - fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp); - fclose(fp); - } - else { - llvm::cerr << "Error: Cannot open " << Filename.c_str() << "\n"; - return; + // Finalize serialization: write the bits to disk. + { + FileSP fp(Filename); + + if (fp) + fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp); + else { + llvm::cerr << "Error: Cannot open " << Filename.c_str() << "\n"; + return; + } } llvm::cerr << "Commited bitstream to disk: " << Filename.c_str() << "\n"; } -void SerializationTest::Deserialize(llvm::sys::Path& Filename) { +void SerializationTest::Deserialize(llvm::sys::Path& Filename, + llvm::sys::Path& FNameDeclPrint) { // Create the memory buffer that contains the contents of the file. using llvm::MemoryBuffer; - MemoryBuffer* MBuffer = MemoryBuffer::getFile(Filename.c_str(), - strlen(Filename.c_str())); + Janitor<MemoryBuffer> MBuffer(MemoryBuffer::getFile(Filename.c_str(), + strlen(Filename.c_str()))); if(!MBuffer) { llvm::cerr << "ERROR: Cannot read file for deserialization.\n"; return; } - // Create an "autocollector" object to release the memory buffer upon - // termination of the current scope. - Janitor<MemoryBuffer> AutoReleaseBuffer(MBuffer); - // Check if the file is of the proper length. if (MBuffer->getBufferSize() & 0x3) { llvm::cerr << "ERROR: AST file length should be a multiple of 4 bytes.\n"; @@ -246,43 +270,115 @@ void SerializationTest::Deserialize(llvm::sys::Path& Filename) { // Read the ASTContext. llvm::cerr << "Deserializing: ASTContext.\n"; Dezr.ReadOwnedPtr<ASTContext>(); - - // Create a printer to "consume" our deserialized ASTS. - ASTConsumer* Printer = CreateASTPrinter(); - Janitor<ASTConsumer> PrinterJanitor(Printer); - + // "Rewind" the stream. Find the block with the serialized top-level decls. Dezr.Rewind(); FoundBlock = Dezr.SkipToBlock(DeclsBlock); assert (FoundBlock); llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation(); + // Create a printer to "consume" our deserialized ASTS. + ASTConsumer* Printer = CreateASTPrinter(); + Janitor<ASTConsumer> PrinterJanitor(Printer); + FileSP DeclFP(FNameDeclPrint,"w"); + assert (DeclFP && "Could not open file for printing out decls."); + Janitor<ASTConsumer> FilePrinter(CreateASTPrinter(DeclFP)); + // The remaining objects in the file are top-level decls. while (!Dezr.FinishedBlock(DeclBlockLoc)) { llvm::cerr << "Deserializing: Decl.\n"; Decl* decl = Dezr.ReadOwnedPtr<Decl>(); - Printer->HandleTopLevelDecl(decl); + Printer->HandleTopLevelDecl(decl); + FilePrinter->HandleTopLevelDecl(decl); } } +namespace { + class TmpDirJanitor { + llvm::sys::Path& Dir; + public: + explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {} + + ~TmpDirJanitor() { + llvm::cerr << "Removing: " << Dir.c_str() << '\n'; + Dir.eraseFromDisk(true); + } + }; +} SerializationTest::~SerializationTest() { - + std::string ErrMsg; - llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); + llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); - if (Filename.isEmpty()) { + if (Dir.isEmpty()) { llvm::cerr << "Error: " << ErrMsg << "\n"; return; } - Filename.appendComponent("test.ast"); + TmpDirJanitor RemoveTmpOnExit(Dir); + + llvm::sys::Path FNameDeclBefore = Dir; + FNameDeclBefore.appendComponent("test.decl_before.txt"); + + if (FNameDeclBefore.makeUnique(true,&ErrMsg)) { + llvm::cerr << "Error: " << ErrMsg << "\n"; + return; + } + + llvm::sys::Path FNameDeclAfter = Dir; + FNameDeclAfter.appendComponent("test.decl_after.txt"); + + if (FNameDeclAfter.makeUnique(true,&ErrMsg)) { + llvm::cerr << "Error: " << ErrMsg << "\n"; + return; + } + + llvm::sys::Path ASTFilename = Dir; + ASTFilename.appendComponent("test.ast"); - if (Filename.makeUnique(true,&ErrMsg)) { + if (ASTFilename.makeUnique(true,&ErrMsg)) { llvm::cerr << "Error: " << ErrMsg << "\n"; return; } - Serialize(Filename); - Deserialize(Filename); + // Serialize and then deserialize the ASTs. + Serialize(ASTFilename, FNameDeclBefore); + Deserialize(ASTFilename, FNameDeclAfter); + + // Read both pretty-printed files and compare them. + + using llvm::MemoryBuffer; + + Janitor<MemoryBuffer> + MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str(), + strlen(FNameDeclBefore.c_str()))); + + if(!MBufferSer) { + llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n"; + return; + } + + Janitor<MemoryBuffer> + MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str(), + strlen(FNameDeclAfter.c_str()))); + + if(!MBufferDSer) { + llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n"; + return; + } + + const char *p1 = MBufferSer->getBufferStart(); + const char *e1 = MBufferSer->getBufferEnd(); + const char *p2 = MBufferDSer->getBufferStart(); + const char *e2 = MBufferDSer->getBufferEnd(); + + if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize()) + for ( ; p1 != e1 ; ++p1, ++p2 ) + if (*p1 != *p2) break; + + if (p1 != e1 || p2 != e2 ) + llvm::cerr << "ERROR: Pretty-printed files are not the same.\n"; + else + llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n"; } |