blob: 0d7b0fe20903fdd423642932c7c429128f672636 [file] [log] [blame]
adlr@google.com3defe6a2009-12-04 20:57:17 +00001// 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
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,
70 &op));
71 EXPECT_TRUE(data.empty());
72
73 EXPECT_TRUE(op.has_type());
74 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_MOVE, op.type());
75 EXPECT_FALSE(op.has_data_offset());
76 EXPECT_FALSE(op.has_data_length());
77 EXPECT_EQ(1, op.src_extents_size());
78 EXPECT_EQ(sizeof(kRandomString), op.src_length());
79 EXPECT_EQ(1, op.dst_extents_size());
80 EXPECT_EQ(sizeof(kRandomString), op.dst_length());
81 EXPECT_EQ(BlocksInExtents(op.src_extents()),
82 BlocksInExtents(op.dst_extents()));
83 EXPECT_EQ(1, BlocksInExtents(op.dst_extents()));
84}
85
86TEST_F(DeltaDiffGeneratorTest, RunAsRootBsdiffSmallTest) {
87 EXPECT_TRUE(utils::WriteFile(old_path().c_str(),
88 reinterpret_cast<const char*>(kRandomString),
89 sizeof(kRandomString) - 1));
90 EXPECT_TRUE(utils::WriteFile(new_path().c_str(),
91 reinterpret_cast<const char*>(kRandomString),
92 sizeof(kRandomString)));
93 vector<char> data;
94 DeltaArchiveManifest_InstallOperation op;
95 EXPECT_TRUE(DeltaDiffGenerator::ReadFileToDiff(old_path(),
96 new_path(),
97 &data,
98 &op));
99 EXPECT_FALSE(data.empty());
100
101 EXPECT_TRUE(op.has_type());
102 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_BSDIFF, op.type());
103 EXPECT_FALSE(op.has_data_offset());
104 EXPECT_FALSE(op.has_data_length());
105 EXPECT_EQ(1, op.src_extents_size());
106 EXPECT_EQ(sizeof(kRandomString) - 1, op.src_length());
107 EXPECT_EQ(1, op.dst_extents_size());
108 EXPECT_EQ(sizeof(kRandomString), op.dst_length());
109 EXPECT_EQ(BlocksInExtents(op.src_extents()),
110 BlocksInExtents(op.dst_extents()));
111 EXPECT_EQ(1, BlocksInExtents(op.dst_extents()));
112}
113
114TEST_F(DeltaDiffGeneratorTest, RunAsRootReplaceSmallTest) {
115 vector<char> new_data;
116 for (int i = 0; i < 2; i++) {
117 new_data.insert(new_data.end(),
118 kRandomString,
119 kRandomString + sizeof(kRandomString));
120 EXPECT_TRUE(utils::WriteFile(new_path().c_str(),
121 &new_data[0],
122 new_data.size()));
123 vector<char> data;
124 DeltaArchiveManifest_InstallOperation op;
125 EXPECT_TRUE(DeltaDiffGenerator::ReadFileToDiff(old_path(),
126 new_path(),
127 &data,
128 &op));
129 EXPECT_FALSE(data.empty());
130
131 EXPECT_TRUE(op.has_type());
132 const DeltaArchiveManifest_InstallOperation_Type expected_type =
133 (i == 0 ? DeltaArchiveManifest_InstallOperation_Type_REPLACE :
134 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
135 EXPECT_EQ(expected_type, op.type());
136 EXPECT_FALSE(op.has_data_offset());
137 EXPECT_FALSE(op.has_data_length());
138 EXPECT_EQ(0, op.src_extents_size());
139 EXPECT_FALSE(op.has_src_length());
140 EXPECT_EQ(1, op.dst_extents_size());
141 EXPECT_EQ(new_data.size(), op.dst_length());
142 EXPECT_EQ(1, BlocksInExtents(op.dst_extents()));
143 }
144}
145
146namespace {
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700147void AppendExtent(vector<Extent>* vect, uint64_t start, uint64_t length) {
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700148 vect->resize(vect->size() + 1);
149 vect->back().set_start_block(start);
150 vect->back().set_num_blocks(length);
151}
152void OpAppendExtent(DeltaArchiveManifest_InstallOperation* op,
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700153 uint64_t start,
154 uint64_t length) {
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700155 Extent* extent = op->add_src_extents();
156 extent->set_start_block(start);
157 extent->set_num_blocks(length);
158}
159}
160
161TEST_F(DeltaDiffGeneratorTest, SubstituteBlocksTest) {
162 vector<Extent> remove_blocks;
163 AppendExtent(&remove_blocks, 3, 3);
164 AppendExtent(&remove_blocks, 7, 1);
165 vector<Extent> replace_blocks;
166 AppendExtent(&replace_blocks, 10, 2);
167 AppendExtent(&replace_blocks, 13, 2);
Andrew de los Reyesef017552010-10-06 17:57:52 -0700168 Vertex vertex;
169 DeltaArchiveManifest_InstallOperation& op = vertex.op;
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700170 OpAppendExtent(&op, 4, 3);
171 OpAppendExtent(&op, kSparseHole, 4); // Sparse hole in file
172 OpAppendExtent(&op, 3, 1);
173 OpAppendExtent(&op, 7, 3);
174
Andrew de los Reyesef017552010-10-06 17:57:52 -0700175 DeltaDiffGenerator::SubstituteBlocks(&vertex, remove_blocks, replace_blocks);
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700176
177 EXPECT_EQ(7, op.src_extents_size());
178 EXPECT_EQ(11, op.src_extents(0).start_block());
179 EXPECT_EQ(1, op.src_extents(0).num_blocks());
180 EXPECT_EQ(13, op.src_extents(1).start_block());
181 EXPECT_EQ(1, op.src_extents(1).num_blocks());
182 EXPECT_EQ(6, op.src_extents(2).start_block());
183 EXPECT_EQ(1, op.src_extents(2).num_blocks());
184 EXPECT_EQ(kSparseHole, op.src_extents(3).start_block());
185 EXPECT_EQ(4, op.src_extents(3).num_blocks());
186 EXPECT_EQ(10, op.src_extents(4).start_block());
187 EXPECT_EQ(1, op.src_extents(4).num_blocks());
188 EXPECT_EQ(14, op.src_extents(5).start_block());
189 EXPECT_EQ(1, op.src_extents(5).num_blocks());
190 EXPECT_EQ(8, op.src_extents(6).start_block());
191 EXPECT_EQ(2, op.src_extents(6).num_blocks());
192}
193
194TEST_F(DeltaDiffGeneratorTest, CutEdgesTest) {
195 Graph graph;
196 vector<Block> blocks(9);
197
198 // Create nodes in graph
199 {
200 graph.resize(graph.size() + 1);
201 graph.back().op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE);
202 // Reads from blocks 3, 5, 7
203 vector<Extent> extents;
204 graph_utils::AppendBlockToExtents(&extents, 3);
205 graph_utils::AppendBlockToExtents(&extents, 5);
206 graph_utils::AppendBlockToExtents(&extents, 7);
207 DeltaDiffGenerator::StoreExtents(extents,
208 graph.back().op.mutable_src_extents());
209 blocks[3].reader = graph.size() - 1;
210 blocks[5].reader = graph.size() - 1;
211 blocks[7].reader = graph.size() - 1;
212
213 // Writes to blocks 1, 2, 4
214 extents.clear();
215 graph_utils::AppendBlockToExtents(&extents, 1);
216 graph_utils::AppendBlockToExtents(&extents, 2);
217 graph_utils::AppendBlockToExtents(&extents, 4);
218 DeltaDiffGenerator::StoreExtents(extents,
219 graph.back().op.mutable_dst_extents());
220 blocks[1].writer = graph.size() - 1;
221 blocks[2].writer = graph.size() - 1;
222 blocks[4].writer = graph.size() - 1;
223 }
224 {
225 graph.resize(graph.size() + 1);
226 graph.back().op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE);
227 // Reads from blocks 1, 2, 4
228 vector<Extent> extents;
229 graph_utils::AppendBlockToExtents(&extents, 1);
230 graph_utils::AppendBlockToExtents(&extents, 2);
231 graph_utils::AppendBlockToExtents(&extents, 4);
232 DeltaDiffGenerator::StoreExtents(extents,
233 graph.back().op.mutable_src_extents());
234 blocks[1].reader = graph.size() - 1;
235 blocks[2].reader = graph.size() - 1;
236 blocks[4].reader = graph.size() - 1;
237
238 // Writes to blocks 3, 5, 6
239 extents.clear();
240 graph_utils::AppendBlockToExtents(&extents, 3);
241 graph_utils::AppendBlockToExtents(&extents, 5);
242 graph_utils::AppendBlockToExtents(&extents, 6);
243 DeltaDiffGenerator::StoreExtents(extents,
244 graph.back().op.mutable_dst_extents());
245 blocks[3].writer = graph.size() - 1;
246 blocks[5].writer = graph.size() - 1;
247 blocks[6].writer = graph.size() - 1;
248 }
249
250 // Create edges
251 DeltaDiffGenerator::CreateEdges(&graph, blocks);
252
253 // Find cycles
254 CycleBreaker cycle_breaker;
255 set<Edge> cut_edges;
256 cycle_breaker.BreakCycles(graph, &cut_edges);
257
258 EXPECT_EQ(1, cut_edges.size());
259 EXPECT_TRUE(cut_edges.end() != cut_edges.find(make_pair<Vertex::Index>(1,
260 0)));
261
Andrew de los Reyesef017552010-10-06 17:57:52 -0700262 vector<CutEdgeVertexes> cuts;
263 EXPECT_TRUE(DeltaDiffGenerator::CutEdges(&graph, cut_edges, &cuts));
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700264
265 EXPECT_EQ(3, graph.size());
266
267 // Check new node in graph:
268 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_MOVE,
269 graph.back().op.type());
270 EXPECT_EQ(2, graph.back().op.src_extents_size());
Andrew de los Reyesef017552010-10-06 17:57:52 -0700271 EXPECT_EQ(1, graph.back().op.dst_extents_size());
272 EXPECT_EQ(kTempBlockStart, graph.back().op.dst_extents(0).start_block());
273 EXPECT_EQ(2, graph.back().op.dst_extents(0).num_blocks());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700274 EXPECT_TRUE(graph.back().out_edges.empty());
275
276 // Check that old node reads from new blocks
Andrew de los Reyesef017552010-10-06 17:57:52 -0700277 EXPECT_EQ(2, graph[0].op.src_extents_size());
278 EXPECT_EQ(kTempBlockStart, graph[0].op.src_extents(0).start_block());
279 EXPECT_EQ(2, graph[0].op.src_extents(0).num_blocks());
280 EXPECT_EQ(7, graph[0].op.src_extents(1).start_block());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700281 EXPECT_EQ(1, graph[0].op.src_extents(1).num_blocks());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700282
283 // And that the old dst extents haven't changed
284 EXPECT_EQ(2, graph[0].op.dst_extents_size());
285 EXPECT_EQ(1, graph[0].op.dst_extents(0).start_block());
286 EXPECT_EQ(2, graph[0].op.dst_extents(0).num_blocks());
287 EXPECT_EQ(4, graph[0].op.dst_extents(1).start_block());
288 EXPECT_EQ(1, graph[0].op.dst_extents(1).num_blocks());
Andrew de los Reyesd12784c2010-07-26 13:55:14 -0700289
290 // Ensure it only depends on the next node and the new temp node
291 EXPECT_EQ(2, graph[0].out_edges.size());
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700292 EXPECT_TRUE(graph[0].out_edges.end() != graph[0].out_edges.find(1));
Andrew de los Reyesd12784c2010-07-26 13:55:14 -0700293 EXPECT_TRUE(graph[0].out_edges.end() != graph[0].out_edges.find(graph.size() -
294 1));
295
Andrew de los Reyesb10320d2010-03-31 16:44:44 -0700296 // Check second node has unchanged extents
297 EXPECT_EQ(2, graph[1].op.src_extents_size());
298 EXPECT_EQ(1, graph[1].op.src_extents(0).start_block());
299 EXPECT_EQ(2, graph[1].op.src_extents(0).num_blocks());
300 EXPECT_EQ(4, graph[1].op.src_extents(1).start_block());
301 EXPECT_EQ(1, graph[1].op.src_extents(1).num_blocks());
302
303 EXPECT_EQ(2, graph[1].op.dst_extents_size());
304 EXPECT_EQ(3, graph[1].op.dst_extents(0).start_block());
305 EXPECT_EQ(1, graph[1].op.dst_extents(0).num_blocks());
306 EXPECT_EQ(5, graph[1].op.dst_extents(1).start_block());
307 EXPECT_EQ(2, graph[1].op.dst_extents(1).num_blocks());
308
309 // Ensure it only depends on the next node
310 EXPECT_EQ(1, graph[1].out_edges.size());
311 EXPECT_TRUE(graph[1].out_edges.end() != graph[1].out_edges.find(2));
312}
313
314TEST_F(DeltaDiffGeneratorTest, ReorderBlobsTest) {
315 string orig_blobs;
316 EXPECT_TRUE(
317 utils::MakeTempFile("ReorderBlobsTest.orig.XXXXXX", &orig_blobs, NULL));
318
319 string orig_data = "abcd";
320 EXPECT_TRUE(
321 utils::WriteFile(orig_blobs.c_str(), orig_data.data(), orig_data.size()));
322
323 string new_blobs;
324 EXPECT_TRUE(
325 utils::MakeTempFile("ReorderBlobsTest.new.XXXXXX", &new_blobs, NULL));
326
327 DeltaArchiveManifest manifest;
328 DeltaArchiveManifest_InstallOperation* op =
329 manifest.add_install_operations();
330 op->set_data_offset(1);
331 op->set_data_length(3);
332 op = manifest.add_install_operations();
333 op->set_data_offset(0);
334 op->set_data_length(1);
335
336 EXPECT_TRUE(DeltaDiffGenerator::ReorderDataBlobs(&manifest,
337 orig_blobs,
338 new_blobs));
339
340 string new_data;
341 EXPECT_TRUE(utils::ReadFileToString(new_blobs, &new_data));
342 EXPECT_EQ("bcda", new_data);
343 EXPECT_EQ(2, manifest.install_operations_size());
344 EXPECT_EQ(0, manifest.install_operations(0).data_offset());
345 EXPECT_EQ(3, manifest.install_operations(0).data_length());
346 EXPECT_EQ(3, manifest.install_operations(1).data_offset());
347 EXPECT_EQ(1, manifest.install_operations(1).data_length());
348
349 unlink(orig_blobs.c_str());
350 unlink(new_blobs.c_str());
351}
adlr@google.com3defe6a2009-12-04 20:57:17 +0000352
Andrew de los Reyesef017552010-10-06 17:57:52 -0700353TEST_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
377namespace {
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
384void 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
395vector<Extent> VectOfExt(uint64_t start_block, uint64_t num_blocks) {
396 return vector<Extent>(1, ExtentForRange(start_block, num_blocks));
397}
398
399EdgeProperties EdgeWithReadDep(const vector<Extent>& extents) {
400 EdgeProperties ret;
401 ret.extents = extents;
402 return ret;
403}
404
405EdgeProperties EdgeWithWriteDep(const vector<Extent>& extents) {
406 EdgeProperties ret;
407 ret.write_extents = extents;
408 return ret;
409}
410
411template<typename T>
412void 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
423TEST_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
adlr@google.com3defe6a2009-12-04 20:57:17 +0000558} // namespace chromeos_update_engine