Index: delta_diff_generator_unittest.cc |
diff --git a/delta_diff_generator_unittest.cc b/delta_diff_generator_unittest.cc |
index 11f77350552bb3896292e310bfc4d5f363f3b1ce..0d7b0fe20903fdd423642932c7c429128f672636 100644 |
--- a/delta_diff_generator_unittest.cc |
+++ b/delta_diff_generator_unittest.cc |
@@ -7,6 +7,7 @@ |
#include <fcntl.h> |
#include <unistd.h> |
#include <set> |
+#include <sstream> |
#include <string> |
#include <utility> |
#include <vector> |
@@ -15,15 +16,18 @@ |
#include "update_engine/cycle_breaker.h" |
#include "update_engine/delta_diff_generator.h" |
#include "update_engine/delta_performer.h" |
+#include "update_engine/extent_ranges.h" |
#include "update_engine/graph_types.h" |
#include "update_engine/graph_utils.h" |
#include "update_engine/subprocess.h" |
#include "update_engine/test_utils.h" |
+#include "update_engine/topological_sort.h" |
#include "update_engine/utils.h" |
using std::make_pair; |
using std::set; |
using std::string; |
+using std::stringstream; |
using std::vector; |
namespace chromeos_update_engine { |
@@ -161,13 +165,14 @@ TEST_F(DeltaDiffGeneratorTest, SubstituteBlocksTest) { |
vector<Extent> replace_blocks; |
AppendExtent(&replace_blocks, 10, 2); |
AppendExtent(&replace_blocks, 13, 2); |
- DeltaArchiveManifest_InstallOperation op; |
+ Vertex vertex; |
+ DeltaArchiveManifest_InstallOperation& op = vertex.op; |
OpAppendExtent(&op, 4, 3); |
OpAppendExtent(&op, kSparseHole, 4); // Sparse hole in file |
OpAppendExtent(&op, 3, 1); |
OpAppendExtent(&op, 7, 3); |
- DeltaDiffGenerator::SubstituteBlocks(&op, remove_blocks, replace_blocks); |
+ DeltaDiffGenerator::SubstituteBlocks(&vertex, remove_blocks, replace_blocks); |
EXPECT_EQ(7, op.src_extents_size()); |
EXPECT_EQ(11, op.src_extents(0).start_block()); |
@@ -254,7 +259,8 @@ TEST_F(DeltaDiffGeneratorTest, CutEdgesTest) { |
EXPECT_TRUE(cut_edges.end() != cut_edges.find(make_pair<Vertex::Index>(1, |
0))); |
- EXPECT_TRUE(DeltaDiffGenerator::CutEdges(&graph, blocks, cut_edges)); |
+ vector<CutEdgeVertexes> cuts; |
+ EXPECT_TRUE(DeltaDiffGenerator::CutEdges(&graph, cut_edges, &cuts)); |
EXPECT_EQ(3, graph.size()); |
@@ -262,21 +268,17 @@ TEST_F(DeltaDiffGeneratorTest, CutEdgesTest) { |
EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_MOVE, |
graph.back().op.type()); |
EXPECT_EQ(2, graph.back().op.src_extents_size()); |
- EXPECT_EQ(2, graph.back().op.dst_extents_size()); |
- EXPECT_EQ(0, graph.back().op.dst_extents(0).start_block()); |
- EXPECT_EQ(1, graph.back().op.dst_extents(0).num_blocks()); |
- EXPECT_EQ(8, graph.back().op.dst_extents(1).start_block()); |
- EXPECT_EQ(1, graph.back().op.dst_extents(1).num_blocks()); |
+ EXPECT_EQ(1, graph.back().op.dst_extents_size()); |
+ EXPECT_EQ(kTempBlockStart, graph.back().op.dst_extents(0).start_block()); |
+ EXPECT_EQ(2, graph.back().op.dst_extents(0).num_blocks()); |
EXPECT_TRUE(graph.back().out_edges.empty()); |
// Check that old node reads from new blocks |
- EXPECT_EQ(3, graph[0].op.src_extents_size()); |
- EXPECT_EQ(0, graph[0].op.src_extents(0).start_block()); |
- EXPECT_EQ(1, graph[0].op.src_extents(0).num_blocks()); |
- EXPECT_EQ(8, graph[0].op.src_extents(1).start_block()); |
+ EXPECT_EQ(2, graph[0].op.src_extents_size()); |
+ EXPECT_EQ(kTempBlockStart, graph[0].op.src_extents(0).start_block()); |
+ EXPECT_EQ(2, graph[0].op.src_extents(0).num_blocks()); |
+ EXPECT_EQ(7, graph[0].op.src_extents(1).start_block()); |
EXPECT_EQ(1, graph[0].op.src_extents(1).num_blocks()); |
- EXPECT_EQ(7, graph[0].op.src_extents(2).start_block()); |
- EXPECT_EQ(1, graph[0].op.src_extents(2).num_blocks()); |
// And that the old dst extents haven't changed |
EXPECT_EQ(2, graph[0].op.dst_extents_size()); |
@@ -348,4 +350,209 @@ TEST_F(DeltaDiffGeneratorTest, ReorderBlobsTest) { |
unlink(new_blobs.c_str()); |
} |
+TEST_F(DeltaDiffGeneratorTest, MoveFullOpsToBackTest) { |
+ Graph graph(4); |
+ graph[0].file_name = "A"; |
+ graph[0].op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE); |
+ graph[1].file_name = "B"; |
+ graph[1].op.set_type(DeltaArchiveManifest_InstallOperation_Type_BSDIFF); |
+ graph[2].file_name = "C"; |
+ graph[2].op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); |
+ graph[3].file_name = "D"; |
+ graph[3].op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE); |
+ |
+ vector<Vertex::Index> vect(graph.size()); |
+ |
+ for (vector<Vertex::Index>::size_type i = 0; i < vect.size(); ++i) { |
+ vect[i] = i; |
+ } |
+ DeltaDiffGenerator::MoveFullOpsToBack(&graph, &vect); |
+ EXPECT_EQ(vect.size(), graph.size()); |
+ EXPECT_EQ(graph[vect[0]].file_name, "B"); |
+ EXPECT_EQ(graph[vect[1]].file_name, "D"); |
+ EXPECT_EQ(graph[vect[2]].file_name, "A"); |
+ EXPECT_EQ(graph[vect[3]].file_name, "C"); |
+} |
+ |
+namespace { |
+ |
+#define OP_BSDIFF DeltaArchiveManifest_InstallOperation_Type_BSDIFF |
+#define OP_MOVE DeltaArchiveManifest_InstallOperation_Type_MOVE |
+#define OP_REPLACE DeltaArchiveManifest_InstallOperation_Type_REPLACE |
+#define OP_REPLACE_BZ DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ |
+ |
+void GenVertex(Vertex* out, |
+ const vector<Extent>& src_extents, |
+ const vector<Extent>& dst_extents, |
+ const string& path, |
+ DeltaArchiveManifest_InstallOperation_Type type) { |
+ out->op.set_type(type); |
+ out->file_name = path; |
+ DeltaDiffGenerator::StoreExtents(src_extents, out->op.mutable_src_extents()); |
+ DeltaDiffGenerator::StoreExtents(dst_extents, out->op.mutable_dst_extents()); |
+} |
+ |
+vector<Extent> VectOfExt(uint64_t start_block, uint64_t num_blocks) { |
+ return vector<Extent>(1, ExtentForRange(start_block, num_blocks)); |
+} |
+ |
+EdgeProperties EdgeWithReadDep(const vector<Extent>& extents) { |
+ EdgeProperties ret; |
+ ret.extents = extents; |
+ return ret; |
+} |
+ |
+EdgeProperties EdgeWithWriteDep(const vector<Extent>& extents) { |
+ EdgeProperties ret; |
+ ret.write_extents = extents; |
+ return ret; |
+} |
+ |
+template<typename T> |
+void DumpVect(const vector<T>& vect) { |
+ std::stringstream ss(stringstream::out); |
+ for (typename vector<T>::const_iterator it = vect.begin(), e = vect.end(); |
+ it != e; ++it) { |
+ ss << *it << ", "; |
+ } |
+ LOG(INFO) << "{" << ss.str() << "}"; |
+} |
+ |
+} // namespace {} |
+ |
+TEST_F(DeltaDiffGeneratorTest, RunAsRootAssignTempBlocksTest) { |
+ Graph graph(9); |
+ const vector<Extent> empt; // empty |
+ const string kFilename = "/foo"; |
+ |
+ // Some scratch space: |
+ GenVertex(&graph[0], empt, VectOfExt(200, 1), "", OP_REPLACE); |
+ GenVertex(&graph[1], empt, VectOfExt(210, 10), "", OP_REPLACE); |
+ GenVertex(&graph[2], empt, VectOfExt(220, 1), "", OP_REPLACE); |
+ |
+ // A cycle that requires 10 blocks to break: |
+ GenVertex(&graph[3], VectOfExt(10, 11), VectOfExt(0, 9), "", OP_BSDIFF); |
+ graph[3].out_edges[4] = EdgeWithReadDep(VectOfExt(0, 9)); |
+ GenVertex(&graph[4], VectOfExt(0, 9), VectOfExt(10, 11), "", OP_BSDIFF); |
+ graph[4].out_edges[3] = EdgeWithReadDep(VectOfExt(10, 11)); |
+ |
+ // A cycle that requires 9 blocks to break: |
+ GenVertex(&graph[5], VectOfExt(40, 11), VectOfExt(30, 10), "", OP_BSDIFF); |
+ graph[5].out_edges[6] = EdgeWithReadDep(VectOfExt(30, 10)); |
+ GenVertex(&graph[6], VectOfExt(30, 10), VectOfExt(40, 11), "", OP_BSDIFF); |
+ graph[6].out_edges[5] = EdgeWithReadDep(VectOfExt(40, 11)); |
+ |
+ // A cycle that requires 40 blocks to break (which is too many): |
+ GenVertex(&graph[7], |
+ VectOfExt(120, 50), |
+ VectOfExt(60, 40), |
+ "", |
+ OP_BSDIFF); |
+ graph[7].out_edges[8] = EdgeWithReadDep(VectOfExt(60, 40)); |
+ GenVertex(&graph[8], |
+ VectOfExt(60, 40), |
+ VectOfExt(120, 50), |
+ kFilename, |
+ OP_BSDIFF); |
+ graph[8].out_edges[7] = EdgeWithReadDep(VectOfExt(120, 50)); |
+ |
+ graph_utils::DumpGraph(graph); |
+ |
+ vector<Vertex::Index> final_order; |
+ |
+ |
+ // Prepare the filesystem with the minimum required for this to work |
+ string temp_dir; |
+ EXPECT_TRUE(utils::MakeTempDirectory("/tmp/AssignTempBlocksTest.XXXXXX", |
+ &temp_dir)); |
+ ScopedDirRemover temp_dir_remover(temp_dir); |
+ |
+ const size_t kBlockSize = 4096; |
+ vector<char> temp_data(kBlockSize * 50); |
+ FillWithData(&temp_data); |
+ EXPECT_TRUE(WriteFileVector(temp_dir + kFilename, temp_data)); |
+ ScopedPathUnlinker filename_unlinker(temp_dir + kFilename); |
+ |
+ int fd; |
+ EXPECT_TRUE(utils::MakeTempFile("/tmp/AssignTempBlocksTestData.XXXXXX", |
+ NULL, |
+ &fd)); |
+ ScopedFdCloser fd_closer(&fd); |
+ off_t data_file_size = 0; |
+ |
+ |
+ EXPECT_TRUE(DeltaDiffGenerator::ConvertGraphToDag(&graph, |
+ temp_dir, |
+ fd, |
+ &data_file_size, |
+ &final_order)); |
+ |
+ |
+ Graph expected_graph(12); |
+ GenVertex(&expected_graph[0], empt, VectOfExt(200, 1), "", OP_REPLACE); |
+ GenVertex(&expected_graph[1], empt, VectOfExt(210, 10), "", OP_REPLACE); |
+ GenVertex(&expected_graph[2], empt, VectOfExt(220, 1), "", OP_REPLACE); |
+ GenVertex(&expected_graph[3], |
+ VectOfExt(10, 11), |
+ VectOfExt(0, 9), |
+ "", |
+ OP_BSDIFF); |
+ expected_graph[3].out_edges[9] = EdgeWithReadDep(VectOfExt(0, 9)); |
+ GenVertex(&expected_graph[4], |
+ VectOfExt(60, 9), |
+ VectOfExt(10, 11), |
+ "", |
+ OP_BSDIFF); |
+ expected_graph[4].out_edges[3] = EdgeWithReadDep(VectOfExt(10, 11)); |
+ expected_graph[4].out_edges[9] = EdgeWithWriteDep(VectOfExt(60, 9)); |
+ GenVertex(&expected_graph[5], |
+ VectOfExt(40, 11), |
+ VectOfExt(30, 10), |
+ "", |
+ OP_BSDIFF); |
+ expected_graph[5].out_edges[10] = EdgeWithReadDep(VectOfExt(30, 10)); |
+ |
+ GenVertex(&expected_graph[6], |
+ VectOfExt(60, 10), |
+ VectOfExt(40, 11), |
+ "", |
+ OP_BSDIFF); |
+ expected_graph[6].out_edges[5] = EdgeWithReadDep(VectOfExt(40, 11)); |
+ expected_graph[6].out_edges[10] = EdgeWithWriteDep(VectOfExt(60, 10)); |
+ |
+ GenVertex(&expected_graph[7], |
+ VectOfExt(120, 50), |
+ VectOfExt(60, 40), |
+ "", |
+ OP_BSDIFF); |
+ expected_graph[7].out_edges[6] = EdgeWithReadDep(VectOfExt(60, 10)); |
+ |
+ GenVertex(&expected_graph[8], empt, VectOfExt(0, 50), "/foo", OP_REPLACE_BZ); |
+ expected_graph[8].out_edges[7] = EdgeWithReadDep(VectOfExt(120, 50)); |
+ |
+ GenVertex(&expected_graph[9], |
+ VectOfExt(0, 9), |
+ VectOfExt(60, 9), |
+ "", |
+ OP_MOVE); |
+ |
+ GenVertex(&expected_graph[10], |
+ VectOfExt(30, 10), |
+ VectOfExt(60, 10), |
+ "", |
+ OP_MOVE); |
+ expected_graph[10].out_edges[4] = EdgeWithReadDep(VectOfExt(60, 9)); |
+ |
+ EXPECT_EQ(12, graph.size()); |
+ EXPECT_FALSE(graph.back().valid); |
+ for (Graph::size_type i = 0; i < graph.size() - 1; i++) { |
+ EXPECT_TRUE(graph[i].out_edges == expected_graph[i].out_edges); |
+ if (i == 8) { |
+ // special case |
+ } else { |
+ // EXPECT_TRUE(graph[i] == expected_graph[i]) << "i = " << i; |
+ } |
+ } |
+} |
+ |
} // namespace chromeos_update_engine |