@@ -218,4 +218,64 @@ TEST_F(DepsLogTest, InvalidHeader) {
218
218
}
219
219
}
220
220
221
+ // Simulate what happens if a write gets interrupted and the resulting
222
+ // file is truncated.
223
+ TEST_F (DepsLogTest, Truncated) {
224
+ // Create a file with some entries.
225
+ {
226
+ State state;
227
+ DepsLog log ;
228
+ string err;
229
+ EXPECT_TRUE (log .OpenForWrite (kTestFilename , &err));
230
+ ASSERT_EQ (" " , err);
231
+
232
+ vector<Node*> deps;
233
+ deps.push_back (state.GetNode (" foo.h" ));
234
+ deps.push_back (state.GetNode (" bar.h" ));
235
+ log .RecordDeps (state.GetNode (" out.o" ), 1 , deps);
236
+
237
+ deps.clear ();
238
+ deps.push_back (state.GetNode (" foo.h" ));
239
+ deps.push_back (state.GetNode (" bar2.h" ));
240
+ log .RecordDeps (state.GetNode (" out2.o" ), 2 , deps);
241
+
242
+ log .Close ();
243
+ }
244
+
245
+ // Get the file size.
246
+ struct stat st;
247
+ ASSERT_EQ (0 , stat (kTestFilename , &st));
248
+
249
+ // Try reloading at truncated sizes.
250
+ // Track how many nodes/deps were found; they should decrease with
251
+ // smaller sizes.
252
+ int node_count = 5 ;
253
+ int deps_count = 2 ;
254
+ for (int size = (int )st.st_size ; size > 0 ; --size) {
255
+ ASSERT_EQ (0 , truncate (kTestFilename , size));
256
+
257
+ State state;
258
+ DepsLog log ;
259
+ string err;
260
+ EXPECT_TRUE (log .Load (kTestFilename , &state, &err));
261
+ if (!err.empty ()) {
262
+ // At some point the log will be so short as to be unparseable.
263
+ break ;
264
+ }
265
+
266
+ ASSERT_GE (node_count, log .nodes ().size ());
267
+ node_count = log .nodes ().size ();
268
+
269
+ // Count how many non-NULL deps entries there are.
270
+ int new_deps_count = 0 ;
271
+ for (vector<DepsLog::Deps*>::const_iterator i = log .deps ().begin ();
272
+ i != log .deps ().end (); ++i) {
273
+ if (*i)
274
+ ++new_deps_count;
275
+ }
276
+ ASSERT_GE (deps_count, new_deps_count);
277
+ deps_count = new_deps_count;
278
+ }
279
+ }
280
+
221
281
} // anonymous namespace
0 commit comments