1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2012 The Android Open Source Project 3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License. 6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at 7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software 11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and 14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License. 15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 163defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/postinstall_runner_action.h" 181c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan 193defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <sys/stat.h> 203defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <sys/types.h> 213defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <unistd.h> 22bfabc3002566ba8aa4bda8c77469a075bd346f00Andrew de los Reyes 2302f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan#include <memory> 243defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <string> 253defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <vector> 26bfabc3002566ba8aa4bda8c77469a075bd346f00Andrew de los Reyes 27d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo#include <base/bind.h> 2806c76a49bfd29c8abdb8abd5b646a6583783191aBen Chan#include <base/files/file_util.h> 290b3db6b6040f53eb9859e614f7fe4c681213d33aAlex Deymo#include <base/message_loop/message_loop.h> 3075039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/string_util.h> 3175039d7397f03dff77bdf4e26398049ff88edc4cAlex Vakulenko#include <base/strings/stringprintf.h> 323f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/bind_lambda.h> 333f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/base_message_loop.h> 343f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko#include <brillo/message_loops/message_loop_utils.h> 350d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo#include <gmock/gmock.h> 363defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com#include <gtest/gtest.h> 37bfabc3002566ba8aa4bda8c77469a075bd346f00Andrew de los Reyes 3839910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/constants.h" 39b15a0b8eaf18c9e9341706df9f4ab59ce595a67cAlex Deymo#include "update_engine/common/fake_boot_control.h" 40fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo#include "update_engine/common/fake_hardware.h" 4139910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/test_utils.h" 4239910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h" 433defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 443f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkousing brillo::MessageLoop; 45cbc2274c4160805bf726df872390112654816ca7Alex Deymousing chromeos_update_engine::test_utils::ScopedLoopbackDeviceBinder; 463defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comusing std::string; 473defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comusing std::vector; 483defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 493defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comnamespace chromeos_update_engine { 503defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 513defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.comclass PostinstActionProcessorDelegate : public ActionProcessorDelegate { 523defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com public: 53d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo PostinstActionProcessorDelegate() = default; 546f03a3b868d4b632931400628763036f79c449f7Darin Petkov void ProcessingDone(const ActionProcessor* processor, 55d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo ErrorCode code) override { 5629b815316519829f133b39dd1cae7ab6224c9da2Alex Deymo MessageLoop::current()->BreakLoop(); 57d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo processing_done_called_ = true; 586f03a3b868d4b632931400628763036f79c449f7Darin Petkov } 59d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo void ProcessingStopped(const ActionProcessor* processor) override { 60d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo MessageLoop::current()->BreakLoop(); 61d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo processing_stopped_called_ = true; 62d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } 63d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 643defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com void ActionCompleted(ActionProcessor* processor, 653defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com AbstractAction* action, 66d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo ErrorCode code) override { 673defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com if (action->Type() == PostinstallRunnerAction::StaticType()) { 68c1a8b426be9542bc880923711ca508ea3f84000eDarin Petkov code_ = code; 69c1a8b426be9542bc880923711ca508ea3f84000eDarin Petkov code_set_ = true; 703defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com } 713defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com } 72cbc2274c4160805bf726df872390112654816ca7Alex Deymo 73d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo ErrorCode code_{ErrorCode::kError}; 74d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo bool code_set_{false}; 75d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo bool processing_done_called_{false}; 76d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo bool processing_stopped_called_{false}; 773defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com}; 783defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 790d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymoclass MockPostinstallRunnerActionDelegate 800d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo : public PostinstallRunnerAction::DelegateInterface { 810d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo public: 820d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo MOCK_METHOD1(ProgressUpdate, void(double progress)); 830d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo}; 840d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 85cbc2274c4160805bf726df872390112654816ca7Alex Deymoclass PostinstallRunnerActionTest : public ::testing::Test { 86cbc2274c4160805bf726df872390112654816ca7Alex Deymo protected: 87cbc2274c4160805bf726df872390112654816ca7Alex Deymo void SetUp() override { 88cbc2274c4160805bf726df872390112654816ca7Alex Deymo loop_.SetAsCurrent(); 89cbc2274c4160805bf726df872390112654816ca7Alex Deymo async_signal_handler_.Init(); 90cbc2274c4160805bf726df872390112654816ca7Alex Deymo subprocess_.Init(&async_signal_handler_); 91cbc2274c4160805bf726df872390112654816ca7Alex Deymo // These tests use the postinstall files generated by "generate_images.sh" 92d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // stored in the "disk_ext2_unittest.img" image. 93260f03bc4d3a3de436e056c686c814444358823aSen Jiang postinstall_image_ = 94260f03bc4d3a3de436e056c686c814444358823aSen Jiang test_utils::GetBuildArtifactsPath("gen/disk_ext2_unittest.img"); 95cbc2274c4160805bf726df872390112654816ca7Alex Deymo } 961c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan 97cbc2274c4160805bf726df872390112654816ca7Alex Deymo // Setup an action processor and run the PostinstallRunnerAction with a single 98cbc2274c4160805bf726df872390112654816ca7Alex Deymo // partition |device_path|, running the |postinstall_program| command from 99cbc2274c4160805bf726df872390112654816ca7Alex Deymo // there. 100cbc2274c4160805bf726df872390112654816ca7Alex Deymo void RunPosinstallAction(const string& device_path, 101cbc2274c4160805bf726df872390112654816ca7Alex Deymo const string& postinstall_program, 102cbc2274c4160805bf726df872390112654816ca7Alex Deymo bool powerwash_required); 1033defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 104d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo public: 105d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo void ResumeRunningAction() { 106d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo ASSERT_NE(nullptr, postinstall_action_); 107d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo postinstall_action_->ResumeAction(); 108d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } 109d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 110d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo void SuspendRunningAction() { 111d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo if (!postinstall_action_ || !postinstall_action_->current_command_ || 112d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo test_utils::Readlink(base::StringPrintf( 113d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo "/proc/%d/fd/0", postinstall_action_->current_command_)) != 114d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo "/dev/zero") { 115d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // We need to wait for the postinstall command to start and flag that it 116d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // is ready by redirecting its input to /dev/zero. 117d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo loop_.PostDelayedTask( 118d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo FROM_HERE, 119d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Bind(&PostinstallRunnerActionTest::SuspendRunningAction, 120d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Unretained(this)), 121d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::TimeDelta::FromMilliseconds(100)); 122d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } else { 123d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo postinstall_action_->SuspendAction(); 124d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // Schedule to be resumed in a little bit. 125d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo loop_.PostDelayedTask( 126d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo FROM_HERE, 127d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Bind(&PostinstallRunnerActionTest::ResumeRunningAction, 128d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Unretained(this)), 129d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::TimeDelta::FromMilliseconds(100)); 130d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } 131d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } 132d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 133d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo void CancelWhenStarted() { 134d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo if (!postinstall_action_ || !postinstall_action_->current_command_) { 135d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // Wait for the postinstall command to run. 136d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo loop_.PostDelayedTask( 137d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo FROM_HERE, 138d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Bind(&PostinstallRunnerActionTest::CancelWhenStarted, 139d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Unretained(this)), 140d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::TimeDelta::FromMilliseconds(10)); 141d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } else { 142d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo CHECK(processor_); 143d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo processor_->StopProcessing(); 144d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } 145d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } 146d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 147cbc2274c4160805bf726df872390112654816ca7Alex Deymo protected: 148cbc2274c4160805bf726df872390112654816ca7Alex Deymo base::MessageLoopForIO base_loop_; 149cbc2274c4160805bf726df872390112654816ca7Alex Deymo brillo::BaseMessageLoop loop_{&base_loop_}; 150cbc2274c4160805bf726df872390112654816ca7Alex Deymo brillo::AsynchronousSignalHandler async_signal_handler_; 151cbc2274c4160805bf726df872390112654816ca7Alex Deymo Subprocess subprocess_; 1523defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 153cbc2274c4160805bf726df872390112654816ca7Alex Deymo // The path to the postinstall sample image. 154cbc2274c4160805bf726df872390112654816ca7Alex Deymo string postinstall_image_; 15581018e089aedb07d806f5e6a18dc44e359a6fc06Don Garrett 156cbc2274c4160805bf726df872390112654816ca7Alex Deymo FakeBootControl fake_boot_control_; 157fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo FakeHardware fake_hardware_; 1580d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo PostinstActionProcessorDelegate processor_delegate_; 1590d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 1600d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo // The PostinstallRunnerAction delegate receiving the progress updates. 1610d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo PostinstallRunnerAction::DelegateInterface* setup_action_delegate_{nullptr}; 162d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 163d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // A pointer to the posinstall_runner action and the processor. 164d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo PostinstallRunnerAction* postinstall_action_{nullptr}; 165d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo ActionProcessor* processor_{nullptr}; 166cbc2274c4160805bf726df872390112654816ca7Alex Deymo}; 16730dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold 168cbc2274c4160805bf726df872390112654816ca7Alex Deymovoid PostinstallRunnerActionTest::RunPosinstallAction( 169cbc2274c4160805bf726df872390112654816ca7Alex Deymo const string& device_path, 170cbc2274c4160805bf726df872390112654816ca7Alex Deymo const string& postinstall_program, 1711c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan bool powerwash_required) { 1723defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com ActionProcessor processor; 173d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo processor_ = &processor; 174f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes ObjectFeederAction<InstallPlan> feeder_action; 175e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo InstallPlan::Partition part; 176e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo part.name = "part"; 177cbc2274c4160805bf726df872390112654816ca7Alex Deymo part.target_path = device_path; 178e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo part.run_postinstall = true; 179cbc2274c4160805bf726df872390112654816ca7Alex Deymo part.postinstall_path = postinstall_program; 180f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes InstallPlan install_plan; 181e5e5fe926e9ea45b1a381af1bee91a86643ffd72Alex Deymo install_plan.partitions = {part}; 182cbc2274c4160805bf726df872390112654816ca7Alex Deymo install_plan.download_url = "http://127.0.0.1:8080/update"; 1831c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan install_plan.powerwash_required = powerwash_required; 184f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes feeder_action.set_obj(install_plan); 185fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo PostinstallRunnerAction runner_action(&fake_boot_control_, &fake_hardware_); 186d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo postinstall_action_ = &runner_action; 1870d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo runner_action.set_delegate(setup_action_delegate_); 1883defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com BondActions(&feeder_action, &runner_action); 189f97144334e945a5ec88970b4b28f4e98ce0bbb80Andrew de los Reyes ObjectCollectorAction<InstallPlan> collector_action; 1903defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com BondActions(&runner_action, &collector_action); 1913defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com processor.EnqueueAction(&feeder_action); 1923defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com processor.EnqueueAction(&runner_action); 1933defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com processor.EnqueueAction(&collector_action); 1940d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo processor.set_delegate(&processor_delegate_); 1956f03a3b868d4b632931400628763036f79c449f7Darin Petkov 196f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez loop_.PostTask( 197f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez FROM_HERE, 198f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez base::Bind( 199f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez [](ActionProcessor* processor) { processor->StartProcessing(); }, 200f1cf34849efdc0158fb1987ba74a51f25016c5bdLuis Hector Chavez base::Unretained(&processor))); 20129b815316519829f133b39dd1cae7ab6224c9da2Alex Deymo loop_.Run(); 2026f03a3b868d4b632931400628763036f79c449f7Darin Petkov ASSERT_FALSE(processor.IsRunning()); 203d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo postinstall_action_ = nullptr; 204d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo processor_ = nullptr; 2050d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_TRUE(processor_delegate_.processing_stopped_called_ || 2060d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo processor_delegate_.processing_done_called_); 2070d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo if (processor_delegate_.processing_done_called_) { 208d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // Sanity check that the code was set when the processor finishes. 2090d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_TRUE(processor_delegate_.code_set_); 210d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo } 211cbc2274c4160805bf726df872390112654816ca7Alex Deymo} 212cbc2274c4160805bf726df872390112654816ca7Alex Deymo 2130d29854cf5bb05a22cf161b50052539aa420a36eAlex DeymoTEST_F(PostinstallRunnerActionTest, ProcessProgressLineTest) { 214fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo PostinstallRunnerAction action(&fake_boot_control_, &fake_hardware_); 2150d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo testing::StrictMock<MockPostinstallRunnerActionDelegate> mock_delegate_; 2160d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.set_delegate(&mock_delegate_); 2170d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 2180d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.current_partition_ = 1; 2190d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.partition_weight_ = {1, 2, 5}; 2200d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.accumulated_weight_ = 1; 2210d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.total_weight_ = 8; 2220d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 223d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo // 50% of the second action is 2/8 = 0.25 of the total. 2240d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_CALL(mock_delegate_, ProgressUpdate(0.25)); 2250d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.ProcessProgressLine("global_progress 0.5"); 2260d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo testing::Mock::VerifyAndClearExpectations(&mock_delegate_); 2270d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 228d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo // 1.5 should be read as 100%, to catch rounding error cases like 1.000001. 229d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo // 100% of the second is 3/8 of the total. 230d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo EXPECT_CALL(mock_delegate_, ProgressUpdate(0.375)); 231d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo action.ProcessProgressLine("global_progress 1.5"); 232d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo testing::Mock::VerifyAndClearExpectations(&mock_delegate_); 233d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo 2340d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo // None of these should trigger a progress update. 2350d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.ProcessProgressLine("foo_bar"); 2360d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.ProcessProgressLine("global_progress"); 2370d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo action.ProcessProgressLine("global_progress "); 238d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo action.ProcessProgressLine("global_progress NaN"); 239d853730826e02647dee6ac818ceef73a4d0e57f0Alex Deymo action.ProcessProgressLine("global_progress Exception in ... :)"); 2400d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo} 2410d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 242cbc2274c4160805bf726df872390112654816ca7Alex Deymo// Test that postinstall succeeds in the simple case of running the default 243cbc2274c4160805bf726df872390112654816ca7Alex Deymo// /postinst command which only exits 0. 244cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootSimpleTest) { 245cbc2274c4160805bf726df872390112654816ca7Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 246cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction(loop.dev(), kPostinstallDefaultScript, false); 2470d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_); 2480d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_TRUE(processor_delegate_.processing_done_called_); 2493defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 250cbc2274c4160805bf726df872390112654816ca7Alex Deymo // Since powerwash_required was false, this should not trigger a powerwash. 251fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo EXPECT_FALSE(fake_hardware_.IsPowerwashScheduled()); 252cbc2274c4160805bf726df872390112654816ca7Alex Deymo} 253cbc2274c4160805bf726df872390112654816ca7Alex Deymo 254cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootRunSymlinkFileTest) { 255cbc2274c4160805bf726df872390112654816ca7Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 256cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction(loop.dev(), "bin/postinst_link", false); 2570d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_); 258cbc2274c4160805bf726df872390112654816ca7Alex Deymo} 259cbc2274c4160805bf726df872390112654816ca7Alex Deymo 260cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootPowerwashRequiredTest) { 261cbc2274c4160805bf726df872390112654816ca7Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 262cbc2274c4160805bf726df872390112654816ca7Alex Deymo // Run a simple postinstall program but requiring a powerwash. 263cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction(loop.dev(), "bin/postinst_example", true); 2640d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_); 2651c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan 266fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo // Check that powerwash was scheduled. 267fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo EXPECT_TRUE(fake_hardware_.IsPowerwashScheduled()); 268cbc2274c4160805bf726df872390112654816ca7Alex Deymo} 2691c0fe79c7ef2b43946d756b54c8505d2bf48b93bJay Srinivasan 270cbc2274c4160805bf726df872390112654816ca7Alex Deymo// Runs postinstall from a partition file that doesn't mount, so it should 271cbc2274c4160805bf726df872390112654816ca7Alex Deymo// fail. 272cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootCantMountTest) { 273cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction("/dev/null", kPostinstallDefaultScript, false); 2740d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_); 2753defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 276cbc2274c4160805bf726df872390112654816ca7Alex Deymo // In case of failure, Postinstall should not signal a powerwash even if it 277cbc2274c4160805bf726df872390112654816ca7Alex Deymo // was requested. 278fb905d9b8d49f8fe41297c7aba2dd0942f1be311Alex Deymo EXPECT_FALSE(fake_hardware_.IsPowerwashScheduled()); 279cbc2274c4160805bf726df872390112654816ca7Alex Deymo} 2803defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 281cbc2274c4160805bf726df872390112654816ca7Alex Deymo// Check that the failures from the postinstall script cause the action to 282cbc2274c4160805bf726df872390112654816ca7Alex Deymo// fail. 283cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) { 284cbc2274c4160805bf726df872390112654816ca7Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 285cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction(loop.dev(), "bin/postinst_fail1", false); 2860d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_); 287cbc2274c4160805bf726df872390112654816ca7Alex Deymo} 28830dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold 289cbc2274c4160805bf726df872390112654816ca7Alex Deymo// The exit code 3 and 4 are a specials cases that would be reported back to 290cbc2274c4160805bf726df872390112654816ca7Alex Deymo// UMA with a different error code. Test those cases are properly detected. 291cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootFirmwareBErrScriptTest) { 292cbc2274c4160805bf726df872390112654816ca7Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 293cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction(loop.dev(), "bin/postinst_fail3", false); 2940d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kPostinstallBootedFromFirmwareB, 2950d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo processor_delegate_.code_); 296cbc2274c4160805bf726df872390112654816ca7Alex Deymo} 29730dedd82be72ffa9bbe570e9c95166ec6bcc7792Gilad Arnold 298cbc2274c4160805bf726df872390112654816ca7Alex Deymo// Check that you can't specify an absolute path. 299cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootAbsolutePathNotAllowedTest) { 300cbc2274c4160805bf726df872390112654816ca7Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 301cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction(loop.dev(), "/etc/../bin/sh", false); 3020d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_); 3033defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com} 3043defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 305cbc2274c4160805bf726df872390112654816ca7Alex Deymo#ifdef __ANDROID__ 306cbc2274c4160805bf726df872390112654816ca7Alex Deymo// Check that the postinstall file is relabeled to the postinstall label. 307cbc2274c4160805bf726df872390112654816ca7Alex Deymo// SElinux labels are only set on Android. 308cbc2274c4160805bf726df872390112654816ca7Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootCheckFileContextsTest) { 309cbc2274c4160805bf726df872390112654816ca7Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 310cbc2274c4160805bf726df872390112654816ca7Alex Deymo RunPosinstallAction(loop.dev(), "bin/self_check_context", false); 3110d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_); 3123defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com} 313cbc2274c4160805bf726df872390112654816ca7Alex Deymo#endif // __ANDROID__ 3143defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com 315d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo// Check that you can suspend/resume postinstall actions. 316d15c546ed794293d0a63770467a0f3c4c84c6214Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootSuspendResumeActionTest) { 317d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 318d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 319d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // We need to wait for the child to run and setup its signal handler. 320d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo loop_.PostTask(FROM_HERE, 321d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Bind(&PostinstallRunnerActionTest::SuspendRunningAction, 322d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo base::Unretained(this))); 323d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo RunPosinstallAction(loop.dev(), "bin/postinst_suspend", false); 324d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // postinst_suspend returns 0 only if it was suspended at some point. 3250d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_); 3260d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_TRUE(processor_delegate_.processing_done_called_); 327d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo} 328d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 329d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo// Test that we can cancel a postinstall action while it is running. 330d15c546ed794293d0a63770467a0f3c4c84c6214Alex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootCancelPostinstallActionTest) { 331d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 332d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 333d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // Wait for the action to start and then cancel it. 334d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo CancelWhenStarted(); 335d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo RunPosinstallAction(loop.dev(), "bin/postinst_suspend", false); 336d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // When canceling the action, the action never finished and therefore we had 337d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo // a ProcessingStopped call instead. 3380d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_FALSE(processor_delegate_.code_set_); 3390d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_TRUE(processor_delegate_.processing_stopped_called_); 3400d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo} 3410d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 3420d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo// Test that we parse and process the progress reports from the progress 3430d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo// file descriptor. 3440d29854cf5bb05a22cf161b50052539aa420a36eAlex DeymoTEST_F(PostinstallRunnerActionTest, RunAsRootProgressUpdatesTest) { 3450d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo testing::StrictMock<MockPostinstallRunnerActionDelegate> mock_delegate_; 3460d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo testing::InSequence s; 3470d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_CALL(mock_delegate_, ProgressUpdate(0)); 3480d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 3490d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo // The postinst_progress program will call with 0.25, 0.5 and 1. 3500d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_CALL(mock_delegate_, ProgressUpdate(0.25)); 3510d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_CALL(mock_delegate_, ProgressUpdate(0.5)); 3520d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_CALL(mock_delegate_, ProgressUpdate(1.)); 3530d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 3540d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_CALL(mock_delegate_, ProgressUpdate(1.)); 3550d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo 3560d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr); 3570d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo setup_action_delegate_ = &mock_delegate_; 3580d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo RunPosinstallAction(loop.dev(), "bin/postinst_progress", false); 3590d29854cf5bb05a22cf161b50052539aa420a36eAlex Deymo EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_); 360d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo} 361d15c546ed794293d0a63770467a0f3c4c84c6214Alex Deymo 3623defe6acb3609e70e851a6eff062577d25a2af9dadlr@google.com} // namespace chromeos_update_engine 363