[cfe-commits] r44411 - /cfe/trunk/Driver/SerializationTest.cpp

Ted Kremenek kremenek at apple.com
Wed Nov 28 11:21:47 PST 2007


Author: kremenek
Date: Wed Nov 28 13:21:47 2007
New Revision: 44411

URL: http://llvm.org/viewvc/llvm-project?rev=44411&view=rev
Log:
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.

Modified:
    cfe/trunk/Driver/SerializationTest.cpp

Modified: cfe/trunk/Driver/SerializationTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/SerializationTest.cpp?rev=44411&r1=44410&r2=44411&view=diff

==============================================================================
--- cfe/trunk/Driver/SerializationTest.cpp (original)
+++ cfe/trunk/Driver/SerializationTest.cpp Wed Nov 28 13:21:47 2007
@@ -26,20 +26,41 @@
 #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;
@@ -62,8 +83,8 @@
   }
 
 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 @@
          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 @@
   // ===---------------------------------------------------===/  
   
   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 @@
   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 @@
   // 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 (Filename.makeUnique(true,&ErrMsg)) {
+  if (FNameDeclAfter.makeUnique(true,&ErrMsg)) {
     llvm::cerr << "Error: " << ErrMsg << "\n";
     return;
   }
+
+  llvm::sys::Path ASTFilename = Dir;
+  ASTFilename.appendComponent("test.ast");
+  
+  if (ASTFilename.makeUnique(true,&ErrMsg)) {
+    llvm::cerr << "Error: " << ErrMsg << "\n";
+    return;
+  }
+  
+  // 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;
+  }
   
-  Serialize(Filename);
-  Deserialize(Filename);
+  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";
 }





More information about the cfe-commits mailing list