update_engine: Add fds for the source partitions.
Add new fds for the source partition, one for the rootfs and another for
the kernel. These are opened if we have a delta update with minor
version 2.
This change also adds support for changing the minor versions in tests.
There is a new private member, supported_minor_version_, which defaults
to kSupportedMinorPayloadVersion. It is set in the unit tests with calls
to SetSupportedVersion.
BUG=chromium:463573
TEST=`FEATURES=test emerge-link update_engine`
Change-Id: Ib988c91eb450b2499c615ae65b271691dfd9c651
Reviewed-on: https://chromium-review.googlesource.com/260950
Trybot-Ready: Allie Wood <alliewood@chromium.org>
Tested-by: Allie Wood <alliewood@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Allie Wood <alliewood@chromium.org>
diff --git a/delta_performer_unittest.cc b/delta_performer_unittest.cc
index 5109fa0..fc2ac7e 100644
--- a/delta_performer_unittest.cc
+++ b/delta_performer_unittest.cc
@@ -107,8 +107,37 @@
kValidOperationData,
};
+// Chuck size used for full payloads during test.
+size_t kDefaultFullChunkSize = 1024 * 1024;
+
} // namespace
+class DeltaPerformerTest : public ::testing::Test {
+ public:
+ // Test helper placed where it can easily be friended from DeltaPerformer.
+ static void RunManifestValidation(const DeltaArchiveManifest& manifest,
+ bool full_payload,
+ ErrorCode expected) {
+ MockPrefs prefs;
+ InstallPlan install_plan;
+ FakeSystemState fake_system_state;
+ DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
+
+ // The install plan is for Full or Delta.
+ install_plan.is_full_update = full_payload;
+
+ // The Manifest we are validating.
+ performer.manifest_.CopyFrom(manifest);
+
+ EXPECT_EQ(expected, performer.ValidateManifest());
+ }
+
+ static void SetSupportedVersion(DeltaPerformer* performer,
+ uint64_t minor_version) {
+ performer->supported_minor_version_ = minor_version;
+ }
+};
+
static void CompareFilesByBlock(const string& a_file, const string& b_file) {
chromeos::Blob a_data, b_data;
EXPECT_TRUE(utils::ReadFile(a_file, &a_data)) << "file failed: " << a_file;
@@ -281,7 +310,8 @@
bool noop,
off_t chunk_size,
SignatureTest signature_test,
- DeltaState *state) {
+ DeltaState *state,
+ uint32_t minor_version) {
EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
test_utils::CreateExtImageAtPath(state->a_img, nullptr);
@@ -474,6 +504,7 @@
payload_config.is_delta = !full_rootfs;
payload_config.chunk_size = chunk_size;
payload_config.rootfs_partition_size = kRootFSPartitionSize;
+ payload_config.minor_version = minor_version;
if (!full_rootfs) {
payload_config.source.rootfs_part = state->a_img;
payload_config.source.rootfs_mountpt = a_mnt;
@@ -482,10 +513,9 @@
payload_config.source.image_info = old_image_info;
EXPECT_TRUE(payload_config.source.LoadImageSize());
- payload_config.minor_version =
- DeltaPerformer::kSupportedMinorPayloadVersion;
} else {
- payload_config.minor_version = DeltaPerformer::kFullPayloadMinorVersion;
+ if (payload_config.chunk_size == -1)
+ payload_config.chunk_size = kDefaultFullChunkSize;
}
payload_config.target.rootfs_part = state->b_img;
payload_config.target.rootfs_mountpt = b_mnt;
@@ -538,7 +568,8 @@
SignatureTest signature_test, DeltaState* state,
bool hash_checks_mandatory,
OperationHashTest op_hash_test,
- DeltaPerformer** performer) {
+ DeltaPerformer** performer,
+ uint32_t minor_version) {
// Check the metadata.
{
DeltaArchiveManifest manifest;
@@ -665,6 +696,8 @@
install_plan.hash_checks_mandatory = hash_checks_mandatory;
install_plan.metadata_size = state->metadata_size;
install_plan.is_full_update = full_kernel && full_rootfs;
+ install_plan.source_path = state->a_img.c_str();
+ install_plan.kernel_source_path = state->old_kernel.c_str();
LOG(INFO) << "Setting payload metadata size in Omaha = "
<< state->metadata_size;
@@ -680,6 +713,7 @@
&install_plan);
EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
(*performer)->set_public_key_path(kUnittestPublicKeyPath);
+ DeltaPerformerTest::SetSupportedVersion(*performer, minor_version);
EXPECT_EQ(state->image_size,
OmahaHashCalculator::RawHashOfFile(state->a_img,
@@ -713,6 +747,12 @@
break;
}
+ // For now, source operations are not implemented, so we expect an error.
+ if (minor_version == kSourceMinorPayloadVersion) {
+ expected_error = ErrorCode::kDownloadOperationExecutionError;
+ continue_writing = false;
+ }
+
// Write at some number of bytes per operation. Arbitrarily chose 5.
const size_t kBytesPerWrite = 5;
for (size_t i = 0; i < state->delta.size(); i += kBytesPerWrite) {
@@ -823,11 +863,11 @@
void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop,
off_t chunk_size,
SignatureTest signature_test,
- bool hash_checks_mandatory) {
+ bool hash_checks_mandatory, uint32_t minor_version) {
DeltaState state;
DeltaPerformer *performer = nullptr;
GenerateDeltaFile(full_kernel, full_rootfs, noop, chunk_size,
- signature_test, &state);
+ signature_test, &state, minor_version);
ScopedPathUnlinker a_img_unlinker(state.a_img);
ScopedPathUnlinker b_img_unlinker(state.b_img);
@@ -836,7 +876,7 @@
ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
ApplyDeltaFile(full_kernel, full_rootfs, noop, signature_test,
&state, hash_checks_mandatory, kValidOperationData,
- &performer);
+ &performer, minor_version);
VerifyPayload(performer, &state, signature_test);
delete performer;
}
@@ -889,7 +929,8 @@
// Using kSignatureNone since it doesn't affect the results of our test.
// If we've to use other signature options, then we'd have to get the
// metadata size again after adding the signing operation to the manifest.
- GenerateDeltaFile(true, true, false, -1, signature_test, &state);
+ GenerateDeltaFile(true, true, false, -1, signature_test, &state,
+ DeltaPerformer::kFullPayloadMinorVersion);
ScopedPathUnlinker a_img_unlinker(state.a_img);
ScopedPathUnlinker b_img_unlinker(state.b_img);
@@ -972,40 +1013,21 @@
void DoOperationHashMismatchTest(OperationHashTest op_hash_test,
bool hash_checks_mandatory) {
DeltaState state;
- GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state);
+ uint64_t minor_version = DeltaPerformer::kFullPayloadMinorVersion;
+ GenerateDeltaFile(true, true, false, -1, kSignatureGenerated, &state,
+ minor_version);
ScopedPathUnlinker a_img_unlinker(state.a_img);
ScopedPathUnlinker b_img_unlinker(state.b_img);
ScopedPathUnlinker delta_unlinker(state.delta_path);
ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
DeltaPerformer *performer = nullptr;
- ApplyDeltaFile(true, true, false, kSignatureGenerated,
- &state, hash_checks_mandatory, op_hash_test, &performer);
+ ApplyDeltaFile(true, true, false, kSignatureGenerated, &state,
+ hash_checks_mandatory, op_hash_test, &performer,
+ minor_version);
delete performer;
}
-
-class DeltaPerformerTest : public ::testing::Test {
- public:
- // Test helper placed where it can easily be friended from DeltaPerformer.
- static void RunManifestValidation(const DeltaArchiveManifest& manifest,
- bool full_payload,
- ErrorCode expected) {
- MockPrefs prefs;
- InstallPlan install_plan;
- FakeSystemState fake_system_state;
- DeltaPerformer performer(&prefs, &fake_system_state, &install_plan);
-
- // The install plan is for Full or Delta.
- install_plan.is_full_update = full_payload;
-
- // The Manifest we are validating.
- performer.manifest_.CopyFrom(manifest);
-
- EXPECT_EQ(expected, performer.ValidateManifest());
- }
-};
-
TEST(DeltaPerformerTest, ExtentsToByteStringTest) {
uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1};
COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
@@ -1110,68 +1132,69 @@
TEST(DeltaPerformerTest, RunAsRootSmallImageTest) {
DoSmallImageTest(false, false, false, -1, kSignatureGenerator,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderTest) {
DoSmallImageTest(false, false, false, -1, kSignatureGeneratedPlaceholder,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignaturePlaceholderMismatchTest) {
DeltaState state;
GenerateDeltaFile(false, false, false, -1,
- kSignatureGeneratedPlaceholderMismatch, &state);
+ kSignatureGeneratedPlaceholderMismatch, &state,
+ kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageChunksTest) {
DoSmallImageTest(false, false, false, kBlockSize, kSignatureGenerator,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) {
DoSmallImageTest(true, false, false, -1, kSignatureGenerator,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) {
DoSmallImageTest(true, true, false, -1, kSignatureGenerator,
- true);
+ true, DeltaPerformer::kFullPayloadMinorVersion);
}
TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) {
DoSmallImageTest(false, false, true, -1, kSignatureGenerator,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignNoneTest) {
DoSmallImageTest(false, false, false, -1, kSignatureNone,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedTest) {
DoSmallImageTest(false, false, false, -1, kSignatureGenerated,
- true);
+ true, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellTest) {
DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShell,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellBadKey,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl1Test) {
DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl1,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, RunAsRootSmallImageSignGeneratedShellRotateCl2Test) {
DoSmallImageTest(false, false, false, -1, kSignatureGeneratedShellRotateCl2,
- false);
+ false, kInPlaceMinorPayloadVersion);
}
TEST(DeltaPerformerTest, BadDeltaMagicTest) {
@@ -1354,6 +1377,24 @@
EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
}
+TEST(DeltaPerformerTest, RunAsRootSourceOperationsTest) {
+ // Make sure we can generate a payload with the new source ops and minor
+ // version 2. For now, we expect ApplyDeltaFile to fail because the ops are
+ // not yet implemented, but eventually we can verify the resulting payload.
+ DeltaState state;
+ DeltaPerformer* performer = nullptr;
+ GenerateDeltaFile(false, false, false, -1, kSignatureNone, &state,
+ kSourceMinorPayloadVersion);
+ ScopedPathUnlinker a_img_unlinker(state.a_img);
+ ScopedPathUnlinker b_img_unlinker(state.b_img);
+ ScopedPathUnlinker delta_unlinker(state.delta_path);
+ ScopedPathUnlinker old_kernel_unlinker(state.old_kernel);
+ ScopedPathUnlinker new_kernel_unlinker(state.new_kernel);
+ ApplyDeltaFile(false, false, false, kSignatureNone, &state, false,
+ kValidOperationData, &performer, kSourceMinorPayloadVersion);
+ delete performer;
+}
+
TEST(DeltaPerformerTest, MinorVersionsMatch) {
// Test that the minor version in update_engine.conf that is installed to
// the image matches the supported delta minor version in the update engine.