Fridge Presets:

  - Added calls to profiles to implement presets.

Final cleanup by Austin and Brian.

Change-Id: Id706acd5dc3d382a68e3c609a760c2be89b60924
diff --git a/aos/common/actions/action_test.cc b/aos/common/actions/action_test.cc
index 0db4b29..423769e 100644
--- a/aos/common/actions/action_test.cc
+++ b/aos/common/actions/action_test.cc
@@ -17,31 +17,51 @@
 namespace actions {
 namespace testing {
 
+class TestActorIndex
+    : public aos::common::actions::ActorBase<actions::TestActionQueueGroup> {
+ public:
+  explicit TestActorIndex(actions::TestActionQueueGroup *s)
+      : aos::common::actions::ActorBase<actions::TestActionQueueGroup>(s) {}
+
+  bool RunAction(const uint32_t &new_index) override {
+    index = new_index;
+    return true;
+  }
+
+  uint32_t index = 0;
+};
+
+::std::unique_ptr<
+    aos::common::actions::TypedAction<actions::TestActionQueueGroup>>
+MakeTestActionIndex(uint32_t index) {
+  return ::std::unique_ptr<
+      aos::common::actions::TypedAction<actions::TestActionQueueGroup>>(
+      new aos::common::actions::TypedAction<actions::TestActionQueueGroup>(
+          &actions::test_action, index));
+}
+
 class TestActorNOP
     : public aos::common::actions::ActorBase<actions::TestActionQueueGroup> {
  public:
-  explicit TestActorNOP(actions::TestActionQueueGroup* s)
+  explicit TestActorNOP(actions::TestActionQueueGroup *s)
       : actions::ActorBase<actions::TestActionQueueGroup>(s) {}
 
-  bool RunAction() { return true; }
+  bool RunAction(const uint32_t &) override { return true; }
 };
 
 ::std::unique_ptr<
     aos::common::actions::TypedAction<actions::TestActionQueueGroup>>
 MakeTestActionNOP() {
-  return ::std::unique_ptr<
-      aos::common::actions::TypedAction<actions::TestActionQueueGroup>>(
-      new aos::common::actions::TypedAction<actions::TestActionQueueGroup>(
-          &actions::test_action));
+  return MakeTestActionIndex(0);
 }
 
 class TestActorShouldCancel
     : public aos::common::actions::ActorBase<actions::TestActionQueueGroup> {
  public:
-  explicit TestActorShouldCancel(actions::TestActionQueueGroup* s)
+  explicit TestActorShouldCancel(actions::TestActionQueueGroup *s)
       : aos::common::actions::ActorBase<actions::TestActionQueueGroup>(s) {}
 
-  bool RunAction() {
+  bool RunAction(const uint32_t &) override {
     while (!ShouldCancel()) {
       LOG(FATAL, "NOT CANCELED!!\n");
     }
@@ -52,10 +72,25 @@
 ::std::unique_ptr<
     aos::common::actions::TypedAction<actions::TestActionQueueGroup>>
 MakeTestActionShouldCancel() {
+  return MakeTestActionIndex(0);
+}
+
+class TestActor2Nop
+    : public aos::common::actions::ActorBase<actions::TestAction2QueueGroup> {
+ public:
+  explicit TestActor2Nop(actions::TestAction2QueueGroup *s)
+      : actions::ActorBase<actions::TestAction2QueueGroup>(s) {}
+
+  bool RunAction(const actions::MyParams &) { return true; }
+};
+
+::std::unique_ptr<
+    aos::common::actions::TypedAction<actions::TestAction2QueueGroup>>
+MakeTestAction2NOP(const actions::MyParams &params) {
   return ::std::unique_ptr<
-      aos::common::actions::TypedAction<actions::TestActionQueueGroup>>(
-      new aos::common::actions::TypedAction<actions::TestActionQueueGroup>(
-          &actions::test_action));
+      aos::common::actions::TypedAction<actions::TestAction2QueueGroup>>(
+      new aos::common::actions::TypedAction<actions::TestAction2QueueGroup>(
+          &actions::test_action2, params));
 }
 
 class ActionTest : public ::testing::Test {
@@ -65,11 +100,15 @@
     // test.
     actions::test_action.goal.Clear();
     actions::test_action.status.Clear();
+    actions::test_action2.goal.Clear();
+    actions::test_action2.status.Clear();
   }
 
   virtual ~ActionTest() {
     actions::test_action.goal.Clear();
     actions::test_action.status.Clear();
+    actions::test_action2.goal.Clear();
+    actions::test_action2.status.Clear();
   }
 
   // Bring up and down Core.
@@ -88,8 +127,8 @@
 // Tests that the queues are properly configured for testing. Tests that queues
 // work exactly as used in the tests.
 TEST_F(ActionTest, QueueCheck) {
-  actions::TestActionQueueGroup* send_side = &actions::test_action;
-  actions::TestActionQueueGroup* recv_side = &actions::test_action;
+  actions::TestActionQueueGroup *send_side = &actions::test_action;
+  actions::TestActionQueueGroup *recv_side = &actions::test_action;
 
   send_side->goal.MakeMessage();
   send_side->goal.MakeWithBuilder().run(1).Send();
@@ -280,6 +319,76 @@
   EXPECT_FALSE(action_queue_.Running());
 }
 
+// Tests that we do get an index with our goal
+TEST_F(ActionTest, ActionIndex) {
+  TestActorIndex idx_act(&actions::test_action);
+
+  // Tick an empty queue and make sure it was not running.
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+
+  // Enqueue action to post index.
+  action_queue_.EnqueueAction(MakeTestActionIndex(5));
+  EXPECT_TRUE(actions::test_action.goal.FetchLatest());
+  EXPECT_EQ(5u, actions::test_action.goal->params);
+  EXPECT_EQ(0u, idx_act.index);
+
+  idx_act.WaitForActionRequest();
+  action_queue_.Tick();
+
+  // Check the new action is the right one.
+  uint32_t test_id = 0;
+  EXPECT_TRUE(action_queue_.GetCurrentActionState(nullptr, nullptr, nullptr,
+                                                  nullptr, &test_id, nullptr));
+
+  // Run the next action so it can accomplish signal completion.
+  idx_act.RunIteration();
+  action_queue_.Tick();
+  idx_act.WaitForStop(test_id);
+  EXPECT_EQ(5u, idx_act.index);
+
+  // Enqueue action to post index.
+  action_queue_.EnqueueAction(MakeTestActionIndex(3));
+  EXPECT_TRUE(actions::test_action.goal.FetchLatest());
+  EXPECT_EQ(3u, actions::test_action.goal->params);
+
+  // Run the next action so it can accomplish signal completion.
+  idx_act.RunIteration();
+  action_queue_.Tick();
+  idx_act.WaitForStop(test_id);
+  EXPECT_EQ(3u, idx_act.index);
+}
+
+// Tests that an action with a structure params works.
+TEST_F(ActionTest, StructParamType) {
+  TestActor2Nop nop_act(&actions::test_action2);
+
+  // Tick an empty queue and make sure it was not running.
+  action_queue_.Tick();
+  EXPECT_FALSE(action_queue_.Running());
+
+  actions::MyParams p;
+  p.param1 = 5.0;
+  p.param2 = 7;
+
+  action_queue_.EnqueueAction(MakeTestAction2NOP(p));
+  nop_act.WaitForActionRequest();
+
+  // We started an action and it should be running.
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Tick it and make sure it is still running.
+  action_queue_.Tick();
+  EXPECT_TRUE(action_queue_.Running());
+
+  // Run the action so it can signal completion.
+  nop_act.RunIteration();
+  action_queue_.Tick();
+
+  // Make sure it stopped.
+  EXPECT_FALSE(action_queue_.Running());
+}
+
 }  // namespace testing.
 }  // namespace actions.
 }  // namespace common.
diff --git a/aos/common/actions/actions.h b/aos/common/actions/actions.h
index 08d94f7..15054d2 100644
--- a/aos/common/actions/actions.h
+++ b/aos/common/actions/actions.h
@@ -44,13 +44,13 @@
   bool Running();
 
   // Retrieves the internal state of the current action for testing.
-  // See comments on the private members of TypedAction<T> for details.
+  // See comments on the private members of TypedAction<T, S> for details.
   bool GetCurrentActionState(bool* has_started, bool* sent_started,
                              bool* sent_cancel, bool* interrupted,
                              uint32_t* run_value, uint32_t* old_run_value);
 
   // Retrieves the internal state of the next action for testing.
-  // See comments on the private members of TypedAction<T> for details.
+  // See comments on the private members of TypedAction<T, S> for details.
   bool GetNextActionState(bool* has_started, bool* sent_started,
                           bool* sent_cancel, bool* interrupted,
                           uint32_t* run_value, uint32_t* old_run_value);
@@ -76,7 +76,7 @@
   void WaitUntilDone() { DoWaitUntilDone(); }
 
   // Retrieves the internal state of the action for testing.
-  // See comments on the private members of TypedAction<T> for details.
+  // See comments on the private members of TypedAction<T, S> for details.
   void GetState(bool* has_started, bool* sent_started, bool* sent_cancel,
                 bool* interrupted, uint32_t* run_value,
                 uint32_t* old_run_value) {
@@ -95,7 +95,7 @@
   // Blocks until complete.
   virtual void DoWaitUntilDone() = 0;
   // For testing we will need to get the internal state.
-  // See comments on the private members of TypedAction<T> for details.
+  // See comments on the private members of TypedAction<T, S> for details.
   virtual void DoGetState(bool* has_started, bool* sent_started,
                           bool* sent_cancel, bool* interrupted,
                           uint32_t* run_value, uint32_t* old_run_value) = 0;
@@ -107,16 +107,19 @@
  public:
   // A convenient way to refer to the type of our goals.
   typedef typename std::remove_reference<decltype(
-      *(static_cast<T*>(NULL)->goal.MakeMessage().get()))>::type GoalType;
+      *(static_cast<T*>(nullptr)->goal.MakeMessage().get()))>::type GoalType;
+  typedef typename std::remove_reference<
+      decltype(static_cast<GoalType*>(nullptr)->params)>::type ParamType;
 
-  TypedAction(T* queue_group)
+  TypedAction(T* queue_group, const ParamType &params)
       : queue_group_(queue_group),
         goal_(queue_group_->goal.MakeMessage()),
         // This adds 1 to the counter (atomically because it's potentially
         // shared across threads) and then bitwise-ORs the bottom of the PID to
         // differentiate it from other processes's values (ie a unique id).
         run_value_(run_counter_.fetch_add(1, ::std::memory_order_relaxed) |
-                   ((getpid() & 0xFFFF) << 16)) {
+                   ((getpid() & 0xFFFF) << 16)),
+        params_(params) {
     LOG(INFO, "Action %" PRIx32 " created on queue %s\n", run_value_,
         queue_group_->goal.name());
     // Clear out any old status messages from before now.
@@ -173,6 +176,9 @@
   // The value we're going to use for goal.run etc.
   const uint32_t run_value_;
 
+  // flag passed to action in order to have differing types
+  const ParamType params_;
+
   // The old value for running that we may have seen. If we see any value other
   // than this or run_value_, somebody else got in the way and we're done. 0 if
   // there was nothing there to start with. Only valid after sent_started_
@@ -282,6 +288,7 @@
   if (goal_) {
     LOG(INFO, "Starting action %" PRIx32 "\n", run_value_);
     goal_->run = run_value_;
+    goal_->params = params_;
     sent_started_ = true;
     if (!goal_.Send()) {
       LOG(ERROR, "sending goal for action %" PRIx32 " failed\n", run_value_);
diff --git a/aos/common/actions/actions.q b/aos/common/actions/actions.q
index 8950dd1..8b75ee7 100644
--- a/aos/common/actions/actions.q
+++ b/aos/common/actions/actions.q
@@ -24,6 +24,9 @@
   // The unique value to put into status.running while running this instance or
   // 0 to cancel.
   uint32_t run;
+  // Default parameter.  The more useful thing to do would be to define your own
+  // goal type to change param to a useful structure.
+  double param;
 };
 
 interface ActionQueueGroup {
diff --git a/aos/common/actions/actor.h b/aos/common/actions/actor.h
index b64051a..2193ea1 100644
--- a/aos/common/actions/actor.h
+++ b/aos/common/actions/actor.h
@@ -17,12 +17,17 @@
 template <class T>
 class ActorBase {
  public:
+  typedef typename std::remove_reference<decltype(
+      *(static_cast<T*>(nullptr)->goal.MakeMessage().get()))>::type GoalType;
+  typedef typename std::remove_reference<
+      decltype(static_cast<GoalType*>(nullptr)->params)>::type ParamType;
+
   ActorBase(T* acq) : action_q_(acq) {}
 
   // Will return true if finished or asked to cancel.
   // Will return false if it failed accomplish its goal
   // due to a problem with the system.
-  virtual bool RunAction() = 0;
+  virtual bool RunAction(const ParamType& params) = 0;
 
   // Runs action while enabled.
   void Run();
@@ -110,7 +115,7 @@
            .Send()) {
     LOG(ERROR, "Failed to send the status.\n");
   }
-  abort_ = !RunAction();
+  abort_ = !RunAction(action_q_->goal->params);
   LOG(INFO, "Done with action %" PRIx32 "\n", running_id);
 
   // If we have a new one to run, we shouldn't say we're stopped in between.
diff --git a/aos/common/actions/test_action.q b/aos/common/actions/test_action.q
index c46e182..3451c04 100644
--- a/aos/common/actions/test_action.q
+++ b/aos/common/actions/test_action.q
@@ -7,7 +7,24 @@
 
   message Goal {
     uint32_t run;
-    double test_value;
+    uint32_t params;
+  };
+
+  queue Goal goal;
+  queue aos.common.actions.Status status;
+};
+
+struct MyParams {
+  double param1;
+  int32_t param2;
+};
+
+queue_group TestAction2QueueGroup {
+  implements aos.common.actions.ActionQueueGroup;
+
+  message Goal {
+    uint32_t run;
+    MyParams params;
   };
 
   queue Goal goal;
@@ -15,3 +32,4 @@
 };
 
 queue_group TestActionQueueGroup test_action;
+queue_group TestAction2QueueGroup test_action2;