// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>
#include <gtest/gtest.h>
#include "update_engine/action.h"
#include "update_engine/action_processor.h"

using std::string;

namespace chromeos_update_engine {

using chromeos_update_engine::ActionPipe;

class ActionTestAction;

template<>
class ActionTraits<ActionTestAction> {
 public:
  typedef string OutputObjectType;
  typedef string InputObjectType;
};

// This is a simple Action class for testing.
class ActionTestAction : public Action<ActionTestAction> {
 public:
  typedef string InputObjectType;
  typedef string OutputObjectType;
  ActionPipe<string>* in_pipe() { return in_pipe_.get(); }
  ActionPipe<string>* out_pipe() { return out_pipe_.get(); }
  ActionProcessor* processor() { return processor_; }
  void PerformAction() {}
  void CompleteAction() {
    ASSERT_TRUE(processor());
    processor()->ActionComplete(this, kActionCodeSuccess);
  }
  string Type() const { return "ActionTestAction"; }
};

class ActionTest : public ::testing::Test { };

// This test creates two simple Actions and sends a message via an ActionPipe
// from one to the other.
TEST(ActionTest, SimpleTest) {
  ActionTestAction action;

  EXPECT_FALSE(action.in_pipe());
  EXPECT_FALSE(action.out_pipe());
  EXPECT_FALSE(action.processor());
  EXPECT_FALSE(action.IsRunning());

  ActionProcessor action_processor;
  action_processor.EnqueueAction(&action);
  EXPECT_EQ(&action_processor, action.processor());

  action_processor.StartProcessing();
  EXPECT_TRUE(action.IsRunning());
  action.CompleteAction();
  EXPECT_FALSE(action.IsRunning());
}

}  // namespace chromeos_update_engine
