From a4c33ea48bdbecb3b0176681885c0192599b01fd Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Fri, 26 Apr 2013 11:21:57 -0700 Subject: add a test for truncated deps This doesn't yet exhibit the full problems with truncation, but it's a start. --- src/deps_log.h | 1 + src/deps_log_test.cc | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/deps_log.h b/src/deps_log.h index 99b006e..4b357a8 100644 --- a/src/deps_log.h +++ b/src/deps_log.h @@ -86,6 +86,7 @@ struct DepsLog { /// Used for tests. const vector& nodes() const { return nodes_; } + const vector& deps() const { return deps_; } private: // Write a node name record, assigning it an id. diff --git a/src/deps_log_test.cc b/src/deps_log_test.cc index 0172d24..40539a7 100644 --- a/src/deps_log_test.cc +++ b/src/deps_log_test.cc @@ -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 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::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 -- cgit v0.12