Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(627)

Side by Side Diff: delta_diff_generator_unittest.cc

Issue 3597014: AU: reuse scratch blocks in delta generation, tolerate insufficient scratch. (Closed) Base URL: ssh://git@chromiumos-git/update_engine.git
Patch Set: address comments, fix code duplication Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « delta_diff_generator.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <sys/types.h> 5 #include <sys/types.h>
6 #include <sys/stat.h> 6 #include <sys/stat.h>
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <unistd.h> 8 #include <unistd.h>
9 #include <set> 9 #include <set>
10 #include <sstream>
10 #include <string> 11 #include <string>
11 #include <utility> 12 #include <utility>
12 #include <vector> 13 #include <vector>
13 #include <gtest/gtest.h> 14 #include <gtest/gtest.h>
14 #include "base/logging.h" 15 #include "base/logging.h"
15 #include "update_engine/cycle_breaker.h" 16 #include "update_engine/cycle_breaker.h"
16 #include "update_engine/delta_diff_generator.h" 17 #include "update_engine/delta_diff_generator.h"
17 #include "update_engine/delta_performer.h" 18 #include "update_engine/delta_performer.h"
19 #include "update_engine/extent_ranges.h"
18 #include "update_engine/graph_types.h" 20 #include "update_engine/graph_types.h"
19 #include "update_engine/graph_utils.h" 21 #include "update_engine/graph_utils.h"
20 #include "update_engine/subprocess.h" 22 #include "update_engine/subprocess.h"
21 #include "update_engine/test_utils.h" 23 #include "update_engine/test_utils.h"
24 #include "update_engine/topological_sort.h"
22 #include "update_engine/utils.h" 25 #include "update_engine/utils.h"
23 26
24 using std::make_pair; 27 using std::make_pair;
25 using std::set; 28 using std::set;
26 using std::string; 29 using std::string;
30 using std::stringstream;
27 using std::vector; 31 using std::vector;
28 32
29 namespace chromeos_update_engine { 33 namespace chromeos_update_engine {
30 34
31 typedef DeltaDiffGenerator::Block Block; 35 typedef DeltaDiffGenerator::Block Block;
32 36
33 namespace { 37 namespace {
34 int64_t BlocksInExtents( 38 int64_t BlocksInExtents(
35 const google::protobuf::RepeatedPtrField<Extent>& extents) { 39 const google::protobuf::RepeatedPtrField<Extent>& extents) {
36 int64_t ret = 0; 40 int64_t ret = 0;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 } 158 }
155 } 159 }
156 160
157 TEST_F(DeltaDiffGeneratorTest, SubstituteBlocksTest) { 161 TEST_F(DeltaDiffGeneratorTest, SubstituteBlocksTest) {
158 vector<Extent> remove_blocks; 162 vector<Extent> remove_blocks;
159 AppendExtent(&remove_blocks, 3, 3); 163 AppendExtent(&remove_blocks, 3, 3);
160 AppendExtent(&remove_blocks, 7, 1); 164 AppendExtent(&remove_blocks, 7, 1);
161 vector<Extent> replace_blocks; 165 vector<Extent> replace_blocks;
162 AppendExtent(&replace_blocks, 10, 2); 166 AppendExtent(&replace_blocks, 10, 2);
163 AppendExtent(&replace_blocks, 13, 2); 167 AppendExtent(&replace_blocks, 13, 2);
164 DeltaArchiveManifest_InstallOperation op; 168 Vertex vertex;
169 DeltaArchiveManifest_InstallOperation& op = vertex.op;
165 OpAppendExtent(&op, 4, 3); 170 OpAppendExtent(&op, 4, 3);
166 OpAppendExtent(&op, kSparseHole, 4); // Sparse hole in file 171 OpAppendExtent(&op, kSparseHole, 4); // Sparse hole in file
167 OpAppendExtent(&op, 3, 1); 172 OpAppendExtent(&op, 3, 1);
168 OpAppendExtent(&op, 7, 3); 173 OpAppendExtent(&op, 7, 3);
169 174
170 DeltaDiffGenerator::SubstituteBlocks(&op, remove_blocks, replace_blocks); 175 DeltaDiffGenerator::SubstituteBlocks(&vertex, remove_blocks, replace_blocks);
171 176
172 EXPECT_EQ(7, op.src_extents_size()); 177 EXPECT_EQ(7, op.src_extents_size());
173 EXPECT_EQ(11, op.src_extents(0).start_block()); 178 EXPECT_EQ(11, op.src_extents(0).start_block());
174 EXPECT_EQ(1, op.src_extents(0).num_blocks()); 179 EXPECT_EQ(1, op.src_extents(0).num_blocks());
175 EXPECT_EQ(13, op.src_extents(1).start_block()); 180 EXPECT_EQ(13, op.src_extents(1).start_block());
176 EXPECT_EQ(1, op.src_extents(1).num_blocks()); 181 EXPECT_EQ(1, op.src_extents(1).num_blocks());
177 EXPECT_EQ(6, op.src_extents(2).start_block()); 182 EXPECT_EQ(6, op.src_extents(2).start_block());
178 EXPECT_EQ(1, op.src_extents(2).num_blocks()); 183 EXPECT_EQ(1, op.src_extents(2).num_blocks());
179 EXPECT_EQ(kSparseHole, op.src_extents(3).start_block()); 184 EXPECT_EQ(kSparseHole, op.src_extents(3).start_block());
180 EXPECT_EQ(4, op.src_extents(3).num_blocks()); 185 EXPECT_EQ(4, op.src_extents(3).num_blocks());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 252
248 // Find cycles 253 // Find cycles
249 CycleBreaker cycle_breaker; 254 CycleBreaker cycle_breaker;
250 set<Edge> cut_edges; 255 set<Edge> cut_edges;
251 cycle_breaker.BreakCycles(graph, &cut_edges); 256 cycle_breaker.BreakCycles(graph, &cut_edges);
252 257
253 EXPECT_EQ(1, cut_edges.size()); 258 EXPECT_EQ(1, cut_edges.size());
254 EXPECT_TRUE(cut_edges.end() != cut_edges.find(make_pair<Vertex::Index>(1, 259 EXPECT_TRUE(cut_edges.end() != cut_edges.find(make_pair<Vertex::Index>(1,
255 0))); 260 0)));
256 261
257 EXPECT_TRUE(DeltaDiffGenerator::CutEdges(&graph, blocks, cut_edges)); 262 vector<CutEdgeVertexes> cuts;
263 EXPECT_TRUE(DeltaDiffGenerator::CutEdges(&graph, cut_edges, &cuts));
258 264
259 EXPECT_EQ(3, graph.size()); 265 EXPECT_EQ(3, graph.size());
260 266
261 // Check new node in graph: 267 // Check new node in graph:
262 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_MOVE, 268 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_MOVE,
263 graph.back().op.type()); 269 graph.back().op.type());
264 EXPECT_EQ(2, graph.back().op.src_extents_size()); 270 EXPECT_EQ(2, graph.back().op.src_extents_size());
265 EXPECT_EQ(2, graph.back().op.dst_extents_size()); 271 EXPECT_EQ(1, graph.back().op.dst_extents_size());
266 EXPECT_EQ(0, graph.back().op.dst_extents(0).start_block()); 272 EXPECT_EQ(kTempBlockStart, graph.back().op.dst_extents(0).start_block());
267 EXPECT_EQ(1, graph.back().op.dst_extents(0).num_blocks()); 273 EXPECT_EQ(2, graph.back().op.dst_extents(0).num_blocks());
268 EXPECT_EQ(8, graph.back().op.dst_extents(1).start_block());
269 EXPECT_EQ(1, graph.back().op.dst_extents(1).num_blocks());
270 EXPECT_TRUE(graph.back().out_edges.empty()); 274 EXPECT_TRUE(graph.back().out_edges.empty());
271 275
272 // Check that old node reads from new blocks 276 // Check that old node reads from new blocks
273 EXPECT_EQ(3, graph[0].op.src_extents_size()); 277 EXPECT_EQ(2, graph[0].op.src_extents_size());
274 EXPECT_EQ(0, graph[0].op.src_extents(0).start_block()); 278 EXPECT_EQ(kTempBlockStart, graph[0].op.src_extents(0).start_block());
275 EXPECT_EQ(1, graph[0].op.src_extents(0).num_blocks()); 279 EXPECT_EQ(2, graph[0].op.src_extents(0).num_blocks());
276 EXPECT_EQ(8, graph[0].op.src_extents(1).start_block()); 280 EXPECT_EQ(7, graph[0].op.src_extents(1).start_block());
277 EXPECT_EQ(1, graph[0].op.src_extents(1).num_blocks()); 281 EXPECT_EQ(1, graph[0].op.src_extents(1).num_blocks());
278 EXPECT_EQ(7, graph[0].op.src_extents(2).start_block());
279 EXPECT_EQ(1, graph[0].op.src_extents(2).num_blocks());
280 282
281 // And that the old dst extents haven't changed 283 // And that the old dst extents haven't changed
282 EXPECT_EQ(2, graph[0].op.dst_extents_size()); 284 EXPECT_EQ(2, graph[0].op.dst_extents_size());
283 EXPECT_EQ(1, graph[0].op.dst_extents(0).start_block()); 285 EXPECT_EQ(1, graph[0].op.dst_extents(0).start_block());
284 EXPECT_EQ(2, graph[0].op.dst_extents(0).num_blocks()); 286 EXPECT_EQ(2, graph[0].op.dst_extents(0).num_blocks());
285 EXPECT_EQ(4, graph[0].op.dst_extents(1).start_block()); 287 EXPECT_EQ(4, graph[0].op.dst_extents(1).start_block());
286 EXPECT_EQ(1, graph[0].op.dst_extents(1).num_blocks()); 288 EXPECT_EQ(1, graph[0].op.dst_extents(1).num_blocks());
287 289
288 // Ensure it only depends on the next node and the new temp node 290 // Ensure it only depends on the next node and the new temp node
289 EXPECT_EQ(2, graph[0].out_edges.size()); 291 EXPECT_EQ(2, graph[0].out_edges.size());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 EXPECT_EQ(2, manifest.install_operations_size()); 343 EXPECT_EQ(2, manifest.install_operations_size());
342 EXPECT_EQ(0, manifest.install_operations(0).data_offset()); 344 EXPECT_EQ(0, manifest.install_operations(0).data_offset());
343 EXPECT_EQ(3, manifest.install_operations(0).data_length()); 345 EXPECT_EQ(3, manifest.install_operations(0).data_length());
344 EXPECT_EQ(3, manifest.install_operations(1).data_offset()); 346 EXPECT_EQ(3, manifest.install_operations(1).data_offset());
345 EXPECT_EQ(1, manifest.install_operations(1).data_length()); 347 EXPECT_EQ(1, manifest.install_operations(1).data_length());
346 348
347 unlink(orig_blobs.c_str()); 349 unlink(orig_blobs.c_str());
348 unlink(new_blobs.c_str()); 350 unlink(new_blobs.c_str());
349 } 351 }
350 352
353 TEST_F(DeltaDiffGeneratorTest, MoveFullOpsToBackTest) {
354 Graph graph(4);
355 graph[0].file_name = "A";
356 graph[0].op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE);
357 graph[1].file_name = "B";
358 graph[1].op.set_type(DeltaArchiveManifest_InstallOperation_Type_BSDIFF);
359 graph[2].file_name = "C";
360 graph[2].op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
361 graph[3].file_name = "D";
362 graph[3].op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE);
363
364 vector<Vertex::Index> vect(graph.size());
365
366 for (vector<Vertex::Index>::size_type i = 0; i < vect.size(); ++i) {
367 vect[i] = i;
368 }
369 DeltaDiffGenerator::MoveFullOpsToBack(&graph, &vect);
370 EXPECT_EQ(vect.size(), graph.size());
371 EXPECT_EQ(graph[vect[0]].file_name, "B");
372 EXPECT_EQ(graph[vect[1]].file_name, "D");
373 EXPECT_EQ(graph[vect[2]].file_name, "A");
374 EXPECT_EQ(graph[vect[3]].file_name, "C");
375 }
376
377 namespace {
378
379 #define OP_BSDIFF DeltaArchiveManifest_InstallOperation_Type_BSDIFF
380 #define OP_MOVE DeltaArchiveManifest_InstallOperation_Type_MOVE
381 #define OP_REPLACE DeltaArchiveManifest_InstallOperation_Type_REPLACE
382 #define OP_REPLACE_BZ DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ
383
384 void GenVertex(Vertex* out,
385 const vector<Extent>& src_extents,
386 const vector<Extent>& dst_extents,
387 const string& path,
388 DeltaArchiveManifest_InstallOperation_Type type) {
389 out->op.set_type(type);
390 out->file_name = path;
391 DeltaDiffGenerator::StoreExtents(src_extents, out->op.mutable_src_extents());
392 DeltaDiffGenerator::StoreExtents(dst_extents, out->op.mutable_dst_extents());
393 }
394
395 vector<Extent> VectOfExt(uint64_t start_block, uint64_t num_blocks) {
396 return vector<Extent>(1, ExtentForRange(start_block, num_blocks));
397 }
398
399 EdgeProperties EdgeWithReadDep(const vector<Extent>& extents) {
400 EdgeProperties ret;
401 ret.extents = extents;
402 return ret;
403 }
404
405 EdgeProperties EdgeWithWriteDep(const vector<Extent>& extents) {
406 EdgeProperties ret;
407 ret.write_extents = extents;
408 return ret;
409 }
410
411 template<typename T>
412 void DumpVect(const vector<T>& vect) {
413 std::stringstream ss(stringstream::out);
414 for (typename vector<T>::const_iterator it = vect.begin(), e = vect.end();
415 it != e; ++it) {
416 ss << *it << ", ";
417 }
418 LOG(INFO) << "{" << ss.str() << "}";
419 }
420
421 } // namespace {}
422
423 TEST_F(DeltaDiffGeneratorTest, RunAsRootAssignTempBlocksTest) {
424 Graph graph(9);
425 const vector<Extent> empt; // empty
426 const string kFilename = "/foo";
427
428 // Some scratch space:
429 GenVertex(&graph[0], empt, VectOfExt(200, 1), "", OP_REPLACE);
430 GenVertex(&graph[1], empt, VectOfExt(210, 10), "", OP_REPLACE);
431 GenVertex(&graph[2], empt, VectOfExt(220, 1), "", OP_REPLACE);
432
433 // A cycle that requires 10 blocks to break:
434 GenVertex(&graph[3], VectOfExt(10, 11), VectOfExt(0, 9), "", OP_BSDIFF);
435 graph[3].out_edges[4] = EdgeWithReadDep(VectOfExt(0, 9));
436 GenVertex(&graph[4], VectOfExt(0, 9), VectOfExt(10, 11), "", OP_BSDIFF);
437 graph[4].out_edges[3] = EdgeWithReadDep(VectOfExt(10, 11));
438
439 // A cycle that requires 9 blocks to break:
440 GenVertex(&graph[5], VectOfExt(40, 11), VectOfExt(30, 10), "", OP_BSDIFF);
441 graph[5].out_edges[6] = EdgeWithReadDep(VectOfExt(30, 10));
442 GenVertex(&graph[6], VectOfExt(30, 10), VectOfExt(40, 11), "", OP_BSDIFF);
443 graph[6].out_edges[5] = EdgeWithReadDep(VectOfExt(40, 11));
444
445 // A cycle that requires 40 blocks to break (which is too many):
446 GenVertex(&graph[7],
447 VectOfExt(120, 50),
448 VectOfExt(60, 40),
449 "",
450 OP_BSDIFF);
451 graph[7].out_edges[8] = EdgeWithReadDep(VectOfExt(60, 40));
452 GenVertex(&graph[8],
453 VectOfExt(60, 40),
454 VectOfExt(120, 50),
455 kFilename,
456 OP_BSDIFF);
457 graph[8].out_edges[7] = EdgeWithReadDep(VectOfExt(120, 50));
458
459 graph_utils::DumpGraph(graph);
460
461 vector<Vertex::Index> final_order;
462
463
464 // Prepare the filesystem with the minimum required for this to work
465 string temp_dir;
466 EXPECT_TRUE(utils::MakeTempDirectory("/tmp/AssignTempBlocksTest.XXXXXX",
467 &temp_dir));
468 ScopedDirRemover temp_dir_remover(temp_dir);
469
470 const size_t kBlockSize = 4096;
471 vector<char> temp_data(kBlockSize * 50);
472 FillWithData(&temp_data);
473 EXPECT_TRUE(WriteFileVector(temp_dir + kFilename, temp_data));
474 ScopedPathUnlinker filename_unlinker(temp_dir + kFilename);
475
476 int fd;
477 EXPECT_TRUE(utils::MakeTempFile("/tmp/AssignTempBlocksTestData.XXXXXX",
478 NULL,
479 &fd));
480 ScopedFdCloser fd_closer(&fd);
481 off_t data_file_size = 0;
482
483
484 EXPECT_TRUE(DeltaDiffGenerator::ConvertGraphToDag(&graph,
485 temp_dir,
486 fd,
487 &data_file_size,
488 &final_order));
489
490
491 Graph expected_graph(12);
492 GenVertex(&expected_graph[0], empt, VectOfExt(200, 1), "", OP_REPLACE);
493 GenVertex(&expected_graph[1], empt, VectOfExt(210, 10), "", OP_REPLACE);
494 GenVertex(&expected_graph[2], empt, VectOfExt(220, 1), "", OP_REPLACE);
495 GenVertex(&expected_graph[3],
496 VectOfExt(10, 11),
497 VectOfExt(0, 9),
498 "",
499 OP_BSDIFF);
500 expected_graph[3].out_edges[9] = EdgeWithReadDep(VectOfExt(0, 9));
501 GenVertex(&expected_graph[4],
502 VectOfExt(60, 9),
503 VectOfExt(10, 11),
504 "",
505 OP_BSDIFF);
506 expected_graph[4].out_edges[3] = EdgeWithReadDep(VectOfExt(10, 11));
507 expected_graph[4].out_edges[9] = EdgeWithWriteDep(VectOfExt(60, 9));
508 GenVertex(&expected_graph[5],
509 VectOfExt(40, 11),
510 VectOfExt(30, 10),
511 "",
512 OP_BSDIFF);
513 expected_graph[5].out_edges[10] = EdgeWithReadDep(VectOfExt(30, 10));
514
515 GenVertex(&expected_graph[6],
516 VectOfExt(60, 10),
517 VectOfExt(40, 11),
518 "",
519 OP_BSDIFF);
520 expected_graph[6].out_edges[5] = EdgeWithReadDep(VectOfExt(40, 11));
521 expected_graph[6].out_edges[10] = EdgeWithWriteDep(VectOfExt(60, 10));
522
523 GenVertex(&expected_graph[7],
524 VectOfExt(120, 50),
525 VectOfExt(60, 40),
526 "",
527 OP_BSDIFF);
528 expected_graph[7].out_edges[6] = EdgeWithReadDep(VectOfExt(60, 10));
529
530 GenVertex(&expected_graph[8], empt, VectOfExt(0, 50), "/foo", OP_REPLACE_BZ);
531 expected_graph[8].out_edges[7] = EdgeWithReadDep(VectOfExt(120, 50));
532
533 GenVertex(&expected_graph[9],
534 VectOfExt(0, 9),
535 VectOfExt(60, 9),
536 "",
537 OP_MOVE);
538
539 GenVertex(&expected_graph[10],
540 VectOfExt(30, 10),
541 VectOfExt(60, 10),
542 "",
543 OP_MOVE);
544 expected_graph[10].out_edges[4] = EdgeWithReadDep(VectOfExt(60, 9));
545
546 EXPECT_EQ(12, graph.size());
547 EXPECT_FALSE(graph.back().valid);
548 for (Graph::size_type i = 0; i < graph.size() - 1; i++) {
549 EXPECT_TRUE(graph[i].out_edges == expected_graph[i].out_edges);
550 if (i == 8) {
551 // special case
552 } else {
553 // EXPECT_TRUE(graph[i] == expected_graph[i]) << "i = " << i;
554 }
555 }
556 }
557
351 } // namespace chromeos_update_engine 558 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « delta_diff_generator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698