blob: d897a0a2f37cf572cf0723445e4d97e9041cd31c [file] [log] [blame]
Darin Petkov68c10d12010-10-14 09:24:37 -07001// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <unistd.h>
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -08009#include <set>
Andrew de los Reyesef017552010-10-06 17:57:52 -070010#include <sstream>
adlr@google.com3defe6a2009-12-04 20:57:17 +000011#include <string>
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070012#include <utility>
adlr@google.com3defe6a2009-12-04 20:57:17 +000013#include <vector>
adlr@google.com3defe6a2009-12-04 20:57:17 +000014#include <gtest/gtest.h>
Chris Masone790e62e2010-08-12 10:41:18 -070015#include "base/logging.h"
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070016#include "update_engine/cycle_breaker.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000017#include "update_engine/delta_diff_generator.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070018#include "update_engine/delta_performer.h"
Andrew de los Reyesef017552010-10-06 17:57:52 -070019#include "update_engine/extent_ranges.h"
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070020#include "update_engine/graph_types.h"
21#include "update_engine/graph_utils.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000022#include "update_engine/subprocess.h"
23#include "update_engine/test_utils.h"
Andrew de los Reyesef017552010-10-06 17:57:52 -070024#include "update_engine/topological_sort.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000025#include "update_engine/utils.h"
26
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070027using std::make_pair;
28using std::set;
29using std::string;
Andrew de los Reyesef017552010-10-06 17:57:52 -070030using std::stringstream;
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070031using std::vector;
32
adlr@google.com3defe6a2009-12-04 20:57:17 +000033namespace chromeos_update_engine {
34
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070035typedef DeltaDiffGenerator::Block Block;
36
37namespace {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070038int64_t BlocksInExtents(
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070039 const google::protobuf::RepeatedPtrField<Extent>& extents) {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070040 int64_t ret = 0;
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070041 for (int i = 0; i < extents.size(); i++) {
42 ret += extents.Get(i).num_blocks();
43 }
44 return ret;
45}
46} // namespace {}
47
48class DeltaDiffGeneratorTest : public ::testing::Test {
49 protected:
50 const string old_path() { return "DeltaDiffGeneratorTest-old_path"; }
51 const string new_path() { return "DeltaDiffGeneratorTest-new_path"; }
52 virtual void TearDown() {
53 unlink(old_path().c_str());
54 unlink(new_path().c_str());
55 }
56};
57
58TEST_F(DeltaDiffGeneratorTest, RunAsRootMoveSmallTest) {
59 EXPECT_TRUE(utils::WriteFile(old_path().c_str(),
60 reinterpret_cast<const char*>(kRandomString),
61 sizeof(kRandomString)));
62 EXPECT_TRUE(utils::WriteFile(new_path().c_str(),
63 reinterpret_cast<const char*>(kRandomString),
64 sizeof(kRandomString)));
65 vector<char> data;
66 DeltaArchiveManifest_InstallOperation op;
67 EXPECT_TRUE(DeltaDiffGenerator::ReadFileToDiff(old_path(),
68 new_path(),
69 &data,
Darin Petkov68c10d12010-10-14 09:24:37 -070070 &op,
71 true));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -070072 EXPECT_TRUE(data.empty());
73
74 EXPECT_TRUE(op.has_type());
75 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_MOVE, op.type());
76 EXPECT_FALSE(op.has_data_offset());
77 EXPECT_FALSE(op.has_data_length());
78 EXPECT_EQ(1, op.src_extents_size());
79 EXPECT_EQ(sizeof(kRandomString), op.src_length());
80 EXPECT_EQ(1, op.dst_extents_size());
81 EXPECT_EQ(sizeof(kRandomString), op.dst_length());
82 EXPECT_EQ(BlocksInExtents(op.src_extents()),
83 BlocksInExtents(op.dst_extents()));
84 EXPECT_EQ(1, BlocksInExtents(op.dst_extents()));
85}
86
87TEST_F(DeltaDiffGeneratorTest, RunAsRootBsdiffSmallTest) {
88 EXPECT_TRUE(utils::WriteFile(old_path().c_str(),
89 reinterpret_cast<const char*>(kRandomString),
90 sizeof(kRandomString) - 1));
91 EXPECT_TRUE(utils::WriteFile(new_path().c_str(),
92 reinterpret_cast<const char*>(kRandomString),
93 sizeof(kRandomString)));
94 vector<char> data;
95 DeltaArchiveManifest_InstallOperation op;
96 EXPECT_TRUE(DeltaDiffGenerator::ReadFileToDiff(old_path(),
97 new_path(),
98 &data,
Darin Petkov68c10d12010-10-14 09:24:37 -070099 &op,
100 true));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700101 EXPECT_FALSE(data.empty());
102
103 EXPECT_TRUE(op.has_type());
104 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_BSDIFF, op.type());
105 EXPECT_FALSE(op.has_data_offset());
106 EXPECT_FALSE(op.has_data_length());
107 EXPECT_EQ(1, op.src_extents_size());
108 EXPECT_EQ(sizeof(kRandomString) - 1, op.src_length());
109 EXPECT_EQ(1, op.dst_extents_size());
110 EXPECT_EQ(sizeof(kRandomString), op.dst_length());
111 EXPECT_EQ(BlocksInExtents(op.src_extents()),
112 BlocksInExtents(op.dst_extents()));
113 EXPECT_EQ(1, BlocksInExtents(op.dst_extents()));
114}
115
116TEST_F(DeltaDiffGeneratorTest, RunAsRootReplaceSmallTest) {
117 vector<char> new_data;
118 for (int i = 0; i < 2; i++) {
119 new_data.insert(new_data.end(),
120 kRandomString,
121 kRandomString + sizeof(kRandomString));
122 EXPECT_TRUE(utils::WriteFile(new_path().c_str(),
123 &new_data[0],
124 new_data.size()));
125 vector<char> data;
126 DeltaArchiveManifest_InstallOperation op;
127 EXPECT_TRUE(DeltaDiffGenerator::ReadFileToDiff(old_path(),
128 new_path(),
129 &data,
Darin Petkov68c10d12010-10-14 09:24:37 -0700130 &op,
131 true));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700132 EXPECT_FALSE(data.empty());
133
134 EXPECT_TRUE(op.has_type());
135 const DeltaArchiveManifest_InstallOperation_Type expected_type =
136 (i == 0 ? DeltaArchiveManifest_InstallOperation_Type_REPLACE :
137 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
138 EXPECT_EQ(expected_type, op.type());
139 EXPECT_FALSE(op.has_data_offset());
140 EXPECT_FALSE(op.has_data_length());
141 EXPECT_EQ(0, op.src_extents_size());
142 EXPECT_FALSE(op.has_src_length());
143 EXPECT_EQ(1, op.dst_extents_size());
144 EXPECT_EQ(new_data.size(), op.dst_length());
145 EXPECT_EQ(1, BlocksInExtents(op.dst_extents()));
146 }
147}
148
Darin Petkov68c10d12010-10-14 09:24:37 -0700149TEST_F(DeltaDiffGeneratorTest, RunAsRootBsdiffNoGatherExtentsSmallTest) {
150 EXPECT_TRUE(utils::WriteFile(old_path().c_str(),
151 reinterpret_cast<const char*>(kRandomString),
152 sizeof(kRandomString) - 1));
153 EXPECT_TRUE(utils::WriteFile(new_path().c_str(),
154 reinterpret_cast<const char*>(kRandomString),
155 sizeof(kRandomString)));
156 vector<char> data;
157 DeltaArchiveManifest_InstallOperation op;
158 EXPECT_TRUE(DeltaDiffGenerator::ReadFileToDiff(old_path(),
159 new_path(),
160 &data,
161 &op,
162 false));
163 EXPECT_FALSE(data.empty());
164
165 EXPECT_TRUE(op.has_type());
166 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_BSDIFF, op.type());
167 EXPECT_FALSE(op.has_data_offset());
168 EXPECT_FALSE(op.has_data_length());
169 EXPECT_EQ(1, op.src_extents_size());
170 EXPECT_EQ(0, op.src_extents().Get(0).start_block());
171 EXPECT_EQ(1, op.src_extents().Get(0).num_blocks());
172 EXPECT_EQ(sizeof(kRandomString) - 1, op.src_length());
173 EXPECT_EQ(1, op.dst_extents_size());
174 EXPECT_EQ(0, op.dst_extents().Get(0).start_block());
175 EXPECT_EQ(1, op.dst_extents().Get(0).num_blocks());
176 EXPECT_EQ(sizeof(kRandomString), op.dst_length());
177}
178
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700179namespace {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700180void AppendExtent(vector<Extent>* vect, uint64_t start, uint64_t length) {
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700181 vect->resize(vect->size() + 1);
182 vect->back().set_start_block(start);
183 vect->back().set_num_blocks(length);
184}
185void OpAppendExtent(DeltaArchiveManifest_InstallOperation* op,
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700186 uint64_t start,
187 uint64_t length) {
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700188 Extent* extent = op->add_src_extents();
189 extent->set_start_block(start);
190 extent->set_num_blocks(length);
191}
192}
193
194TEST_F(DeltaDiffGeneratorTest, SubstituteBlocksTest) {
195 vector<Extent> remove_blocks;
196 AppendExtent(&remove_blocks, 3, 3);
197 AppendExtent(&remove_blocks, 7, 1);
198 vector<Extent> replace_blocks;
199 AppendExtent(&replace_blocks, 10, 2);
200 AppendExtent(&replace_blocks, 13, 2);
Andrew de los Reyesef017552010-10-06 17:57:52 -0700201 Vertex vertex;
202 DeltaArchiveManifest_InstallOperation& op = vertex.op;
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700203 OpAppendExtent(&op, 4, 3);
204 OpAppendExtent(&op, kSparseHole, 4); // Sparse hole in file
205 OpAppendExtent(&op, 3, 1);
206 OpAppendExtent(&op, 7, 3);
Darin Petkov68c10d12010-10-14 09:24:37 -0700207
Andrew de los Reyesef017552010-10-06 17:57:52 -0700208 DeltaDiffGenerator::SubstituteBlocks(&vertex, remove_blocks, replace_blocks);
Darin Petkov68c10d12010-10-14 09:24:37 -0700209
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700210 EXPECT_EQ(7, op.src_extents_size());
211 EXPECT_EQ(11, op.src_extents(0).start_block());
212 EXPECT_EQ(1, op.src_extents(0).num_blocks());
213 EXPECT_EQ(13, op.src_extents(1).start_block());
214 EXPECT_EQ(1, op.src_extents(1).num_blocks());
215 EXPECT_EQ(6, op.src_extents(2).start_block());
216 EXPECT_EQ(1, op.src_extents(2).num_blocks());
217 EXPECT_EQ(kSparseHole, op.src_extents(3).start_block());
218 EXPECT_EQ(4, op.src_extents(3).num_blocks());
219 EXPECT_EQ(10, op.src_extents(4).start_block());
220 EXPECT_EQ(1, op.src_extents(4).num_blocks());
221 EXPECT_EQ(14, op.src_extents(5).start_block());
222 EXPECT_EQ(1, op.src_extents(5).num_blocks());
223 EXPECT_EQ(8, op.src_extents(6).start_block());
224 EXPECT_EQ(2, op.src_extents(6).num_blocks());
225}
226
227TEST_F(DeltaDiffGeneratorTest, CutEdgesTest) {
228 Graph graph;
229 vector<Block> blocks(9);
Darin Petkov68c10d12010-10-14 09:24:37 -0700230
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700231 // Create nodes in graph
232 {
233 graph.resize(graph.size() + 1);
234 graph.back().op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE);
235 // Reads from blocks 3, 5, 7
236 vector<Extent> extents;
237 graph_utils::AppendBlockToExtents(&extents, 3);
238 graph_utils::AppendBlockToExtents(&extents, 5);
239 graph_utils::AppendBlockToExtents(&extents, 7);
240 DeltaDiffGenerator::StoreExtents(extents,
241 graph.back().op.mutable_src_extents());
242 blocks[3].reader = graph.size() - 1;
243 blocks[5].reader = graph.size() - 1;
244 blocks[7].reader = graph.size() - 1;
Darin Petkov68c10d12010-10-14 09:24:37 -0700245
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700246 // Writes to blocks 1, 2, 4
247 extents.clear();
248 graph_utils::AppendBlockToExtents(&extents, 1);
249 graph_utils::AppendBlockToExtents(&extents, 2);
250 graph_utils::AppendBlockToExtents(&extents, 4);
251 DeltaDiffGenerator::StoreExtents(extents,
252 graph.back().op.mutable_dst_extents());
253 blocks[1].writer = graph.size() - 1;
254 blocks[2].writer = graph.size() - 1;
255 blocks[4].writer = graph.size() - 1;
256 }
257 {
258 graph.resize(graph.size() + 1);
259 graph.back().op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE);
260 // Reads from blocks 1, 2, 4
261 vector<Extent> extents;
262 graph_utils::AppendBlockToExtents(&extents, 1);
263 graph_utils::AppendBlockToExtents(&extents, 2);
264 graph_utils::AppendBlockToExtents(&extents, 4);
265 DeltaDiffGenerator::StoreExtents(extents,
266 graph.back().op.mutable_src_extents());
267 blocks[1].reader = graph.size() - 1;
268 blocks[2].reader = graph.size() - 1;
269 blocks[4].reader = graph.size() - 1;
Darin Petkov68c10d12010-10-14 09:24:37 -0700270
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700271 // Writes to blocks 3, 5, 6
272 extents.clear();
273 graph_utils::AppendBlockToExtents(&extents, 3);
274 graph_utils::AppendBlockToExtents(&extents, 5);
275 graph_utils::AppendBlockToExtents(&extents, 6);
276 DeltaDiffGenerator::StoreExtents(extents,
277 graph.back().op.mutable_dst_extents());
278 blocks[3].writer = graph.size() - 1;
279 blocks[5].writer = graph.size() - 1;
280 blocks[6].writer = graph.size() - 1;
281 }
Darin Petkov68c10d12010-10-14 09:24:37 -0700282
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700283 // Create edges
284 DeltaDiffGenerator::CreateEdges(&graph, blocks);
Darin Petkov68c10d12010-10-14 09:24:37 -0700285
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700286 // Find cycles
287 CycleBreaker cycle_breaker;
288 set<Edge> cut_edges;
289 cycle_breaker.BreakCycles(graph, &cut_edges);
290
291 EXPECT_EQ(1, cut_edges.size());
292 EXPECT_TRUE(cut_edges.end() != cut_edges.find(make_pair<Vertex::Index>(1,
293 0)));
294
Andrew de los Reyesef017552010-10-06 17:57:52 -0700295 vector<CutEdgeVertexes> cuts;
296 EXPECT_TRUE(DeltaDiffGenerator::CutEdges(&graph, cut_edges, &cuts));
Darin Petkov68c10d12010-10-14 09:24:37 -0700297
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700298 EXPECT_EQ(3, graph.size());
Darin Petkov68c10d12010-10-14 09:24:37 -0700299
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700300 // Check new node in graph:
301 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_MOVE,
302 graph.back().op.type());
303 EXPECT_EQ(2, graph.back().op.src_extents_size());
Andrew de los Reyesef017552010-10-06 17:57:52 -0700304 EXPECT_EQ(1, graph.back().op.dst_extents_size());
305 EXPECT_EQ(kTempBlockStart, graph.back().op.dst_extents(0).start_block());
306 EXPECT_EQ(2, graph.back().op.dst_extents(0).num_blocks());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700307 EXPECT_TRUE(graph.back().out_edges.empty());
Darin Petkov68c10d12010-10-14 09:24:37 -0700308
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700309 // Check that old node reads from new blocks
Andrew de los Reyesef017552010-10-06 17:57:52 -0700310 EXPECT_EQ(2, graph[0].op.src_extents_size());
311 EXPECT_EQ(kTempBlockStart, graph[0].op.src_extents(0).start_block());
312 EXPECT_EQ(2, graph[0].op.src_extents(0).num_blocks());
313 EXPECT_EQ(7, graph[0].op.src_extents(1).start_block());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700314 EXPECT_EQ(1, graph[0].op.src_extents(1).num_blocks());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700315
316 // And that the old dst extents haven't changed
317 EXPECT_EQ(2, graph[0].op.dst_extents_size());
318 EXPECT_EQ(1, graph[0].op.dst_extents(0).start_block());
319 EXPECT_EQ(2, graph[0].op.dst_extents(0).num_blocks());
320 EXPECT_EQ(4, graph[0].op.dst_extents(1).start_block());
321 EXPECT_EQ(1, graph[0].op.dst_extents(1).num_blocks());
Andrew de los Reyesd12784c2010-07-26 13:55:14 -0700322
323 // Ensure it only depends on the next node and the new temp node
324 EXPECT_EQ(2, graph[0].out_edges.size());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700325 EXPECT_TRUE(graph[0].out_edges.end() != graph[0].out_edges.find(1));
Andrew de los Reyesd12784c2010-07-26 13:55:14 -0700326 EXPECT_TRUE(graph[0].out_edges.end() != graph[0].out_edges.find(graph.size() -
327 1));
328
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700329 // Check second node has unchanged extents
330 EXPECT_EQ(2, graph[1].op.src_extents_size());
331 EXPECT_EQ(1, graph[1].op.src_extents(0).start_block());
332 EXPECT_EQ(2, graph[1].op.src_extents(0).num_blocks());
333 EXPECT_EQ(4, graph[1].op.src_extents(1).start_block());
334 EXPECT_EQ(1, graph[1].op.src_extents(1).num_blocks());
335
336 EXPECT_EQ(2, graph[1].op.dst_extents_size());
337 EXPECT_EQ(3, graph[1].op.dst_extents(0).start_block());
338 EXPECT_EQ(1, graph[1].op.dst_extents(0).num_blocks());
339 EXPECT_EQ(5, graph[1].op.dst_extents(1).start_block());
340 EXPECT_EQ(2, graph[1].op.dst_extents(1).num_blocks());
Darin Petkov68c10d12010-10-14 09:24:37 -0700341
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700342 // Ensure it only depends on the next node
343 EXPECT_EQ(1, graph[1].out_edges.size());
344 EXPECT_TRUE(graph[1].out_edges.end() != graph[1].out_edges.find(2));
345}
346
347TEST_F(DeltaDiffGeneratorTest, ReorderBlobsTest) {
348 string orig_blobs;
349 EXPECT_TRUE(
350 utils::MakeTempFile("ReorderBlobsTest.orig.XXXXXX", &orig_blobs, NULL));
351
352 string orig_data = "abcd";
353 EXPECT_TRUE(
354 utils::WriteFile(orig_blobs.c_str(), orig_data.data(), orig_data.size()));
355
356 string new_blobs;
357 EXPECT_TRUE(
358 utils::MakeTempFile("ReorderBlobsTest.new.XXXXXX", &new_blobs, NULL));
Darin Petkov68c10d12010-10-14 09:24:37 -0700359
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700360 DeltaArchiveManifest manifest;
361 DeltaArchiveManifest_InstallOperation* op =
362 manifest.add_install_operations();
363 op->set_data_offset(1);
364 op->set_data_length(3);
365 op = manifest.add_install_operations();
366 op->set_data_offset(0);
367 op->set_data_length(1);
Darin Petkov68c10d12010-10-14 09:24:37 -0700368
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700369 EXPECT_TRUE(DeltaDiffGenerator::ReorderDataBlobs(&manifest,
370 orig_blobs,
371 new_blobs));
Darin Petkov68c10d12010-10-14 09:24:37 -0700372
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700373 string new_data;
374 EXPECT_TRUE(utils::ReadFileToString(new_blobs, &new_data));
375 EXPECT_EQ("bcda", new_data);
376 EXPECT_EQ(2, manifest.install_operations_size());
377 EXPECT_EQ(0, manifest.install_operations(0).data_offset());
378 EXPECT_EQ(3, manifest.install_operations(0).data_length());
379 EXPECT_EQ(3, manifest.install_operations(1).data_offset());
380 EXPECT_EQ(1, manifest.install_operations(1).data_length());
Darin Petkov68c10d12010-10-14 09:24:37 -0700381
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700382 unlink(orig_blobs.c_str());
383 unlink(new_blobs.c_str());
384}
adlr@google.com3defe6a2009-12-04 20:57:17 +0000385
Andrew de los Reyesef017552010-10-06 17:57:52 -0700386TEST_F(DeltaDiffGeneratorTest, MoveFullOpsToBackTest) {
387 Graph graph(4);
388 graph[0].file_name = "A";
389 graph[0].op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE);
390 graph[1].file_name = "B";
391 graph[1].op.set_type(DeltaArchiveManifest_InstallOperation_Type_BSDIFF);
392 graph[2].file_name = "C";
393 graph[2].op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
394 graph[3].file_name = "D";
395 graph[3].op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE);
396
397 vector<Vertex::Index> vect(graph.size());
398
399 for (vector<Vertex::Index>::size_type i = 0; i < vect.size(); ++i) {
400 vect[i] = i;
401 }
402 DeltaDiffGenerator::MoveFullOpsToBack(&graph, &vect);
403 EXPECT_EQ(vect.size(), graph.size());
404 EXPECT_EQ(graph[vect[0]].file_name, "B");
405 EXPECT_EQ(graph[vect[1]].file_name, "D");
406 EXPECT_EQ(graph[vect[2]].file_name, "A");
407 EXPECT_EQ(graph[vect[3]].file_name, "C");
408}
409
410namespace {
411
412#define OP_BSDIFF DeltaArchiveManifest_InstallOperation_Type_BSDIFF
413#define OP_MOVE DeltaArchiveManifest_InstallOperation_Type_MOVE
414#define OP_REPLACE DeltaArchiveManifest_InstallOperation_Type_REPLACE
415#define OP_REPLACE_BZ DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ
416
417void GenVertex(Vertex* out,
418 const vector<Extent>& src_extents,
419 const vector<Extent>& dst_extents,
420 const string& path,
421 DeltaArchiveManifest_InstallOperation_Type type) {
422 out->op.set_type(type);
423 out->file_name = path;
424 DeltaDiffGenerator::StoreExtents(src_extents, out->op.mutable_src_extents());
425 DeltaDiffGenerator::StoreExtents(dst_extents, out->op.mutable_dst_extents());
426}
427
428vector<Extent> VectOfExt(uint64_t start_block, uint64_t num_blocks) {
429 return vector<Extent>(1, ExtentForRange(start_block, num_blocks));
430}
431
432EdgeProperties EdgeWithReadDep(const vector<Extent>& extents) {
433 EdgeProperties ret;
434 ret.extents = extents;
435 return ret;
436}
437
438EdgeProperties EdgeWithWriteDep(const vector<Extent>& extents) {
439 EdgeProperties ret;
440 ret.write_extents = extents;
441 return ret;
442}
443
444template<typename T>
445void DumpVect(const vector<T>& vect) {
446 std::stringstream ss(stringstream::out);
447 for (typename vector<T>::const_iterator it = vect.begin(), e = vect.end();
448 it != e; ++it) {
449 ss << *it << ", ";
450 }
451 LOG(INFO) << "{" << ss.str() << "}";
452}
453
454} // namespace {}
455
456TEST_F(DeltaDiffGeneratorTest, RunAsRootAssignTempBlocksTest) {
457 Graph graph(9);
458 const vector<Extent> empt; // empty
459 const string kFilename = "/foo";
Darin Petkov68c10d12010-10-14 09:24:37 -0700460
Andrew de los Reyesef017552010-10-06 17:57:52 -0700461 // Some scratch space:
462 GenVertex(&graph[0], empt, VectOfExt(200, 1), "", OP_REPLACE);
463 GenVertex(&graph[1], empt, VectOfExt(210, 10), "", OP_REPLACE);
464 GenVertex(&graph[2], empt, VectOfExt(220, 1), "", OP_REPLACE);
465
466 // A cycle that requires 10 blocks to break:
467 GenVertex(&graph[3], VectOfExt(10, 11), VectOfExt(0, 9), "", OP_BSDIFF);
468 graph[3].out_edges[4] = EdgeWithReadDep(VectOfExt(0, 9));
469 GenVertex(&graph[4], VectOfExt(0, 9), VectOfExt(10, 11), "", OP_BSDIFF);
470 graph[4].out_edges[3] = EdgeWithReadDep(VectOfExt(10, 11));
471
472 // A cycle that requires 9 blocks to break:
473 GenVertex(&graph[5], VectOfExt(40, 11), VectOfExt(30, 10), "", OP_BSDIFF);
474 graph[5].out_edges[6] = EdgeWithReadDep(VectOfExt(30, 10));
475 GenVertex(&graph[6], VectOfExt(30, 10), VectOfExt(40, 11), "", OP_BSDIFF);
476 graph[6].out_edges[5] = EdgeWithReadDep(VectOfExt(40, 11));
477
478 // A cycle that requires 40 blocks to break (which is too many):
479 GenVertex(&graph[7],
480 VectOfExt(120, 50),
481 VectOfExt(60, 40),
482 "",
483 OP_BSDIFF);
484 graph[7].out_edges[8] = EdgeWithReadDep(VectOfExt(60, 40));
485 GenVertex(&graph[8],
486 VectOfExt(60, 40),
487 VectOfExt(120, 50),
488 kFilename,
489 OP_BSDIFF);
490 graph[8].out_edges[7] = EdgeWithReadDep(VectOfExt(120, 50));
Darin Petkov68c10d12010-10-14 09:24:37 -0700491
Andrew de los Reyesef017552010-10-06 17:57:52 -0700492 graph_utils::DumpGraph(graph);
Darin Petkov68c10d12010-10-14 09:24:37 -0700493
Andrew de los Reyesef017552010-10-06 17:57:52 -0700494 vector<Vertex::Index> final_order;
495
496
497 // Prepare the filesystem with the minimum required for this to work
498 string temp_dir;
499 EXPECT_TRUE(utils::MakeTempDirectory("/tmp/AssignTempBlocksTest.XXXXXX",
500 &temp_dir));
501 ScopedDirRemover temp_dir_remover(temp_dir);
Darin Petkov68c10d12010-10-14 09:24:37 -0700502
Andrew de los Reyesef017552010-10-06 17:57:52 -0700503 const size_t kBlockSize = 4096;
504 vector<char> temp_data(kBlockSize * 50);
505 FillWithData(&temp_data);
506 EXPECT_TRUE(WriteFileVector(temp_dir + kFilename, temp_data));
507 ScopedPathUnlinker filename_unlinker(temp_dir + kFilename);
Darin Petkov68c10d12010-10-14 09:24:37 -0700508
Andrew de los Reyesef017552010-10-06 17:57:52 -0700509 int fd;
510 EXPECT_TRUE(utils::MakeTempFile("/tmp/AssignTempBlocksTestData.XXXXXX",
511 NULL,
512 &fd));
513 ScopedFdCloser fd_closer(&fd);
514 off_t data_file_size = 0;
515
516
517 EXPECT_TRUE(DeltaDiffGenerator::ConvertGraphToDag(&graph,
518 temp_dir,
519 fd,
520 &data_file_size,
521 &final_order));
522
Darin Petkov68c10d12010-10-14 09:24:37 -0700523
Andrew de los Reyesef017552010-10-06 17:57:52 -0700524 Graph expected_graph(12);
525 GenVertex(&expected_graph[0], empt, VectOfExt(200, 1), "", OP_REPLACE);
526 GenVertex(&expected_graph[1], empt, VectOfExt(210, 10), "", OP_REPLACE);
527 GenVertex(&expected_graph[2], empt, VectOfExt(220, 1), "", OP_REPLACE);
528 GenVertex(&expected_graph[3],
529 VectOfExt(10, 11),
530 VectOfExt(0, 9),
531 "",
532 OP_BSDIFF);
533 expected_graph[3].out_edges[9] = EdgeWithReadDep(VectOfExt(0, 9));
534 GenVertex(&expected_graph[4],
535 VectOfExt(60, 9),
536 VectOfExt(10, 11),
537 "",
538 OP_BSDIFF);
539 expected_graph[4].out_edges[3] = EdgeWithReadDep(VectOfExt(10, 11));
540 expected_graph[4].out_edges[9] = EdgeWithWriteDep(VectOfExt(60, 9));
541 GenVertex(&expected_graph[5],
542 VectOfExt(40, 11),
543 VectOfExt(30, 10),
544 "",
545 OP_BSDIFF);
546 expected_graph[5].out_edges[10] = EdgeWithReadDep(VectOfExt(30, 10));
547
548 GenVertex(&expected_graph[6],
549 VectOfExt(60, 10),
550 VectOfExt(40, 11),
551 "",
552 OP_BSDIFF);
553 expected_graph[6].out_edges[5] = EdgeWithReadDep(VectOfExt(40, 11));
554 expected_graph[6].out_edges[10] = EdgeWithWriteDep(VectOfExt(60, 10));
Darin Petkov68c10d12010-10-14 09:24:37 -0700555
Andrew de los Reyesef017552010-10-06 17:57:52 -0700556 GenVertex(&expected_graph[7],
557 VectOfExt(120, 50),
558 VectOfExt(60, 40),
559 "",
560 OP_BSDIFF);
561 expected_graph[7].out_edges[6] = EdgeWithReadDep(VectOfExt(60, 10));
562
563 GenVertex(&expected_graph[8], empt, VectOfExt(0, 50), "/foo", OP_REPLACE_BZ);
564 expected_graph[8].out_edges[7] = EdgeWithReadDep(VectOfExt(120, 50));
565
566 GenVertex(&expected_graph[9],
567 VectOfExt(0, 9),
568 VectOfExt(60, 9),
569 "",
570 OP_MOVE);
571
572 GenVertex(&expected_graph[10],
573 VectOfExt(30, 10),
574 VectOfExt(60, 10),
575 "",
576 OP_MOVE);
577 expected_graph[10].out_edges[4] = EdgeWithReadDep(VectOfExt(60, 9));
Darin Petkov68c10d12010-10-14 09:24:37 -0700578
Andrew de los Reyesef017552010-10-06 17:57:52 -0700579 EXPECT_EQ(12, graph.size());
580 EXPECT_FALSE(graph.back().valid);
581 for (Graph::size_type i = 0; i < graph.size() - 1; i++) {
582 EXPECT_TRUE(graph[i].out_edges == expected_graph[i].out_edges);
583 if (i == 8) {
584 // special case
585 } else {
586 // EXPECT_TRUE(graph[i] == expected_graph[i]) << "i = " << i;
587 }
588 }
589}
590
adlr@google.com3defe6a2009-12-04 20:57:17 +0000591} // namespace chromeos_update_engine