25 struct DepsLogTest :
public testing::Test {
26 virtual void SetUp() {
28 unlink(kTestFilename);
30 virtual void TearDown() {
31 unlink(kTestFilename);
35 TEST_F(DepsLogTest, WriteRead) {
44 deps.push_back(state1.
GetNode(
"foo.h"));
45 deps.push_back(state1.
GetNode(
"bar.h"));
49 deps.push_back(state1.
GetNode(
"foo.h"));
50 deps.push_back(state1.
GetNode(
"bar2.h"));
54 ASSERT_TRUE(log_deps);
55 ASSERT_EQ(1, log_deps->
mtime);
57 ASSERT_EQ(
"foo.h", log_deps->
nodes[0]->
path());
58 ASSERT_EQ(
"bar.h", log_deps->
nodes[1]->
path());
65 EXPECT_TRUE(log2.
Load(kTestFilename, &state2, &err));
68 ASSERT_EQ(log1.
nodes().size(), log2.
nodes().size());
69 for (
int i = 0; i < (int)log1.
nodes().size(); ++i) {
72 ASSERT_EQ(i, node1->
id());
73 ASSERT_EQ(node1->
id(), node2->
id());
78 ASSERT_TRUE(log_deps);
79 ASSERT_EQ(2, log_deps->
mtime);
81 ASSERT_EQ(
"foo.h", log_deps->
nodes[0]->
path());
82 ASSERT_EQ(
"bar2.h", log_deps->
nodes[1]->
path());
85 TEST_F(DepsLogTest, LotsOfDeps) {
86 const int kNumDeps = 100000;
96 for (
int i = 0; i < kNumDeps; ++i) {
98 sprintf(buf,
"file%d.h", i);
99 deps.push_back(state1.
GetNode(buf));
111 EXPECT_TRUE(log2.
Load(kTestFilename, &state2, &err));
119 TEST_F(DepsLogTest, DoubleEntry) {
130 deps.push_back(state.
GetNode(
"foo.h"));
131 deps.push_back(state.
GetNode(
"bar.h"));
136 ASSERT_EQ(0, stat(kTestFilename, &st));
137 file_size = (int)st.st_size;
138 ASSERT_GT(file_size, 0);
146 EXPECT_TRUE(log.
Load(kTestFilename, &state, &err));
152 deps.push_back(state.
GetNode(
"foo.h"));
153 deps.push_back(state.
GetNode(
"bar.h"));
158 ASSERT_EQ(0, stat(kTestFilename, &st));
159 int file_size_2 = (int)st.st_size;
160 ASSERT_EQ(file_size, file_size_2);
165 TEST_F(DepsLogTest, Recompact) {
166 const char kManifest[] =
171 "build other_out.o: cc\n";
177 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, kManifest));
184 deps.push_back(state.
GetNode(
"foo.h"));
185 deps.push_back(state.
GetNode(
"bar.h"));
189 deps.push_back(state.
GetNode(
"foo.h"));
190 deps.push_back(state.
GetNode(
"baz.h"));
196 ASSERT_EQ(0, stat(kTestFilename, &st));
197 file_size = (int)st.st_size;
198 ASSERT_GT(file_size, 0);
205 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, kManifest));
208 ASSERT_TRUE(log.
Load(kTestFilename, &state, &err));
214 deps.push_back(state.
GetNode(
"foo.h"));
219 ASSERT_EQ(0, stat(kTestFilename, &st));
220 file_size_2 = (int)st.st_size;
222 ASSERT_GT(file_size_2, file_size);
230 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, kManifest));
233 ASSERT_TRUE(log.
Load(kTestFilename, &state, &err));
238 ASSERT_EQ(1, deps->
mtime);
240 ASSERT_EQ(
"foo.h", deps->
nodes[0]->
path());
245 ASSERT_EQ(1, deps->
mtime);
247 ASSERT_EQ(
"foo.h", deps->
nodes[0]->
path());
248 ASSERT_EQ(
"baz.h", deps->
nodes[1]->
path());
250 ASSERT_TRUE(log.
Recompact(kTestFilename, &err));
255 ASSERT_EQ(1, deps->mtime);
256 ASSERT_EQ(1, deps->node_count);
257 ASSERT_EQ(
"foo.h", deps->nodes[0]->path());
258 ASSERT_EQ(out, log.
nodes()[out->id()]);
262 ASSERT_EQ(1, deps->mtime);
263 ASSERT_EQ(2, deps->node_count);
264 ASSERT_EQ(
"foo.h", deps->nodes[0]->path());
265 ASSERT_EQ(
"baz.h", deps->nodes[1]->path());
266 ASSERT_EQ(other_out, log.
nodes()[other_out->id()]);
270 ASSERT_EQ(0, stat(kTestFilename, &st));
271 file_size_3 = (int)st.st_size;
272 ASSERT_LT(file_size_3, file_size_2);
282 ASSERT_TRUE(log.
Load(kTestFilename, &state, &err));
287 ASSERT_EQ(1, deps->
mtime);
289 ASSERT_EQ(
"foo.h", deps->
nodes[0]->
path());
294 ASSERT_EQ(1, deps->
mtime);
296 ASSERT_EQ(
"foo.h", deps->
nodes[0]->
path());
297 ASSERT_EQ(
"baz.h", deps->
nodes[1]->
path());
299 ASSERT_TRUE(log.
Recompact(kTestFilename, &err));
314 ASSERT_EQ(0, stat(kTestFilename, &st));
315 int file_size_4 = (int)st.st_size;
316 ASSERT_LT(file_size_4, file_size_3);
321 TEST_F(DepsLogTest, InvalidHeader) {
322 const char *kInvalidHeaders[] = {
326 "# ninjadeps\n\001\002",
327 "# ninjadeps\n\001\002\003\004"
329 for (
size_t i = 0; i <
sizeof(kInvalidHeaders) /
sizeof(kInvalidHeaders[0]);
331 FILE* deps_log = fopen(kTestFilename,
"wb");
332 ASSERT_TRUE(deps_log != NULL);
334 strlen(kInvalidHeaders[i]),
335 fwrite(kInvalidHeaders[i], 1, strlen(kInvalidHeaders[i]), deps_log));
336 ASSERT_EQ(0 ,fclose(deps_log));
341 ASSERT_TRUE(log.
Load(kTestFilename, &state, &err));
342 EXPECT_EQ(
"bad deps log signature or version; starting over", err);
347 TEST_F(DepsLogTest, Truncated) {
357 deps.push_back(state.
GetNode(
"foo.h"));
358 deps.push_back(state.
GetNode(
"bar.h"));
362 deps.push_back(state.
GetNode(
"foo.h"));
363 deps.push_back(state.
GetNode(
"bar2.h"));
371 ASSERT_EQ(0, stat(kTestFilename, &st));
378 for (
int size = (
int)st.st_size; size > 0; --size) {
380 ASSERT_TRUE(
Truncate(kTestFilename, size, &err));
384 EXPECT_TRUE(log.
Load(kTestFilename, &state, &err));
390 ASSERT_GE(node_count, (
int)log.
nodes().size());
391 node_count = log.
nodes().size();
394 int new_deps_count = 0;
395 for (vector<DepsLog::Deps*>::const_iterator i = log.
deps().begin();
396 i != log.
deps().end(); ++i) {
400 ASSERT_GE(deps_count, new_deps_count);
401 deps_count = new_deps_count;
406 TEST_F(DepsLogTest, TruncatedRecovery) {
416 deps.push_back(state.
GetNode(
"foo.h"));
417 deps.push_back(state.
GetNode(
"bar.h"));
421 deps.push_back(state.
GetNode(
"foo.h"));
422 deps.push_back(state.
GetNode(
"bar2.h"));
430 ASSERT_EQ(0, stat(kTestFilename, &st));
432 ASSERT_TRUE(
Truncate(kTestFilename, st.st_size - 2, &err));
439 EXPECT_TRUE(log.
Load(kTestFilename, &state, &err));
440 ASSERT_EQ(
"premature end of file; recovering", err);
451 deps.push_back(state.
GetNode(
"foo.h"));
452 deps.push_back(state.
GetNode(
"bar2.h"));
464 EXPECT_TRUE(log.
Load(kTestFilename, &state, &err));
Node * GetNode(StringPiece path)
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
void AssertParse(State *state, const char *input)
As build commands run they can output extra dependency information (e.g.
bool OpenForWrite(const string &path, string *err)
Deps * GetDeps(Node *node)
const char kTestFilename[]
bool Load(const string &path, State *state, string *err)
bool Recompact(const string &path, string *err)
Rewrite the known log entries, throwing away old data.
const string & path() const
bool Truncate(const string &path, size_t size, string *err)
Truncates a file to the given size.
const vector< Deps * > & deps() const
Global state (file status, loaded rules) for a single run.
const vector< Node * > & nodes() const
Used for tests.
bool RecordDeps(Node *node, TimeStamp mtime, const vector< Node * > &nodes)
Node * LookupNode(StringPiece path) const