ab_generator_unittest.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. //
  2. // Copyright (C) 2015 The Android Open Source Project
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "update_engine/payload_generator/ab_generator.h"
  17. #include <fcntl.h>
  18. #include <sys/stat.h>
  19. #include <sys/types.h>
  20. #include <random>
  21. #include <string>
  22. #include <vector>
  23. #include <gtest/gtest.h>
  24. #include "update_engine/common/hash_calculator.h"
  25. #include "update_engine/common/test_utils.h"
  26. #include "update_engine/common/utils.h"
  27. #include "update_engine/payload_generator/annotated_operation.h"
  28. #include "update_engine/payload_generator/bzip.h"
  29. #include "update_engine/payload_generator/delta_diff_generator.h"
  30. #include "update_engine/payload_generator/extent_ranges.h"
  31. #include "update_engine/payload_generator/extent_utils.h"
  32. using std::string;
  33. using std::vector;
  34. namespace chromeos_update_engine {
  35. namespace {
  36. bool ExtentEquals(const Extent& ext,
  37. uint64_t start_block,
  38. uint64_t num_blocks) {
  39. return ext.start_block() == start_block && ext.num_blocks() == num_blocks;
  40. }
  41. // Tests splitting of a REPLACE/REPLACE_BZ operation.
  42. void TestSplitReplaceOrReplaceBzOperation(InstallOperation::Type orig_type,
  43. bool compressible) {
  44. const size_t op_ex1_start_block = 2;
  45. const size_t op_ex1_num_blocks = 2;
  46. const size_t op_ex2_start_block = 6;
  47. const size_t op_ex2_num_blocks = 1;
  48. const size_t part_num_blocks = 7;
  49. // Create the target partition data.
  50. const size_t part_size = part_num_blocks * kBlockSize;
  51. brillo::Blob part_data;
  52. if (compressible) {
  53. part_data.resize(part_size);
  54. test_utils::FillWithData(&part_data);
  55. } else {
  56. std::mt19937 gen(12345);
  57. std::uniform_int_distribution<uint8_t> dis(0, 255);
  58. for (uint32_t i = 0; i < part_size; i++)
  59. part_data.push_back(dis(gen));
  60. }
  61. ASSERT_EQ(part_size, part_data.size());
  62. test_utils::ScopedTempFile part_file(
  63. "SplitReplaceOrReplaceBzTest_part.XXXXXX");
  64. ASSERT_TRUE(test_utils::WriteFileVector(part_file.path(), part_data));
  65. // Create original operation and blob data.
  66. const size_t op_ex1_offset = op_ex1_start_block * kBlockSize;
  67. const size_t op_ex1_size = op_ex1_num_blocks * kBlockSize;
  68. const size_t op_ex2_offset = op_ex2_start_block * kBlockSize;
  69. const size_t op_ex2_size = op_ex2_num_blocks * kBlockSize;
  70. InstallOperation op;
  71. op.set_type(orig_type);
  72. *(op.add_dst_extents()) =
  73. ExtentForRange(op_ex1_start_block, op_ex1_num_blocks);
  74. *(op.add_dst_extents()) =
  75. ExtentForRange(op_ex2_start_block, op_ex2_num_blocks);
  76. brillo::Blob op_data;
  77. op_data.insert(op_data.end(),
  78. part_data.begin() + op_ex1_offset,
  79. part_data.begin() + op_ex1_offset + op_ex1_size);
  80. op_data.insert(op_data.end(),
  81. part_data.begin() + op_ex2_offset,
  82. part_data.begin() + op_ex2_offset + op_ex2_size);
  83. brillo::Blob op_blob;
  84. if (orig_type == InstallOperation::REPLACE) {
  85. op_blob = op_data;
  86. } else {
  87. ASSERT_TRUE(BzipCompress(op_data, &op_blob));
  88. }
  89. op.set_data_offset(0);
  90. op.set_data_length(op_blob.size());
  91. AnnotatedOperation aop;
  92. aop.op = op;
  93. aop.name = "SplitTestOp";
  94. // Create the data file.
  95. test_utils::ScopedTempFile data_file(
  96. "SplitReplaceOrReplaceBzTest_data.XXXXXX");
  97. EXPECT_TRUE(test_utils::WriteFileVector(data_file.path(), op_blob));
  98. int data_fd = open(data_file.path().c_str(), O_RDWR, 000);
  99. EXPECT_GE(data_fd, 0);
  100. ScopedFdCloser data_fd_closer(&data_fd);
  101. off_t data_file_size = op_blob.size();
  102. BlobFileWriter blob_file(data_fd, &data_file_size);
  103. // Split the operation.
  104. vector<AnnotatedOperation> result_ops;
  105. PayloadVersion version(kChromeOSMajorPayloadVersion,
  106. kSourceMinorPayloadVersion);
  107. ASSERT_TRUE(ABGenerator::SplitAReplaceOp(
  108. version, aop, part_file.path(), &result_ops, &blob_file));
  109. // Check the result.
  110. InstallOperation::Type expected_type =
  111. compressible ? InstallOperation::REPLACE_BZ : InstallOperation::REPLACE;
  112. ASSERT_EQ(2U, result_ops.size());
  113. EXPECT_EQ("SplitTestOp:0", result_ops[0].name);
  114. InstallOperation first_op = result_ops[0].op;
  115. EXPECT_EQ(expected_type, first_op.type());
  116. EXPECT_FALSE(first_op.has_src_length());
  117. EXPECT_FALSE(first_op.has_dst_length());
  118. EXPECT_EQ(1, first_op.dst_extents().size());
  119. EXPECT_TRUE(ExtentEquals(
  120. first_op.dst_extents(0), op_ex1_start_block, op_ex1_num_blocks));
  121. // Obtain the expected blob.
  122. brillo::Blob first_expected_data(
  123. part_data.begin() + op_ex1_offset,
  124. part_data.begin() + op_ex1_offset + op_ex1_size);
  125. brillo::Blob first_expected_blob;
  126. if (compressible) {
  127. ASSERT_TRUE(BzipCompress(first_expected_data, &first_expected_blob));
  128. } else {
  129. first_expected_blob = first_expected_data;
  130. }
  131. EXPECT_EQ(first_expected_blob.size(), first_op.data_length());
  132. // Check that the actual blob matches what's expected.
  133. brillo::Blob first_data_blob(first_op.data_length());
  134. ssize_t bytes_read;
  135. ASSERT_TRUE(utils::PReadAll(data_fd,
  136. first_data_blob.data(),
  137. first_op.data_length(),
  138. first_op.data_offset(),
  139. &bytes_read));
  140. ASSERT_EQ(bytes_read, static_cast<ssize_t>(first_op.data_length()));
  141. EXPECT_EQ(first_expected_blob, first_data_blob);
  142. EXPECT_EQ("SplitTestOp:1", result_ops[1].name);
  143. InstallOperation second_op = result_ops[1].op;
  144. EXPECT_EQ(expected_type, second_op.type());
  145. EXPECT_FALSE(second_op.has_src_length());
  146. EXPECT_FALSE(second_op.has_dst_length());
  147. EXPECT_EQ(1, second_op.dst_extents().size());
  148. EXPECT_TRUE(ExtentEquals(
  149. second_op.dst_extents(0), op_ex2_start_block, op_ex2_num_blocks));
  150. // Obtain the expected blob.
  151. brillo::Blob second_expected_data(
  152. part_data.begin() + op_ex2_offset,
  153. part_data.begin() + op_ex2_offset + op_ex2_size);
  154. brillo::Blob second_expected_blob;
  155. if (compressible) {
  156. ASSERT_TRUE(BzipCompress(second_expected_data, &second_expected_blob));
  157. } else {
  158. second_expected_blob = second_expected_data;
  159. }
  160. EXPECT_EQ(second_expected_blob.size(), second_op.data_length());
  161. // Check that the actual blob matches what's expected.
  162. brillo::Blob second_data_blob(second_op.data_length());
  163. ASSERT_TRUE(utils::PReadAll(data_fd,
  164. second_data_blob.data(),
  165. second_op.data_length(),
  166. second_op.data_offset(),
  167. &bytes_read));
  168. ASSERT_EQ(bytes_read, static_cast<ssize_t>(second_op.data_length()));
  169. EXPECT_EQ(second_expected_blob, second_data_blob);
  170. // Check relative layout of data blobs.
  171. EXPECT_EQ(first_op.data_offset() + first_op.data_length(),
  172. second_op.data_offset());
  173. EXPECT_EQ(second_op.data_offset() + second_op.data_length(),
  174. static_cast<uint64_t>(data_file_size));
  175. // If we split a REPLACE into multiple ones, ensure reuse of preexisting blob.
  176. if (!compressible && orig_type == InstallOperation::REPLACE) {
  177. EXPECT_EQ(0U, first_op.data_offset());
  178. }
  179. }
  180. // Tests merging of REPLACE/REPLACE_BZ operations.
  181. void TestMergeReplaceOrReplaceBzOperations(InstallOperation::Type orig_type,
  182. bool compressible) {
  183. const size_t first_op_num_blocks = 1;
  184. const size_t second_op_num_blocks = 2;
  185. const size_t total_op_num_blocks = first_op_num_blocks + second_op_num_blocks;
  186. const size_t part_num_blocks = total_op_num_blocks + 2;
  187. // Create the target partition data.
  188. const size_t part_size = part_num_blocks * kBlockSize;
  189. brillo::Blob part_data;
  190. if (compressible) {
  191. part_data.resize(part_size);
  192. test_utils::FillWithData(&part_data);
  193. } else {
  194. std::mt19937 gen(12345);
  195. std::uniform_int_distribution<uint8_t> dis(0, 255);
  196. for (uint32_t i = 0; i < part_size; i++)
  197. part_data.push_back(dis(gen));
  198. }
  199. ASSERT_EQ(part_size, part_data.size());
  200. test_utils::ScopedTempFile part_file(
  201. "MergeReplaceOrReplaceBzTest_part.XXXXXX");
  202. ASSERT_TRUE(test_utils::WriteFileVector(part_file.path(), part_data));
  203. // Create original operations and blob data.
  204. vector<AnnotatedOperation> aops;
  205. brillo::Blob blob_data;
  206. const size_t total_op_size = total_op_num_blocks * kBlockSize;
  207. InstallOperation first_op;
  208. first_op.set_type(orig_type);
  209. const size_t first_op_size = first_op_num_blocks * kBlockSize;
  210. *(first_op.add_dst_extents()) = ExtentForRange(0, first_op_num_blocks);
  211. brillo::Blob first_op_data(part_data.begin(),
  212. part_data.begin() + first_op_size);
  213. brillo::Blob first_op_blob;
  214. if (orig_type == InstallOperation::REPLACE) {
  215. first_op_blob = first_op_data;
  216. } else {
  217. ASSERT_TRUE(BzipCompress(first_op_data, &first_op_blob));
  218. }
  219. first_op.set_data_offset(0);
  220. first_op.set_data_length(first_op_blob.size());
  221. blob_data.insert(blob_data.end(), first_op_blob.begin(), first_op_blob.end());
  222. AnnotatedOperation first_aop;
  223. first_aop.op = first_op;
  224. first_aop.name = "first";
  225. aops.push_back(first_aop);
  226. InstallOperation second_op;
  227. second_op.set_type(orig_type);
  228. *(second_op.add_dst_extents()) =
  229. ExtentForRange(first_op_num_blocks, second_op_num_blocks);
  230. brillo::Blob second_op_data(part_data.begin() + first_op_size,
  231. part_data.begin() + total_op_size);
  232. brillo::Blob second_op_blob;
  233. if (orig_type == InstallOperation::REPLACE) {
  234. second_op_blob = second_op_data;
  235. } else {
  236. ASSERT_TRUE(BzipCompress(second_op_data, &second_op_blob));
  237. }
  238. second_op.set_data_offset(first_op_blob.size());
  239. second_op.set_data_length(second_op_blob.size());
  240. blob_data.insert(
  241. blob_data.end(), second_op_blob.begin(), second_op_blob.end());
  242. AnnotatedOperation second_aop;
  243. second_aop.op = second_op;
  244. second_aop.name = "second";
  245. aops.push_back(second_aop);
  246. // Create the data file.
  247. test_utils::ScopedTempFile data_file(
  248. "MergeReplaceOrReplaceBzTest_data.XXXXXX");
  249. EXPECT_TRUE(test_utils::WriteFileVector(data_file.path(), blob_data));
  250. int data_fd = open(data_file.path().c_str(), O_RDWR, 000);
  251. EXPECT_GE(data_fd, 0);
  252. ScopedFdCloser data_fd_closer(&data_fd);
  253. off_t data_file_size = blob_data.size();
  254. BlobFileWriter blob_file(data_fd, &data_file_size);
  255. // Merge the operations.
  256. PayloadVersion version(kChromeOSMajorPayloadVersion,
  257. kSourceMinorPayloadVersion);
  258. EXPECT_TRUE(ABGenerator::MergeOperations(
  259. &aops, version, 5, part_file.path(), &blob_file));
  260. // Check the result.
  261. InstallOperation::Type expected_op_type =
  262. compressible ? InstallOperation::REPLACE_BZ : InstallOperation::REPLACE;
  263. EXPECT_EQ(1U, aops.size());
  264. InstallOperation new_op = aops[0].op;
  265. EXPECT_EQ(expected_op_type, new_op.type());
  266. EXPECT_FALSE(new_op.has_src_length());
  267. EXPECT_FALSE(new_op.has_dst_length());
  268. EXPECT_EQ(1, new_op.dst_extents().size());
  269. EXPECT_TRUE(ExtentEquals(new_op.dst_extents(0), 0, total_op_num_blocks));
  270. EXPECT_EQ("first,second", aops[0].name);
  271. // Check to see if the blob pointed to in the new extent has what we expect.
  272. brillo::Blob expected_data(part_data.begin(),
  273. part_data.begin() + total_op_size);
  274. brillo::Blob expected_blob;
  275. if (compressible) {
  276. ASSERT_TRUE(BzipCompress(expected_data, &expected_blob));
  277. } else {
  278. expected_blob = expected_data;
  279. }
  280. ASSERT_EQ(expected_blob.size(), new_op.data_length());
  281. ASSERT_EQ(blob_data.size() + expected_blob.size(),
  282. static_cast<size_t>(data_file_size));
  283. brillo::Blob new_op_blob(new_op.data_length());
  284. ssize_t bytes_read;
  285. ASSERT_TRUE(utils::PReadAll(data_fd,
  286. new_op_blob.data(),
  287. new_op.data_length(),
  288. new_op.data_offset(),
  289. &bytes_read));
  290. ASSERT_EQ(static_cast<ssize_t>(new_op.data_length()), bytes_read);
  291. EXPECT_EQ(expected_blob, new_op_blob);
  292. }
  293. } // namespace
  294. class ABGeneratorTest : public ::testing::Test {};
  295. TEST_F(ABGeneratorTest, SplitSourceCopyTest) {
  296. InstallOperation op;
  297. op.set_type(InstallOperation::SOURCE_COPY);
  298. *(op.add_src_extents()) = ExtentForRange(2, 3);
  299. *(op.add_src_extents()) = ExtentForRange(6, 1);
  300. *(op.add_src_extents()) = ExtentForRange(8, 4);
  301. *(op.add_dst_extents()) = ExtentForRange(10, 2);
  302. *(op.add_dst_extents()) = ExtentForRange(14, 3);
  303. *(op.add_dst_extents()) = ExtentForRange(18, 3);
  304. AnnotatedOperation aop;
  305. aop.op = op;
  306. aop.name = "SplitSourceCopyTestOp";
  307. vector<AnnotatedOperation> result_ops;
  308. EXPECT_TRUE(ABGenerator::SplitSourceCopy(aop, &result_ops));
  309. EXPECT_EQ(3U, result_ops.size());
  310. EXPECT_EQ("SplitSourceCopyTestOp:0", result_ops[0].name);
  311. InstallOperation first_op = result_ops[0].op;
  312. EXPECT_EQ(InstallOperation::SOURCE_COPY, first_op.type());
  313. EXPECT_FALSE(first_op.has_src_length());
  314. EXPECT_EQ(1, first_op.src_extents().size());
  315. EXPECT_EQ(2U, first_op.src_extents(0).start_block());
  316. EXPECT_EQ(2U, first_op.src_extents(0).num_blocks());
  317. EXPECT_FALSE(first_op.has_dst_length());
  318. EXPECT_EQ(1, first_op.dst_extents().size());
  319. EXPECT_EQ(10U, first_op.dst_extents(0).start_block());
  320. EXPECT_EQ(2U, first_op.dst_extents(0).num_blocks());
  321. EXPECT_EQ("SplitSourceCopyTestOp:1", result_ops[1].name);
  322. InstallOperation second_op = result_ops[1].op;
  323. EXPECT_EQ(InstallOperation::SOURCE_COPY, second_op.type());
  324. EXPECT_FALSE(second_op.has_src_length());
  325. EXPECT_EQ(3, second_op.src_extents().size());
  326. EXPECT_EQ(4U, second_op.src_extents(0).start_block());
  327. EXPECT_EQ(1U, second_op.src_extents(0).num_blocks());
  328. EXPECT_EQ(6U, second_op.src_extents(1).start_block());
  329. EXPECT_EQ(1U, second_op.src_extents(1).num_blocks());
  330. EXPECT_EQ(8U, second_op.src_extents(2).start_block());
  331. EXPECT_EQ(1U, second_op.src_extents(2).num_blocks());
  332. EXPECT_FALSE(second_op.has_dst_length());
  333. EXPECT_EQ(1, second_op.dst_extents().size());
  334. EXPECT_EQ(14U, second_op.dst_extents(0).start_block());
  335. EXPECT_EQ(3U, second_op.dst_extents(0).num_blocks());
  336. EXPECT_EQ("SplitSourceCopyTestOp:2", result_ops[2].name);
  337. InstallOperation third_op = result_ops[2].op;
  338. EXPECT_EQ(InstallOperation::SOURCE_COPY, third_op.type());
  339. EXPECT_FALSE(third_op.has_src_length());
  340. EXPECT_EQ(1, third_op.src_extents().size());
  341. EXPECT_EQ(9U, third_op.src_extents(0).start_block());
  342. EXPECT_EQ(3U, third_op.src_extents(0).num_blocks());
  343. EXPECT_FALSE(third_op.has_dst_length());
  344. EXPECT_EQ(1, third_op.dst_extents().size());
  345. EXPECT_EQ(18U, third_op.dst_extents(0).start_block());
  346. EXPECT_EQ(3U, third_op.dst_extents(0).num_blocks());
  347. }
  348. TEST_F(ABGeneratorTest, SplitReplaceTest) {
  349. TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, false);
  350. }
  351. TEST_F(ABGeneratorTest, SplitReplaceIntoReplaceBzTest) {
  352. TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, true);
  353. }
  354. TEST_F(ABGeneratorTest, SplitReplaceBzTest) {
  355. TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, true);
  356. }
  357. TEST_F(ABGeneratorTest, SplitReplaceBzIntoReplaceTest) {
  358. TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, false);
  359. }
  360. TEST_F(ABGeneratorTest, SortOperationsByDestinationTest) {
  361. vector<AnnotatedOperation> aops;
  362. // One operation with multiple destination extents.
  363. InstallOperation first_op;
  364. *(first_op.add_dst_extents()) = ExtentForRange(6, 1);
  365. *(first_op.add_dst_extents()) = ExtentForRange(10, 2);
  366. AnnotatedOperation first_aop;
  367. first_aop.op = first_op;
  368. first_aop.name = "first";
  369. aops.push_back(first_aop);
  370. // One with no destination extent. Should end up at the end of the vector.
  371. InstallOperation second_op;
  372. AnnotatedOperation second_aop;
  373. second_aop.op = second_op;
  374. second_aop.name = "second";
  375. aops.push_back(second_aop);
  376. // One with one destination extent.
  377. InstallOperation third_op;
  378. *(third_op.add_dst_extents()) = ExtentForRange(3, 2);
  379. AnnotatedOperation third_aop;
  380. third_aop.op = third_op;
  381. third_aop.name = "third";
  382. aops.push_back(third_aop);
  383. ABGenerator::SortOperationsByDestination(&aops);
  384. EXPECT_EQ(3U, aops.size());
  385. EXPECT_EQ(third_aop.name, aops[0].name);
  386. EXPECT_EQ(first_aop.name, aops[1].name);
  387. EXPECT_EQ(second_aop.name, aops[2].name);
  388. }
  389. TEST_F(ABGeneratorTest, MergeSourceCopyOperationsTest) {
  390. vector<AnnotatedOperation> aops;
  391. InstallOperation first_op;
  392. first_op.set_type(InstallOperation::SOURCE_COPY);
  393. *(first_op.add_src_extents()) = ExtentForRange(1, 1);
  394. *(first_op.add_dst_extents()) = ExtentForRange(6, 1);
  395. AnnotatedOperation first_aop;
  396. first_aop.op = first_op;
  397. first_aop.name = "1";
  398. aops.push_back(first_aop);
  399. InstallOperation second_op;
  400. second_op.set_type(InstallOperation::SOURCE_COPY);
  401. *(second_op.add_src_extents()) = ExtentForRange(2, 2);
  402. *(second_op.add_src_extents()) = ExtentForRange(8, 2);
  403. *(second_op.add_dst_extents()) = ExtentForRange(7, 3);
  404. *(second_op.add_dst_extents()) = ExtentForRange(11, 1);
  405. AnnotatedOperation second_aop;
  406. second_aop.op = second_op;
  407. second_aop.name = "2";
  408. aops.push_back(second_aop);
  409. InstallOperation third_op;
  410. third_op.set_type(InstallOperation::SOURCE_COPY);
  411. *(third_op.add_src_extents()) = ExtentForRange(11, 1);
  412. *(third_op.add_dst_extents()) = ExtentForRange(12, 1);
  413. AnnotatedOperation third_aop;
  414. third_aop.op = third_op;
  415. third_aop.name = "3";
  416. aops.push_back(third_aop);
  417. BlobFileWriter blob_file(0, nullptr);
  418. PayloadVersion version(kChromeOSMajorPayloadVersion,
  419. kSourceMinorPayloadVersion);
  420. EXPECT_TRUE(ABGenerator::MergeOperations(&aops, version, 5, "", &blob_file));
  421. EXPECT_EQ(1U, aops.size());
  422. InstallOperation first_result_op = aops[0].op;
  423. EXPECT_EQ(InstallOperation::SOURCE_COPY, first_result_op.type());
  424. EXPECT_FALSE(first_result_op.has_src_length());
  425. EXPECT_EQ(3, first_result_op.src_extents().size());
  426. EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(0), 1, 3));
  427. EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(1), 8, 2));
  428. EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(2), 11, 1));
  429. EXPECT_FALSE(first_result_op.has_dst_length());
  430. EXPECT_EQ(2, first_result_op.dst_extents().size());
  431. EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(0), 6, 4));
  432. EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(1), 11, 2));
  433. EXPECT_EQ(aops[0].name, "1,2,3");
  434. }
  435. TEST_F(ABGeneratorTest, MergeReplaceOperationsTest) {
  436. TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE, false);
  437. }
  438. TEST_F(ABGeneratorTest, MergeReplaceOperationsToReplaceBzTest) {
  439. TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE, true);
  440. }
  441. TEST_F(ABGeneratorTest, MergeReplaceBzOperationsTest) {
  442. TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, true);
  443. }
  444. TEST_F(ABGeneratorTest, MergeReplaceBzOperationsToReplaceTest) {
  445. TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, false);
  446. }
  447. TEST_F(ABGeneratorTest, NoMergeOperationsTest) {
  448. // Test to make sure we don't merge operations that shouldn't be merged.
  449. vector<AnnotatedOperation> aops;
  450. InstallOperation first_op;
  451. first_op.set_type(InstallOperation::ZERO);
  452. *(first_op.add_dst_extents()) = ExtentForRange(0, 1);
  453. AnnotatedOperation first_aop;
  454. first_aop.op = first_op;
  455. aops.push_back(first_aop);
  456. // Should merge with first, except op types don't match...
  457. InstallOperation second_op;
  458. second_op.set_type(InstallOperation::REPLACE);
  459. *(second_op.add_dst_extents()) = ExtentForRange(1, 2);
  460. second_op.set_data_length(2 * kBlockSize);
  461. AnnotatedOperation second_aop;
  462. second_aop.op = second_op;
  463. aops.push_back(second_aop);
  464. // Should merge with second, except it would exceed chunk size...
  465. InstallOperation third_op;
  466. third_op.set_type(InstallOperation::REPLACE);
  467. *(third_op.add_dst_extents()) = ExtentForRange(3, 3);
  468. third_op.set_data_length(3 * kBlockSize);
  469. AnnotatedOperation third_aop;
  470. third_aop.op = third_op;
  471. aops.push_back(third_aop);
  472. // Should merge with third, except they aren't contiguous...
  473. InstallOperation fourth_op;
  474. fourth_op.set_type(InstallOperation::REPLACE);
  475. *(fourth_op.add_dst_extents()) = ExtentForRange(7, 2);
  476. fourth_op.set_data_length(2 * kBlockSize);
  477. AnnotatedOperation fourth_aop;
  478. fourth_aop.op = fourth_op;
  479. aops.push_back(fourth_aop);
  480. BlobFileWriter blob_file(0, nullptr);
  481. PayloadVersion version(kChromeOSMajorPayloadVersion,
  482. kSourceMinorPayloadVersion);
  483. EXPECT_TRUE(ABGenerator::MergeOperations(&aops, version, 4, "", &blob_file));
  484. // No operations were merged, the number of ops is the same.
  485. EXPECT_EQ(4U, aops.size());
  486. }
  487. TEST_F(ABGeneratorTest, AddSourceHashTest) {
  488. vector<AnnotatedOperation> aops;
  489. InstallOperation first_op;
  490. first_op.set_type(InstallOperation::SOURCE_COPY);
  491. first_op.set_src_length(kBlockSize);
  492. *(first_op.add_src_extents()) = ExtentForRange(0, 1);
  493. AnnotatedOperation first_aop;
  494. first_aop.op = first_op;
  495. aops.push_back(first_aop);
  496. InstallOperation second_op;
  497. second_op.set_type(InstallOperation::REPLACE);
  498. AnnotatedOperation second_aop;
  499. second_aop.op = second_op;
  500. aops.push_back(second_aop);
  501. test_utils::ScopedTempFile src_part_file("AddSourceHashTest_src_part.XXXXXX");
  502. brillo::Blob src_data(kBlockSize);
  503. test_utils::FillWithData(&src_data);
  504. ASSERT_TRUE(test_utils::WriteFileVector(src_part_file.path(), src_data));
  505. EXPECT_TRUE(ABGenerator::AddSourceHash(&aops, src_part_file.path()));
  506. EXPECT_TRUE(aops[0].op.has_src_sha256_hash());
  507. EXPECT_FALSE(aops[1].op.has_src_sha256_hash());
  508. brillo::Blob expected_hash;
  509. EXPECT_TRUE(HashCalculator::RawHashOfData(src_data, &expected_hash));
  510. brillo::Blob result_hash(aops[0].op.src_sha256_hash().begin(),
  511. aops[0].op.src_sha256_hash().end());
  512. EXPECT_EQ(expected_hash, result_hash);
  513. }
  514. } // namespace chromeos_update_engine