blob: 9a882cb24a75d46dfac97f32d6d4004f9adf3ae4 [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
#include <gtest/gtest.h>
#include <string>
#include <process/future.hpp>
#include <process/gtest.hpp>
#include <process/state_machine.hpp>
#include <stout/gtest.hpp>
#include <stout/try.hpp>
using process::Failure;
using process::Future;
using process::Promise;
using process::StateMachine;
using std::string;
enum class State
{
INITIAL,
STARTING,
RUNNING,
STOPPING,
STOPPED,
TERMINAL,
};
TEST(StateMachineTest, Transition)
{
StateMachine<State> state(State::INITIAL);
Try<int> i = state.transition<State::INITIAL, State::STARTING>(
[]() {
return 42;
});
EXPECT_SOME_EQ(42, i);
Try<Nothing> error = state.transition<State::INITIAL, State::STARTING>();
EXPECT_ERROR(error);
Try<Try<int>> t = state.transition<State::STARTING, State::RUNNING>(
[]() -> Try<int> {
return 42;
});
ASSERT_SOME(t);
EXPECT_SOME_EQ(42, t.get());
error = state.transition<State::STARTING, State::RUNNING>();
EXPECT_ERROR(error);
t = state.transition<State::RUNNING, State::STOPPING>(
[]() -> Try<int> {
return Error("Error");
});
ASSERT_SOME(t);
ASSERT_ERROR(t.get());
EXPECT_EQ("Error", t->error());
error = state.transition<State::RUNNING, State::STOPPING>();
EXPECT_ERROR(error);
Promise<int> promise;
Try<Future<int>> f = state.transition<State::STOPPING, State::STOPPED>(
[&]() -> Future<int> {
return promise.future();
});
ASSERT_SOME(f);
EXPECT_TRUE(f->isPending());
promise.set(42);
AWAIT_EXPECT_EQ(42, f.get());
error = state.transition<State::STOPPING, State::STOPPED>();
EXPECT_ERROR(error);
f = state.transition<State::STOPPED, State::TERMINAL>(
[&]() -> Future<int> {
return Failure("Failure");
});
ASSERT_SOME(f);
ASSERT_TRUE(f->isFailed());
EXPECT_EQ("Failure", f->failure());
}
TEST(StateMachineTest, Is)
{
StateMachine<State> state(State::STARTING);
EXPECT_TRUE(state.is<State::STARTING>());
state.transition<State::STARTING, State::RUNNING>();
EXPECT_TRUE(state.is<State::RUNNING>());
}
TEST(StateMachineTest, When)
{
StateMachine<State> state(State::STARTING);
AWAIT_READY(state.when<State::STARTING>());
Future<Nothing> f = state.when<State::RUNNING>();
EXPECT_TRUE(f.isPending());
state.transition<State::STARTING, State::RUNNING>();
AWAIT_READY(f);
}