• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2009 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 
17 #include "update_engine/common/action_processor.h"
18 
19 #include <string>
20 #include <utility>
21 
22 #include <gtest/gtest.h>
23 
24 #include "update_engine/common/action.h"
25 #include "update_engine/common/mock_action.h"
26 
27 using std::string;
28 
29 namespace chromeos_update_engine {
30 
31 using chromeos_update_engine::ActionPipe;
32 
33 class ActionProcessorTestAction;
34 
35 template <>
36 class ActionTraits<ActionProcessorTestAction> {
37  public:
38   typedef string OutputObjectType;
39   typedef string InputObjectType;
40 };
41 
42 // This is a simple Action class for testing.
43 class ActionProcessorTestAction : public Action<ActionProcessorTestAction> {
44  public:
45   typedef string InputObjectType;
46   typedef string OutputObjectType;
in_pipe()47   ActionPipe<string>* in_pipe() { return in_pipe_.get(); }
out_pipe()48   ActionPipe<string>* out_pipe() { return out_pipe_.get(); }
processor()49   ActionProcessor* processor() { return processor_; }
PerformAction()50   void PerformAction() {}
CompleteAction()51   void CompleteAction() {
52     ASSERT_TRUE(processor());
53     processor()->ActionComplete(this, ErrorCode::kSuccess);
54   }
Type() const55   string Type() const { return "ActionProcessorTestAction"; }
56 };
57 
58 namespace {
59 class MyActionProcessorDelegate : public ActionProcessorDelegate {
60  public:
MyActionProcessorDelegate(const ActionProcessor * processor)61   explicit MyActionProcessorDelegate(const ActionProcessor* processor)
62       : processor_(processor),
63         processing_done_called_(false),
64         processing_stopped_called_(false),
65         action_completed_called_(false),
66         action_exit_code_(ErrorCode::kError) {}
67 
ProcessingDone(const ActionProcessor * processor,ErrorCode code)68   virtual void ProcessingDone(const ActionProcessor* processor,
69                               ErrorCode code) {
70     EXPECT_EQ(processor_, processor);
71     EXPECT_FALSE(processing_done_called_);
72     processing_done_called_ = true;
73   }
ProcessingStopped(const ActionProcessor * processor)74   virtual void ProcessingStopped(const ActionProcessor* processor) {
75     EXPECT_EQ(processor_, processor);
76     EXPECT_FALSE(processing_stopped_called_);
77     processing_stopped_called_ = true;
78   }
ActionCompleted(ActionProcessor * processor,AbstractAction * action,ErrorCode code)79   virtual void ActionCompleted(ActionProcessor* processor,
80                                AbstractAction* action,
81                                ErrorCode code) {
82     EXPECT_EQ(processor_, processor);
83     EXPECT_FALSE(action_completed_called_);
84     action_completed_called_ = true;
85     action_exit_code_ = code;
86   }
87 
88   const ActionProcessor* processor_;
89   bool processing_done_called_;
90   bool processing_stopped_called_;
91   bool action_completed_called_;
92   ErrorCode action_exit_code_;
93 };
94 }  // namespace
95 
96 class ActionProcessorTest : public ::testing::Test {
SetUp()97   void SetUp() override {
98     action_processor_.set_delegate(&delegate_);
99     // Silence Type() calls used for logging.
100     mock_action_.reset(new testing::StrictMock<MockAction>());
101     mock_action_ptr_ = mock_action_.get();
102     action_.reset(new ActionProcessorTestAction());
103     action_ptr_ = action_.get();
104     EXPECT_CALL(*mock_action_, Type()).Times(testing::AnyNumber());
105   }
106 
TearDown()107   void TearDown() override { action_processor_.set_delegate(nullptr); }
108 
109  protected:
110   // The ActionProcessor under test.
111   ActionProcessor action_processor_;
112 
113   MyActionProcessorDelegate delegate_{&action_processor_};
114 
115   // Common actions used during most tests.
116   std::unique_ptr<testing::StrictMock<MockAction>> mock_action_;
117   testing::StrictMock<MockAction>* mock_action_ptr_;
118   std::unique_ptr<ActionProcessorTestAction> action_;
119   ActionProcessorTestAction* action_ptr_;
120 };
121 
TEST_F(ActionProcessorTest,SimpleTest)122 TEST_F(ActionProcessorTest, SimpleTest) {
123   EXPECT_FALSE(action_processor_.IsRunning());
124   action_processor_.EnqueueAction(std::move(action_));
125   EXPECT_FALSE(action_processor_.IsRunning());
126   EXPECT_FALSE(action_ptr_->IsRunning());
127   action_processor_.StartProcessing();
128   EXPECT_TRUE(action_processor_.IsRunning());
129   EXPECT_TRUE(action_ptr_->IsRunning());
130   action_ptr_->CompleteAction();
131   EXPECT_FALSE(action_processor_.IsRunning());
132   EXPECT_EQ(action_processor_.current_action(), nullptr);
133 }
134 
TEST_F(ActionProcessorTest,DelegateTest)135 TEST_F(ActionProcessorTest, DelegateTest) {
136   action_processor_.EnqueueAction(std::move(action_));
137   action_processor_.StartProcessing();
138   action_ptr_->CompleteAction();
139   EXPECT_TRUE(delegate_.processing_done_called_);
140   EXPECT_TRUE(delegate_.action_completed_called_);
141 }
142 
TEST_F(ActionProcessorTest,StopProcessingTest)143 TEST_F(ActionProcessorTest, StopProcessingTest) {
144   action_processor_.EnqueueAction(std::move(action_));
145   action_processor_.StartProcessing();
146   action_processor_.StopProcessing();
147   EXPECT_TRUE(delegate_.processing_stopped_called_);
148   EXPECT_FALSE(delegate_.action_completed_called_);
149   EXPECT_FALSE(action_processor_.IsRunning());
150   EXPECT_EQ(nullptr, action_processor_.current_action());
151 }
152 
TEST_F(ActionProcessorTest,ChainActionsTest)153 TEST_F(ActionProcessorTest, ChainActionsTest) {
154   // This test doesn't use a delegate since it terminates several actions.
155   action_processor_.set_delegate(nullptr);
156 
157   auto action0 = std::make_unique<ActionProcessorTestAction>();
158   auto action1 = std::make_unique<ActionProcessorTestAction>();
159   auto action2 = std::make_unique<ActionProcessorTestAction>();
160   auto action0_ptr = action0.get();
161   auto action1_ptr = action1.get();
162   auto action2_ptr = action2.get();
163   action_processor_.EnqueueAction(std::move(action0));
164   action_processor_.EnqueueAction(std::move(action1));
165   action_processor_.EnqueueAction(std::move(action2));
166 
167   EXPECT_EQ(action_processor_.actions_.size(), 3u);
168   EXPECT_EQ(action_processor_.actions_[0].get(), action0_ptr);
169   EXPECT_EQ(action_processor_.actions_[1].get(), action1_ptr);
170   EXPECT_EQ(action_processor_.actions_[2].get(), action2_ptr);
171 
172   action_processor_.StartProcessing();
173   EXPECT_EQ(action0_ptr, action_processor_.current_action());
174   EXPECT_TRUE(action_processor_.IsRunning());
175   action0_ptr->CompleteAction();
176   EXPECT_EQ(action1_ptr, action_processor_.current_action());
177   EXPECT_TRUE(action_processor_.IsRunning());
178   action1_ptr->CompleteAction();
179   EXPECT_EQ(action2_ptr, action_processor_.current_action());
180   EXPECT_TRUE(action_processor_.actions_.empty());
181   EXPECT_TRUE(action_processor_.IsRunning());
182   action2_ptr->CompleteAction();
183   EXPECT_EQ(nullptr, action_processor_.current_action());
184   EXPECT_TRUE(action_processor_.actions_.empty());
185   EXPECT_FALSE(action_processor_.IsRunning());
186 }
187 
TEST_F(ActionProcessorTest,DefaultDelegateTest)188 TEST_F(ActionProcessorTest, DefaultDelegateTest) {
189   // Just make sure it doesn't crash.
190   action_processor_.EnqueueAction(std::move(action_));
191   action_processor_.StartProcessing();
192   action_ptr_->CompleteAction();
193 
194   action_.reset(new ActionProcessorTestAction());
195   action_processor_.EnqueueAction(std::move(action_));
196   action_processor_.StartProcessing();
197   action_processor_.StopProcessing();
198 }
199 
200 // This test suspends and resume the action processor while running one action.
TEST_F(ActionProcessorTest,SuspendResumeTest)201 TEST_F(ActionProcessorTest, SuspendResumeTest) {
202   action_processor_.EnqueueAction(std::move(mock_action_));
203 
204   testing::InSequence s;
205   EXPECT_CALL(*mock_action_ptr_, PerformAction());
206   action_processor_.StartProcessing();
207 
208   EXPECT_CALL(*mock_action_ptr_, SuspendAction());
209   action_processor_.SuspendProcessing();
210   // Suspending the processor twice should not suspend the action twice.
211   action_processor_.SuspendProcessing();
212 
213   // IsRunning should return whether there's is an action doing some work, even
214   // if it is suspended.
215   EXPECT_TRUE(action_processor_.IsRunning());
216   EXPECT_EQ(mock_action_ptr_, action_processor_.current_action());
217 
218   EXPECT_CALL(*mock_action_ptr_, ResumeAction());
219   action_processor_.ResumeProcessing();
220 
221   // Calling ResumeProcessing twice should not affect the action_.
222   action_processor_.ResumeProcessing();
223   action_processor_.ActionComplete(mock_action_ptr_, ErrorCode::kSuccess);
224 }
225 
226 // This test suspends an action that presumably doesn't support suspend/resume
227 // and it finished before being resumed.
TEST_F(ActionProcessorTest,ActionCompletedWhileSuspendedTest)228 TEST_F(ActionProcessorTest, ActionCompletedWhileSuspendedTest) {
229   action_processor_.EnqueueAction(std::move(mock_action_));
230 
231   testing::InSequence s;
232   EXPECT_CALL(*mock_action_ptr_, PerformAction());
233   action_processor_.StartProcessing();
234 
235   EXPECT_CALL(*mock_action_ptr_, SuspendAction());
236   action_processor_.SuspendProcessing();
237 
238   // Simulate the action completion while suspended. No other call to
239   // |mock_action_| is expected at this point.
240   action_processor_.ActionComplete(mock_action_ptr_, ErrorCode::kSuccess);
241 
242   // The processing should not be done since the ActionProcessor is suspended
243   // and the processing is considered to be still running until resumed.
244   EXPECT_FALSE(delegate_.processing_done_called_);
245   EXPECT_TRUE(action_processor_.IsRunning());
246 
247   action_processor_.ResumeProcessing();
248   EXPECT_TRUE(delegate_.processing_done_called_);
249   EXPECT_FALSE(delegate_.processing_stopped_called_);
250 }
251 
TEST_F(ActionProcessorTest,StoppedWhileSuspendedTest)252 TEST_F(ActionProcessorTest, StoppedWhileSuspendedTest) {
253   action_processor_.EnqueueAction(std::move(mock_action_));
254 
255   testing::InSequence s;
256   EXPECT_CALL(*mock_action_ptr_, PerformAction());
257   action_processor_.StartProcessing();
258   EXPECT_CALL(*mock_action_ptr_, SuspendAction());
259   action_processor_.SuspendProcessing();
260 
261   EXPECT_CALL(*mock_action_ptr_, TerminateProcessing());
262   action_processor_.StopProcessing();
263   // Stopping the processing should abort the current execution no matter what.
264   EXPECT_TRUE(delegate_.processing_stopped_called_);
265   EXPECT_FALSE(delegate_.processing_done_called_);
266   EXPECT_FALSE(delegate_.action_completed_called_);
267   EXPECT_FALSE(action_processor_.IsRunning());
268   EXPECT_EQ(nullptr, action_processor_.current_action());
269 }
270 
271 }  // namespace chromeos_update_engine
272