1/*
2 * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "gtest/gtest.h"
17#define private public
18#define protected public
19
20#include "foundation/osal/utils/util.h"
21#include "scene/player/internal/state_machine.h"
22#include "scene/player/play_executor.h"
23
24namespace OHOS {
25namespace Media {
26namespace Test {
27class PlayExecutorStub : public PlayExecutor {
28public:
29    PlayExecutorStub() noexcept : isLooping_(false), stateMachine_(nullptr)
30    {
31    }
32    bool IsSingleLoop() override
33    {
34        return isLooping_;
35    }
36    void SetLooping(bool looping)
37    {
38        isLooping_ = looping;
39    }
40    void SetStateMachine(const StateMachine* stateMachine)
41    {
42        stateMachine_ = stateMachine;
43    }
44    ErrorCode DoSetSource(const std::shared_ptr<MediaSource>& source) override
45    {
46        return source ? ErrorCode::SUCCESS : ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
47    }
48    ErrorCode DoOnReady() override
49    {
50        return ErrorCode::SUCCESS;
51    }
52    ErrorCode DoOnComplete() override
53    {
54        if (!isLooping_ && stateMachine_) {
55            stateMachine_->SendEventAsync(Intent::STOP);
56        }
57        return ErrorCode::SUCCESS;
58    }
59    ErrorCode DoOnError(ErrorCode) override
60    {
61        return ErrorCode::SUCCESS;
62    }
63
64private:
65    bool isLooping_;
66    const StateMachine* stateMachine_;
67};
68
69PlayExecutorStub g_playExecutorStub;
70
71class TestStateMachine : public ::testing::Test {
72protected:
73    void SetUp() override
74    {
75        g_playExecutorStub.SetStateMachine(&stateMachine);
76        stateMachine.Start();
77    }
78
79    void TearDown() override
80    {
81    }
82
83    static StateMachine stateMachine;
84};
85
86StateMachine TestStateMachine::stateMachine(g_playExecutorStub);
87
88TEST_F(TestStateMachine, test_Idle_state)
89{
90    EXPECT_TRUE(stateMachine.GetCurrentState() == "IdleState");
91}
92
93TEST_F(TestStateMachine, test_set_invalid_source)
94{
95    EXPECT_TRUE(stateMachine.GetCurrentState() == "IdleState");
96    EXPECT_EQ(ErrorCode::ERROR_INVALID_PARAMETER_TYPE, stateMachine.SendEvent(Intent::SET_SOURCE));
97    EXPECT_TRUE(stateMachine.GetCurrentState() == "IdleState");
98}
99
100TEST_F(TestStateMachine, test_set_valid_source)
101{
102    EXPECT_TRUE(stateMachine.GetCurrentState() == "IdleState");
103    auto source = std::make_shared<MediaSource>("FakeUri");
104    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::SET_SOURCE, source));
105    EXPECT_TRUE(stateMachine.GetCurrentState() == "InitState");
106}
107
108TEST_F(TestStateMachine, test_prepare_after_set_source)
109{
110    EXPECT_TRUE(stateMachine.GetCurrentState() == "InitState");
111    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::PREPARE));
112    EXPECT_TRUE(stateMachine.GetCurrentState() == "PreparingState");
113}
114
115TEST_F(TestStateMachine, test_set_notify_error_in_preparing)
116{
117    EXPECT_TRUE(stateMachine.GetCurrentState() == "PreparingState");
118    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::NOTIFY_ERROR));
119    EXPECT_TRUE(stateMachine.GetCurrentState() == "InitState");
120}
121
122TEST_F(TestStateMachine, test_notify_ready)
123{
124    EXPECT_TRUE(stateMachine.GetCurrentState() == "InitState");
125    auto source = std::make_shared<MediaSource>("FakeUri");
126    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::SET_SOURCE, source));
127    EXPECT_TRUE(stateMachine.GetCurrentState() == "InitState");
128    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::PREPARE));
129    EXPECT_TRUE(stateMachine.GetCurrentState() == "PreparingState");
130    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::NOTIFY_READY));
131    EXPECT_TRUE(stateMachine.GetCurrentState() == "ReadyState");
132}
133
134TEST_F(TestStateMachine, test_play_after_ready)
135{
136    EXPECT_TRUE(stateMachine.GetCurrentState() == "ReadyState");
137    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::PLAY));
138    EXPECT_TRUE(stateMachine.GetCurrentState() == "PlayingState");
139}
140
141TEST_F(TestStateMachine, test_pause)
142{
143    EXPECT_TRUE(stateMachine.GetCurrentState() == "PlayingState");
144    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::PAUSE));
145    EXPECT_TRUE(stateMachine.GetCurrentState() == "PauseState");
146}
147
148TEST_F(TestStateMachine, test_play_after_pause)
149{
150    EXPECT_TRUE(stateMachine.GetCurrentState() == "PauseState");
151    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::PLAY));
152    EXPECT_TRUE(stateMachine.GetCurrentState() == "PlayingState");
153}
154
155TEST_F(TestStateMachine, test_play_complete_looping)
156{
157    g_playExecutorStub.SetLooping(true);
158    EXPECT_TRUE(stateMachine.GetCurrentState() == "PlayingState");
159    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::NOTIFY_COMPLETE));
160    EXPECT_TRUE(stateMachine.GetCurrentState() == "PlayingState");
161}
162
163TEST_F(TestStateMachine, test_play_complete_nolooping)
164{
165    g_playExecutorStub.SetLooping(false);
166    EXPECT_TRUE(stateMachine.GetCurrentState() == "PlayingState");
167    EXPECT_EQ(ErrorCode::SUCCESS, stateMachine.SendEvent(Intent::NOTIFY_COMPLETE));
168    OSAL::SleepFor(100);
169    EXPECT_TRUE(stateMachine.GetCurrentState() == "StoppedState");
170}
171} // namespace Test
172} // namespace Media
173} // namespace OHOS