add a test for truncated deps
authorEvan Martin <martine@danga.com>
Fri, 26 Apr 2013 18:21:57 +0000 (11:21 -0700)
committerEvan Martin <martine@danga.com>
Fri, 26 Apr 2013 18:21:57 +0000 (11:21 -0700)
This doesn't yet exhibit the full problems with truncation, but it's
a start.

src/deps_log.h
src/deps_log_test.cc

index 99b006e..4b357a8 100644 (file)
@@ -86,6 +86,7 @@ struct DepsLog {
 
   /// Used for tests.
   const vector<Node*>& nodes() const { return nodes_; }
+  const vector<Deps*>& deps() const { return deps_; }
 
  private:
   // Write a node name record, assigning it an id.
index 0172d24..40539a7 100644 (file)
@@ -218,4 +218,64 @@ TEST_F(DepsLogTest, InvalidHeader) {
   }
 }
 
+// Simulate what happens if a write gets interrupted and the resulting
+// file is truncated.
+TEST_F(DepsLogTest, Truncated) {
+  // Create a file with some entries.
+  {
+    State state;
+    DepsLog log;
+    string err;
+    EXPECT_TRUE(log.OpenForWrite(kTestFilename, &err));
+    ASSERT_EQ("", err);
+
+    vector<Node*> deps;
+    deps.push_back(state.GetNode("foo.h"));
+    deps.push_back(state.GetNode("bar.h"));
+    log.RecordDeps(state.GetNode("out.o"), 1, deps);
+
+    deps.clear();
+    deps.push_back(state.GetNode("foo.h"));
+    deps.push_back(state.GetNode("bar2.h"));
+    log.RecordDeps(state.GetNode("out2.o"), 2, deps);
+
+    log.Close();
+  }
+
+  // Get the file size.
+  struct stat st;
+  ASSERT_EQ(0, stat(kTestFilename, &st));
+
+  // Try reloading at truncated sizes.
+  // Track how many nodes/deps were found; they should decrease with
+  // smaller sizes.
+  int node_count = 5;
+  int deps_count = 2;
+  for (int size = (int)st.st_size; size > 0; --size) {
+    ASSERT_EQ(0, truncate(kTestFilename, size));
+
+    State state;
+    DepsLog log;
+    string err;
+    EXPECT_TRUE(log.Load(kTestFilename, &state, &err));
+    if (!err.empty()) {
+      // At some point the log will be so short as to be unparseable.
+      break;
+    }
+
+    ASSERT_GE(node_count, log.nodes().size());
+    node_count = log.nodes().size();
+
+    // Count how many non-NULL deps entries there are.
+    int new_deps_count = 0;
+    for (vector<DepsLog::Deps*>::const_iterator i = log.deps().begin();
+         i != log.deps().end(); ++i) {
+      if (*i)
+        ++new_deps_count;
+    }
+    ASSERT_GE(deps_count, new_deps_count);
+    deps_count = new_deps_count;
+  }
+}
+
 }  // anonymous namespace