update_engine: Allow Action's to set ActionPipes individually

This doesn't require bonding two actions in order to set the output.
Making pipes useful when input/output is still required as a standalone
action.

BUG=b:187843882
TEST=# update_engine unittest

Change-Id: I6f838e5e36175a20f22f02978213d866ef96a2d9
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/3151342
Tested-by: Jae Hoon Kim <[email protected]>
Reviewed-by: Vyshu Khota <[email protected]>
Commit-Queue: Jae Hoon Kim <[email protected]>
diff --git a/common/action_pipe.h b/common/action_pipe.h
index cdf3ae6..0479caf 100644
--- a/common/action_pipe.h
+++ b/common/action_pipe.h
@@ -79,6 +79,20 @@
     // different from the To object's InputObjectType.
   }
 
+  // Sets the Action's input pipe with a new ActionPipe.
+  template <typename Action>
+  static void SetInPipe(Action* action) {
+    std::shared_ptr<ActionPipe<ObjectType>> pipe(new ActionPipe<ObjectType>);
+    action->set_in_pipe(pipe);
+  }
+
+  // Sets the Action's output pipe with a new ActionPipe.
+  template <typename Action>
+  static void SetOutPipe(Action* action) {
+    std::shared_ptr<ActionPipe<ObjectType>> pipe(new ActionPipe<ObjectType>);
+    action->set_out_pipe(pipe);
+  }
+
  private:
   ObjectType contents_;
   // Give unit test access
@@ -99,6 +113,16 @@
   ActionPipe<typename FromAction::OutputObjectType>::Bond(from, to);
 }
 
+template <typename Action>
+void SetInPipe(Action* action) {
+  ActionPipe<typename Action::OutputObjectType>::SetInPipe(action);
+}
+
+template <typename Action>
+void SetOutPipe(Action* action) {
+  ActionPipe<typename Action::OutputObjectType>::SetOutPipe(action);
+}
+
 }  // namespace chromeos_update_engine
 
 #endif  // UPDATE_ENGINE_COMMON_ACTION_PIPE_H_
diff --git a/common/action_pipe_unittest.cc b/common/action_pipe_unittest.cc
index 233561d..e6126ad 100644
--- a/common/action_pipe_unittest.cc
+++ b/common/action_pipe_unittest.cc
@@ -50,11 +50,25 @@
 
 // This test creates two simple Actions and sends a message via an ActionPipe
 // from one to the other.
-TEST(ActionPipeTest, SimpleTest) {
+TEST_F(ActionPipeTest, SimpleTest) {
   ActionPipeTestAction a, b;
   BondActions(&a, &b);
   a.out_pipe()->set_contents("foo");
   EXPECT_EQ("foo", b.in_pipe()->contents());
 }
 
+TEST_F(ActionPipeTest, SetInPipeTest) {
+  ActionPipeTestAction a;
+  EXPECT_FALSE(a.HasInputObject());
+  SetInPipe(&a);
+  EXPECT_TRUE(a.HasInputObject());
+}
+
+TEST_F(ActionPipeTest, SetOutPipeTest) {
+  ActionPipeTestAction a;
+  EXPECT_FALSE(a.HasOutputPipe());
+  SetOutPipe(&a);
+  EXPECT_TRUE(a.HasOutputPipe());
+}
+
 }  // namespace chromeos_update_engine