1159 lines
No EOL
50 KiB
C++
1159 lines
No EOL
50 KiB
C++
// ----------------------------------------------------------------------------
|
|
// Unit test for the class engine/musicband/Brick
|
|
// ----------------------------------------------------------------------------
|
|
#include "precompiled_unittests_engine.h"
|
|
|
|
#include "engine/musicband/Brick.h"
|
|
#include "musicband/ConductorBrickMock.h"
|
|
|
|
using ::testing::Return;
|
|
using ::testing::AnyNumber;
|
|
using ::testing::_;
|
|
|
|
namespace ITF
|
|
{
|
|
|
|
class Brick_PrivateMembersAccessor
|
|
{
|
|
public:
|
|
Brick_PrivateMembersAccessor(const Brick& _source) : m_source(_source) {}
|
|
|
|
MusicScoreType getMusicScoreType() const { return m_source.m_score; }
|
|
|
|
FBeat computeLocalTime(const MusicScoreTime &_time) const { return m_source.computeLocalTime(_time); }
|
|
bool isActiveAt(const FBeat _localTime) const { return m_source.isActiveAt(_localTime); }
|
|
bool isStartedAt(const FBeat _localTime) const { return m_source.isStartedAt(_localTime); }
|
|
|
|
private:
|
|
const Brick& m_source;
|
|
};
|
|
|
|
ITF_ASSERT_STATIC(Brick::BrickState_Count == 9, "New state added, please check and update unit tests");
|
|
|
|
// test state of the class after the construction
|
|
TEST(Brick, test_Construction)
|
|
{
|
|
// arrange
|
|
BrickDescriptor expectedBrickDescriptor;
|
|
MusicScoreType expectedMusicScoreType(MusicScoreType_Menu);
|
|
Brick::BrickState expectedState(Brick::BrickState_NotCreated);
|
|
ConductorBrick* brickInstance = new ConductorBrickMock();
|
|
|
|
// act
|
|
Brick brick(expectedBrickDescriptor, expectedMusicScoreType, brickInstance);
|
|
Brick_PrivateMembersAccessor testMemberAccessor(brick);
|
|
|
|
// assert
|
|
EXPECT_EQ(expectedBrickDescriptor, brick.getDescriptor());
|
|
EXPECT_EQ(expectedMusicScoreType, testMemberAccessor.getMusicScoreType());
|
|
EXPECT_EQ(expectedState, brick.getState());
|
|
EXPECT_TRUE(brick.containsConductorBrick(brickInstance));
|
|
EXPECT_FALSE(brick.isDestroyable());
|
|
}
|
|
|
|
// Test internal function computeLocalTime
|
|
TEST(Brick, test_computeLocalTime)
|
|
{
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_absoluteStartBeat = 4; // starts at beat 4 in conductor time
|
|
brickDescriptor.m_localStartBeat = 2; // starts at beat 2 in song time
|
|
brickDescriptor.m_duration = 5; // brick duration is 5 beats
|
|
|
|
MusicScoreTime t;
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(3.f); // current metronome beat time
|
|
|
|
// Absolute Beat: 01234567890123
|
|
// Music time: -----MMMMMMMMM // music time starts at absolute beat 5
|
|
// Brick time: ----BBBBB----- // brick (absolute) time starts at beat 4
|
|
// Brick local beat: --012345678901 // brick will play beat 2 content at conductor time 4
|
|
// Current time: -----A--o----- // A - absolute start beat, o - reference local beat
|
|
// Brick local time: --------6-----
|
|
FBeat expectedLocalTime(6.0f);
|
|
|
|
// act / assert
|
|
Brick brick(brickDescriptor, MusicScoreType_Menu, nullptr);
|
|
Brick_PrivateMembersAccessor privateMembersAccessor(brick);
|
|
|
|
EXPECT_EQ(expectedLocalTime.toFloat(), privateMembersAccessor.computeLocalTime(t).toFloat());
|
|
}
|
|
|
|
// Test internal function isActive
|
|
// uses the following timing setup:
|
|
// Absolute Beat: 01234567890123
|
|
// Music time: -----MMMMMMMMM // music time starts at absolute beat 5
|
|
// Brick time: ----BBBBB----- // brick (absolute) time starts at beat 4
|
|
// Brick local beat: --012345678901 // brick will play beat 2 content at conductor time 4
|
|
TEST(Brick, test_isActive)
|
|
{
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_absoluteStartBeat = IBeat(4); // starts at beat 4 in conductor time
|
|
brickDescriptor.m_localStartBeat = IBeat(2); // starts at beat 2 in song time
|
|
brickDescriptor.m_duration = IBeat(5); // brick duration is 5 beats
|
|
brickDescriptor.m_prefetchDuration = IBeat(2); // prefetch will be started 2 beats before start (beat 2 in conductor time)
|
|
// discard will be started 2 beats after end (beat 11 in conductor time)
|
|
|
|
MusicScoreTime t;
|
|
FBeat localBrickTime;
|
|
Brick brick(brickDescriptor, MusicScoreType_Menu, nullptr);
|
|
Brick_PrivateMembersAccessor privateMembersAccessor(brick);
|
|
|
|
// Absolute beat time = 1, expected => inactive
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(-4.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isActiveAt(localBrickTime));
|
|
|
|
// Absolute beat time = 2, expected => active
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(-3.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_TRUE(privateMembersAccessor.isActiveAt(localBrickTime));
|
|
|
|
// Absolute beat time = 4, expected => active
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(-1.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_TRUE(privateMembersAccessor.isActiveAt(localBrickTime));
|
|
|
|
// Absolute beat time = 8, expected => active
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(3.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_TRUE(privateMembersAccessor.isActiveAt(localBrickTime));
|
|
|
|
// Absolute beat time = 10, expected => active
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(5.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_TRUE(privateMembersAccessor.isActiveAt(localBrickTime));
|
|
|
|
// Absolute beat time = 11, expected => inactive
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(6.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isActiveAt(localBrickTime));
|
|
}
|
|
|
|
// Test internal function isStarted
|
|
// uses the following timing setup:
|
|
// Absolute Beat: 01234567890123
|
|
// Music time: -----MMMMMMMMM // music time starts at absolute beat 5
|
|
// Brick time: ----BBBBB----- // brick (absolute) time starts at beat 4
|
|
// Brick local beat: --012345678901 // brick will play beat 2 content at conductor time 4
|
|
TEST(Brick, test_isStarted)
|
|
{
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_absoluteStartBeat = 4; // starts at beat 4 in conductor time
|
|
brickDescriptor.m_localStartBeat = 2; // starts at beat 2 in song time
|
|
brickDescriptor.m_duration = 5; // brick duration is 5 beats
|
|
brickDescriptor.m_prefetchDuration = 2; // prefetch will be started 2 beats before start (beat 2 in conductor time)
|
|
// discard will be started 2 beats after end (beat 11 in conductor time)
|
|
|
|
MusicScoreTime t;
|
|
FBeat localBrickTime;
|
|
Brick brick(brickDescriptor, MusicScoreType_Menu, nullptr);
|
|
Brick_PrivateMembersAccessor privateMembersAccessor(brick);
|
|
|
|
// Absolute beat time = 1, expected => not started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(-4.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
|
|
// Absolute beat time = 2, expected => not started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(-3.f); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
|
|
// Absolute beat time = 3, expected => not started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(-2); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
|
|
// Absolute beat time = 4, expected => started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(-1); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_TRUE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
|
|
// Absolute beat time = 8, expected => started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(3); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_TRUE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
|
|
// Absolute beat time = 9, expected => not started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(4); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
|
|
// Absolute beat time = 10, expected => not started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(5); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
|
|
// Absolute beat time = 11, expected => not started
|
|
t.m_referenceAbsoluteStartBeat = IBeat(5); // local beat time starts at this offset in conductor time
|
|
t.m_referenceLocalBeat = FBeat(6); // current metronome beat time
|
|
localBrickTime = privateMembersAccessor.computeLocalTime(t);
|
|
EXPECT_FALSE(privateMembersAccessor.isStartedAt(localBrickTime));
|
|
}
|
|
|
|
// Test 'cancel prepare' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Canceling -> NotCreated
|
|
TEST(Brick, test_CancelPrepareScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Canceling
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, allowCancel()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, cancelBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Canceling, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Canceling -> NotCreated
|
|
EXPECT_CALL(*brickInstance, isBrickCanceled()).Times(1).WillRepeatedly(Return(true));
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_NotCreated, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
}
|
|
|
|
// Test 'cancel prepare' scenario for the brick which cannot cancel
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Discarding -> NotCreated
|
|
TEST(Brick, test_CancelPrepareScenario_CancelNotAllowed)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Try Canceling => Fails
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, allowCancel()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Discarding
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Discarding -> NotCreated
|
|
EXPECT_CALL(*brickInstance, isBrickDiscarded()).Times(1).WillRepeatedly(Return(true));
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_NotCreated, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
}
|
|
|
|
// Test 'Discard Ready' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Discarding -> NotCreated
|
|
TEST(Brick, test_DiscardReadyScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Discarding
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Discarding -> NotCreated
|
|
EXPECT_CALL(*brickInstance, isBrickDiscarded()).Times(1).WillRepeatedly(Return(true));
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_NotCreated, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
}
|
|
|
|
// Test 'Discard Started' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Ready -> Discarding -> NotCreated
|
|
TEST(Brick, test_DiscardStartedScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 4;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Ready
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, stopBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Discarding
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Discarding -> NotCreated
|
|
EXPECT_CALL(*brickInstance, isBrickDiscarded()).Times(1).WillRepeatedly(Return(true));
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_NotCreated, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
}
|
|
|
|
// Test 'Seek started brick' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Seeking -> Started
|
|
TEST(Brick, test_SeekInStartedBrickScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Seeking
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, seekBrick(_)).Times(1);
|
|
EXPECT_CALL(*brickInstance, isBrickSeekFinished()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
t.m_referenceLocalBeat = FBeat(5);
|
|
brick.seek(t);
|
|
EXPECT_EQ(Brick::BrickState_Seeking, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Seeking -> Started
|
|
EXPECT_CALL(*brickInstance, isBrickSeekFinished()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Seek started brick to discard' scenario
|
|
// (seek to time where the brick is not started anymore)
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Ready -> Discarding
|
|
TEST(Brick, test_SeekInStartedBrickToDiscardScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Ready
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, stopBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
t.m_referenceLocalBeat = FBeat(13);
|
|
brick.seek(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Discarding
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Seek ready brick' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Discarding (-> Preparing -> Ready)
|
|
TEST(Brick, test_SeekInReadyBrickScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Discarding (on seek)
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, isBrickDiscarded()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
t.m_referenceLocalBeat = FBeat(6);
|
|
brick.seek(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Seek preparing cancelable brick' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Canceling (-> Preparing -> Ready)
|
|
TEST(Brick, test_SeekInPreparingBrickScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Canceling (on seek)
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, allowCancel()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, cancelBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, isBrickCanceled()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
t.m_referenceLocalBeat = FBeat(6);
|
|
brick.seek(t);
|
|
EXPECT_EQ(Brick::BrickState_Canceling, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Error during Preparing' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Error -> Discarding (-> NotCreated)
|
|
TEST(Brick, test_ErrorDuringPreparingScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Error
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Error, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Error -> Discarding
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Error while Ready' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Error -> Discarding (-> NotCreated)
|
|
TEST(Brick, test_ErrorWhileReadyScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Error
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Error, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Error -> Discarding
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Error while Started' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Error -> Discarding (-> NotCreated)
|
|
TEST(Brick, test_ErrorWhileStartedScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Error
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Error, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Error -> Discarding
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Error while Seeking' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Seeking -> Error -> Discarding (-> NotCreated)
|
|
TEST(Brick, test_ErrorWhileSeekingScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Seeking
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, seekBrick(_)).Times(1);
|
|
EXPECT_CALL(*brickInstance, isBrickSeekFinished()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
t.m_referenceLocalBeat = FBeat(5);
|
|
brick.seek(t);
|
|
EXPECT_EQ(Brick::BrickState_Seeking, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Seeking -> Error
|
|
EXPECT_CALL(*brickInstance, isBrickSeekFinished()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Error, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Error -> Discarding
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Error at Seek' scenario
|
|
// (error detected when the seek command is issued)
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Error -> Discarding (-> NotCreated)
|
|
TEST(Brick, test_ErrorAtSeekScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Error
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
t.m_referenceLocalBeat = FBeat(5);
|
|
brick.seek(t);
|
|
EXPECT_EQ(Brick::BrickState_Error, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Error -> Discarding
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Starving' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Starving -> Started (-> ...)
|
|
TEST(Brick, test_StarvingScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Starving
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, isBrickStarving()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Starving, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Starving -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, isBrickStarving()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
// Test 'Discard Starving' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Starving -> Started -> Ready -> Discarding -> NotCreated
|
|
TEST(Brick, test_DiscardStarvingScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Starving
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, isBrickStarving()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Starving, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Starving -> Started (because disabled)
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Ready
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, stopBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Discarding
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Discarding -> NotCreated
|
|
EXPECT_CALL(*brickInstance, isBrickDiscarded()).Times(1).WillRepeatedly(Return(true));
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_NotCreated, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
}
|
|
|
|
// Test 'Seek Starving brick' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Starving -> Seeking -> Started
|
|
TEST(Brick, test_SeekInStarvingBrickScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Starving
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, isBrickStarving()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Starving, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Starving -> Seeking
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, seekBrick(_)).Times(1);
|
|
EXPECT_CALL(*brickInstance, isBrickSeekFinished()).Times(1).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
t.m_referenceLocalBeat = FBeat(5);
|
|
brick.seek(t);
|
|
EXPECT_EQ(Brick::BrickState_Seeking, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Seeking -> Started
|
|
EXPECT_CALL(*brickInstance, isBrickSeekFinished()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
|
|
// Test 'Error while Starving' scenario
|
|
// The brick should pass through the following states:
|
|
// NotCreated -> Preparing -> Ready -> Started -> Starving -> Error -> Discarding (-> NotCreated)
|
|
TEST(Brick, test_ErrorWhileStarvingScenario)
|
|
{
|
|
// arrange
|
|
BrickDescriptor brickDescriptor;
|
|
brickDescriptor.m_localStartBeat = 2;
|
|
brickDescriptor.m_prefetchDuration = 2;
|
|
brickDescriptor.m_duration = 10;
|
|
MusicScoreType musicScoreType(MusicScoreType_Menu);
|
|
::testing::StrictMock<ConductorBrickMock>* brickInstance = new ::testing::StrictMock<ConductorBrickMock>();
|
|
|
|
// act / assert
|
|
MusicScoreTime t;
|
|
Brick brick(brickDescriptor, musicScoreType, brickInstance);
|
|
|
|
// NotCreated -> Preparing
|
|
EXPECT_CALL(*brickInstance, prepareBrick(brickDescriptor, musicScoreType, &brick)).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Preparing, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Preparing -> Ready
|
|
EXPECT_CALL(*brickInstance, isBrickReady()).Times(AnyNumber()).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Ready, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Ready -> Started
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, startBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Started, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Started -> Starving
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(AnyNumber()).WillRepeatedly(Return(false));
|
|
EXPECT_CALL(*brickInstance, isBrickStarving()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Starving, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Starving -> Error
|
|
EXPECT_CALL(*brickInstance, brickHasError()).Times(1).WillRepeatedly(Return(true));
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Error, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// Error -> Discarding
|
|
EXPECT_CALL(*brickInstance, discardBrick()).Times(1);
|
|
EXPECT_CALL(*brickInstance, updateBrick(_)).Times(1);
|
|
brick.disable();
|
|
brick.update(t);
|
|
EXPECT_EQ(Brick::BrickState_Discarding, brick.getState());
|
|
::testing::Mock::VerifyAndClear(brickInstance);
|
|
|
|
// ignore the rest of the lifetime...
|
|
}
|
|
|
|
|
|
|
|
} // namespace ITF
|