#include "precompiled_unittests_engine.h" #include "engine/tapes/clipplayers/TapeReferenceClipPlayer.h" #include "engine/tapes/clips/TapeReferenceClip.h" #include "../tape/MockTape.h" namespace ITF { //custom warning #define JOIN_AS_TEXT( X, Y ) DO_JOIN_AS_TEXT( X, Y ) #define DO_JOIN_AS_TEXT( X, Y ) X"("#Y")" #define __LOC__ JOIN_AS_TEXT(__FILE__,__LINE__) // gtest & gmock use namespace testing using namespace testing; class MockTapeReferenceClip : public TapeReferenceClip { public: void setStartTime(TapeFrame_t _time) {m_startTime = _time;} void setDuration(TapeFrame_t _time) {m_duration = _time;} void setLoopingType(LoopingType _loop) {m_loop = _loop;} }; class MockTapeReferenceClipPlayer : public TapeReferenceClipPlayer { public: MockTapeReferenceClipPlayer(const Clip* _clip) : TapeReferenceClipPlayer(_clip) {} void setTapePlayer(TapePlayer* _tapePlayer) { m_tapePlayer = _tapePlayer; m_tape = _tapePlayer->getTape(); } }; class TestTapeReferenceClipPlayerFixture : public ::testing::Test { public: TapePlayer* getTapePlayer() {return m_parentTapePlayer;} MockClipPlayer* getMockClipPlayer() {return m_mockClipPlayer;} void setLoopingType(LoopingType _loopingType) { ITF_VECTOR clipPlayers; m_parentTapePlayer->getClipPlayerByType(TapeReferenceClipPlayer_CRC, clipPlayers); for (u32 i = 0; i < clipPlayers.size(); i++) { MockTapeReferenceClipPlayer* clipPlayer = static_cast(clipPlayers[i]); MockTapeReferenceClip* clip = static_cast(const_cast(clipPlayers[i]->getClip())); clip->setLoopingType(_loopingType); clip->setDuration(clipPlayer->getTapePlayer().getTape()->getDuration()); } } void forceSeamlessLooping() { static_cast(const_cast(getMockClipPlayer()->getClip()))->setStartTime(0); Tape_PrivateMembersAccessor parent(*const_cast(m_parentTapePlayer->getTape())); parent.onSerializeLoad(); for (u32 i = 0; i < m_childrenPlayers.size(); i++) { Tape_PrivateMembersAccessor childrenAccessor (*const_cast(m_childrenPlayers[i]->getTape())); childrenAccessor.onSerializeLoad(); } } static const TapeFrame_t s_subTapeOffset = 5; FTapeFrame_t s_dt; protected: virtual void SetUp() override { s_dt = 0.16; TapePlayer* parentTapePlayer = createTapePlayer(0); TapePlayer* childTapePlayer = createTapePlayer(1); MockTapeReferenceClip* mockClip = new MockTapeReferenceClip(); MockTapeReferenceClipPlayer* mockClipPlayer = new MockTapeReferenceClipPlayer(mockClip); mockClip->setStartTime(s_subTapeOffset); mockClip->setDuration(childTapePlayer->getTape()->getDuration()); mockClipPlayer->setTapePlayer(childTapePlayer); addClipToTapePlayer(parentTapePlayer, mockClipPlayer, mockClip); m_mockClipPlayer = (MockClipPlayer*)childTapePlayer->getClipPlayer(0); m_parentTapePlayer = parentTapePlayer; m_childrenPlayers.push_back(childTapePlayer); // request tape player start m_parentTapePlayer->play(); m_parentTapePlayer->update(0.f); Mock::VerifyAndClearExpectations(&mockClipPlayer); } virtual void TearDown() override { for (u32 i = 0; i < m_childrenPlayers.size(); i++) { deleteTapePlayer(m_childrenPlayers[i]); } m_childrenPlayers.clear(); deleteTapePlayer(m_parentTapePlayer); m_parentTapePlayer = nullptr; } private: MockClipPlayer* m_mockClipPlayer; TapePlayer* m_parentTapePlayer; ITF_VECTOR m_childrenPlayers; }; TEST_F(TestTapeReferenceClipPlayerFixture, test_subClipTakesOffsetIntoAccount) { FTapeFrame_t time = 0.f; // the subtape is not started yet, the MockClip shouldn't be called { getMockClipPlayer()->expectNoCallSequence(); for (time = 0.0; time < s_subTapeOffset; time += s_dt) { getTapePlayer()->update(time); } EXPECT_EQ(bfalse, getMockClipPlayer()->isAlive()); EXPECT_EQ(btrue, getTapePlayer()->isPlaying()); Mock::VerifyAndClearExpectations(getMockClipPlayer()); } { // we are now updating the subtape, the MockClip should be called getMockClipPlayer()->expectBasicCallSequence(); getMockClipPlayer()->expectCallToUpdate(MockClipPlayer::Increase, __LOC__); while (getTapePlayer()->isPlaying()) { getTapePlayer()->update(time); time += s_dt; } FTapeFrame_t endTime = s_subTapeOffset + getMockClipPlayer()->getClip()->getEndTime(); EXPECT_EQ(bfalse, getMockClipPlayer()->isAlive()); EXPECT_EQ(bfalse, getTapePlayer()->isPlaying()); EXPECT_LE(endTime, time); EXPECT_GE(endTime + 2 * s_dt, time); Mock::VerifyAndClearExpectations(getMockClipPlayer()); } } TEST_F(TestTapeReferenceClipPlayerFixture, test_tapeRefPlayedInReverse) { setLoopingType(LoopingType_Reverse); getMockClipPlayer()->expectBasicCallSequence(); getMockClipPlayer()->expectCallToUpdate(MockClipPlayer::Decrease, __LOC__); FTapeFrame_t time = 0.f; while (getTapePlayer()->isPlaying()) { getTapePlayer()->update(time); time += s_dt; } EXPECT_EQ(bfalse, getMockClipPlayer()->isAlive()); EXPECT_EQ(bfalse, getTapePlayer()->isPlaying()); } TEST_F(TestTapeReferenceClipPlayerFixture, test_tapeRefPlayedInPingPong) { setLoopingType(LoopingType_PingPong); getMockClipPlayer()->expectBasicCallSequence(); FTapeFrame_t time = 0.f; FTapeFrame_t mockTimeBegin = s_subTapeOffset + getMockClipPlayer()->getClip()->getStartTime(); FTapeFrame_t mockTimeEnd = s_subTapeOffset + getMockClipPlayer()->getClip()->getEndTime(); FTapeFrame_t mockTimeDuration = getMockClipPlayer()->getClip()->getDuration(); // ping { getMockClipPlayer()->expectCallToUpdate(MockClipPlayer::Increase, __LOC__); for (time = mockTimeBegin; time < mockTimeEnd; time += s_dt) { getTapePlayer()->update(time); } } // pong { getMockClipPlayer()->expectCallToUpdate(MockClipPlayer::Decrease, __LOC__); for (time = mockTimeEnd; time < mockTimeEnd + mockTimeDuration; time += s_dt) { getTapePlayer()->update(time); } } } TEST_F(TestTapeReferenceClipPlayerFixture, test_tapeRefPlayedInPingPongInfinite) { setLoopingType(LoopingType_PingPongInfinite); forceSeamlessLooping(); getMockClipPlayer()->expectInfiniteUpdateSequence(); FTapeFrame_t time = 0.f; FTapeFrame_t mockTimeBegin = s_subTapeOffset + getMockClipPlayer()->getClip()->getStartTime(); FTapeFrame_t mockTimeEnd = s_subTapeOffset + getMockClipPlayer()->getClip()->getEndTime(); FTapeFrame_t mockTimeDuration = getMockClipPlayer()->getClip()->getDuration(); for (u32 i = 0; i < 10; i++) // ping pong ping pong ping pong... { // ping { getMockClipPlayer()->expectCallToUpdate(MockClipPlayer::Increase, __LOC__); for (time = mockTimeBegin; time < mockTimeEnd; time += s_dt) { getTapePlayer()->update(time); } } // pong { getMockClipPlayer()->expectCallToUpdate(MockClipPlayer::Decrease, __LOC__); for (time = mockTimeEnd; time < mockTimeEnd + mockTimeDuration; time += s_dt) { getTapePlayer()->update(time); } } mockTimeBegin = time; mockTimeEnd += mockTimeDuration * 2; } } TEST_F(TestTapeReferenceClipPlayerFixture, test_tapeRefPlayedInLoopInfinite) { setLoopingType(LoopingType_Infinite); forceSeamlessLooping(); getMockClipPlayer()->expectInfiniteUpdateSequence(); FTapeFrame_t mockTimeBegin = s_subTapeOffset + getMockClipPlayer()->getClip()->getStartTime(); FTapeFrame_t mockTimeEnd = s_subTapeOffset + getMockClipPlayer()->getClip()->getEndTime(); FTapeFrame_t mockTimeDuration = getMockClipPlayer()->getClip()->getDuration(); FTapeFrame_t time = 0.f; for (u32 i = 0; i < 10; i++) // ping ping ping ping ping... { // ping { getMockClipPlayer()->expectCallToUpdate(MockClipPlayer::Increase, __LOC__); for (time = mockTimeBegin; time < mockTimeEnd; time += s_dt) { getTapePlayer()->update(time); } } mockTimeBegin = time; mockTimeEnd += mockTimeDuration; } } }