summaryrefslogtreecommitdiff
path: root/payload_consumer/postinstall_runner_action_unittest.cc
diff options
context:
space:
mode:
authorAlex Deymo <deymo@google.com>2016-03-30 18:31:49 -0700
committerAlex Deymo <deymo@google.com>2016-04-04 19:17:27 -0700
commit0d29854cf5bb05a22cf161b50052539aa420a36e (patch)
tree323b0577ca6767d0e39fec74067bb2f32d5d1ea1 /payload_consumer/postinstall_runner_action_unittest.cc
parente384bb2e403b0f0f666e89d5f6acfaec41120cc5 (diff)
Parse postinstall program progress updates.
In Android postinstall is expected to take a long time in common cases. This patch allows the postinstall program to report back to the updater a progress indication, which will then be forwarded to all the clients listening. These progress updates are part of the FINALIZING status. Bug: 27880754 TEST=Added unittests. Deployed an update to an edison-eng and post-install reported progress back with the postinstall_example. Change-Id: I35f96b92f090219c54cca48d8ab07c54cf8b4ab1
Diffstat (limited to 'payload_consumer/postinstall_runner_action_unittest.cc')
-rw-r--r--payload_consumer/postinstall_runner_action_unittest.cc92
1 files changed, 73 insertions, 19 deletions
diff --git a/payload_consumer/postinstall_runner_action_unittest.cc b/payload_consumer/postinstall_runner_action_unittest.cc
index 7d300eb6..3e7d87a8 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -32,6 +32,7 @@
#include <brillo/bind_lambda.h>
#include <brillo/message_loops/base_message_loop.h>
#include <brillo/message_loops/message_loop_utils.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "update_engine/common/constants.h"
@@ -74,6 +75,12 @@ class PostinstActionProcessorDelegate : public ActionProcessorDelegate {
bool processing_stopped_called_{false};
};
+class MockPostinstallRunnerActionDelegate
+ : public PostinstallRunnerAction::DelegateInterface {
+ public:
+ MOCK_METHOD1(ProgressUpdate, void(double progress));
+};
+
class PostinstallRunnerActionTest : public ::testing::Test {
protected:
void SetUp() override {
@@ -160,7 +167,10 @@ class PostinstallRunnerActionTest : public ::testing::Test {
string postinstall_image_;
FakeBootControl fake_boot_control_;
- PostinstActionProcessorDelegate delegate_;
+ PostinstActionProcessorDelegate processor_delegate_;
+
+ // The PostinstallRunnerAction delegate receiving the progress updates.
+ PostinstallRunnerAction::DelegateInterface* setup_action_delegate_{nullptr};
// A pointer to the posinstall_runner action and the processor.
PostinstallRunnerAction* postinstall_action_{nullptr};
@@ -187,13 +197,14 @@ void PostinstallRunnerActionTest::RunPosinstallAction(
PostinstallRunnerAction runner_action(&fake_boot_control_,
powerwash_marker_file_.c_str());
postinstall_action_ = &runner_action;
+ runner_action.set_delegate(setup_action_delegate_);
BondActions(&feeder_action, &runner_action);
ObjectCollectorAction<InstallPlan> collector_action;
BondActions(&runner_action, &collector_action);
processor.EnqueueAction(&feeder_action);
processor.EnqueueAction(&runner_action);
processor.EnqueueAction(&collector_action);
- processor.set_delegate(&delegate_);
+ processor.set_delegate(&processor_delegate_);
loop_.PostTask(FROM_HERE,
base::Bind([&processor] { processor.StartProcessing(); }));
@@ -201,21 +212,43 @@ void PostinstallRunnerActionTest::RunPosinstallAction(
ASSERT_FALSE(processor.IsRunning());
postinstall_action_ = nullptr;
processor_ = nullptr;
- EXPECT_TRUE(delegate_.processing_stopped_called_ ||
- delegate_.processing_done_called_);
- if (delegate_.processing_done_called_) {
+ EXPECT_TRUE(processor_delegate_.processing_stopped_called_ ||
+ processor_delegate_.processing_done_called_);
+ if (processor_delegate_.processing_done_called_) {
// Sanity check that the code was set when the processor finishes.
- EXPECT_TRUE(delegate_.code_set_);
+ EXPECT_TRUE(processor_delegate_.code_set_);
}
}
+TEST_F(PostinstallRunnerActionTest, ProcessProgressLineTest) {
+ PostinstallRunnerAction action(&fake_boot_control_,
+ powerwash_marker_file_.c_str());
+ testing::StrictMock<MockPostinstallRunnerActionDelegate> mock_delegate_;
+ action.set_delegate(&mock_delegate_);
+
+ action.current_partition_ = 1;
+ action.partition_weight_ = {1, 2, 5};
+ action.accumulated_weight_ = 1;
+ action.total_weight_ = 8;
+
+ // 50% of the second actions is 2/8 = 0.25 of the total.
+ EXPECT_CALL(mock_delegate_, ProgressUpdate(0.25));
+ action.ProcessProgressLine("global_progress 0.5");
+ testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
+
+ // None of these should trigger a progress update.
+ action.ProcessProgressLine("foo_bar");
+ action.ProcessProgressLine("global_progress");
+ action.ProcessProgressLine("global_progress ");
+}
+
// Test that postinstall succeeds in the simple case of running the default
// /postinst command which only exits 0.
TEST_F(PostinstallRunnerActionTest, RunAsRootSimpleTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
RunPosinstallAction(loop.dev(), kPostinstallDefaultScript, false);
- EXPECT_EQ(ErrorCode::kSuccess, delegate_.code_);
- EXPECT_TRUE(delegate_.processing_done_called_);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
+ EXPECT_TRUE(processor_delegate_.processing_done_called_);
// Since powerwash_required was false, this should not trigger a powerwash.
EXPECT_FALSE(utils::FileExists(powerwash_marker_file_.c_str()));
@@ -224,14 +257,14 @@ TEST_F(PostinstallRunnerActionTest, RunAsRootSimpleTest) {
TEST_F(PostinstallRunnerActionTest, RunAsRootRunSymlinkFileTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
RunPosinstallAction(loop.dev(), "bin/postinst_link", false);
- EXPECT_EQ(ErrorCode::kSuccess, delegate_.code_);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
TEST_F(PostinstallRunnerActionTest, RunAsRootPowerwashRequiredTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
// Run a simple postinstall program but requiring a powerwash.
RunPosinstallAction(loop.dev(), "bin/postinst_example", true);
- EXPECT_EQ(ErrorCode::kSuccess, delegate_.code_);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
// Check that the powerwash marker file was set.
string actual_cmd;
@@ -244,7 +277,7 @@ TEST_F(PostinstallRunnerActionTest, RunAsRootPowerwashRequiredTest) {
// fail.
TEST_F(PostinstallRunnerActionTest, RunAsRootCantMountTest) {
RunPosinstallAction("/dev/null", kPostinstallDefaultScript, false);
- EXPECT_EQ(ErrorCode::kPostinstallRunnerError, delegate_.code_);
+ EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
// In case of failure, Postinstall should not signal a powerwash even if it
// was requested.
@@ -256,7 +289,7 @@ TEST_F(PostinstallRunnerActionTest, RunAsRootCantMountTest) {
TEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
RunPosinstallAction(loop.dev(), "bin/postinst_fail1", false);
- EXPECT_EQ(ErrorCode::kPostinstallRunnerError, delegate_.code_);
+ EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
}
// The exit code 3 and 4 are a specials cases that would be reported back to
@@ -264,14 +297,15 @@ TEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) {
TEST_F(PostinstallRunnerActionTest, RunAsRootFirmwareBErrScriptTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
RunPosinstallAction(loop.dev(), "bin/postinst_fail3", false);
- EXPECT_EQ(ErrorCode::kPostinstallBootedFromFirmwareB, delegate_.code_);
+ EXPECT_EQ(ErrorCode::kPostinstallBootedFromFirmwareB,
+ processor_delegate_.code_);
}
// Check that you can't specify an absolute path.
TEST_F(PostinstallRunnerActionTest, RunAsRootAbsolutePathNotAllowedTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
RunPosinstallAction(loop.dev(), "/etc/../bin/sh", false);
- EXPECT_EQ(ErrorCode::kPostinstallRunnerError, delegate_.code_);
+ EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
}
#ifdef __ANDROID__
@@ -280,7 +314,7 @@ TEST_F(PostinstallRunnerActionTest, RunAsRootAbsolutePathNotAllowedTest) {
TEST_F(PostinstallRunnerActionTest, RunAsRootCheckFileContextsTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
RunPosinstallAction(loop.dev(), "bin/self_check_context", false);
- EXPECT_EQ(ErrorCode::kSuccess, delegate_.code_);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
#endif // __ANDROID__
@@ -294,8 +328,8 @@ TEST_F(PostinstallRunnerActionTest, RunAsRootSuspendResumeActionTest) {
base::Unretained(this)));
RunPosinstallAction(loop.dev(), "bin/postinst_suspend", false);
// postinst_suspend returns 0 only if it was suspended at some point.
- EXPECT_EQ(ErrorCode::kSuccess, delegate_.code_);
- EXPECT_TRUE(delegate_.processing_done_called_);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
+ EXPECT_TRUE(processor_delegate_.processing_done_called_);
}
// Test that we can cancel a postinstall action while it is running.
@@ -307,8 +341,28 @@ TEST_F(PostinstallRunnerActionTest, RunAsRootCancelPostinstallActionTest) {
RunPosinstallAction(loop.dev(), "bin/postinst_suspend", false);
// When canceling the action, the action never finished and therefore we had
// a ProcessingStopped call instead.
- EXPECT_FALSE(delegate_.code_set_);
- EXPECT_TRUE(delegate_.processing_stopped_called_);
+ EXPECT_FALSE(processor_delegate_.code_set_);
+ EXPECT_TRUE(processor_delegate_.processing_stopped_called_);
+}
+
+// Test that we parse and process the progress reports from the progress
+// file descriptor.
+TEST_F(PostinstallRunnerActionTest, RunAsRootProgressUpdatesTest) {
+ testing::StrictMock<MockPostinstallRunnerActionDelegate> mock_delegate_;
+ testing::InSequence s;
+ EXPECT_CALL(mock_delegate_, ProgressUpdate(0));
+
+ // The postinst_progress program will call with 0.25, 0.5 and 1.
+ EXPECT_CALL(mock_delegate_, ProgressUpdate(0.25));
+ EXPECT_CALL(mock_delegate_, ProgressUpdate(0.5));
+ EXPECT_CALL(mock_delegate_, ProgressUpdate(1.));
+
+ EXPECT_CALL(mock_delegate_, ProgressUpdate(1.));
+
+ ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
+ setup_action_delegate_ = &mock_delegate_;
+ RunPosinstallAction(loop.dev(), "bin/postinst_progress", false);
+ EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
} // namespace chromeos_update_engine