CCSchedulerStateMachineTest.cpp [plain text]
#include "config.h"
#include "cc/CCSchedulerStateMachine.h"
#include <gtest/gtest.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>
using namespace WTF;
using namespace WebCore;
namespace {
const CCSchedulerStateMachine::CommitState allCommitStates[] = {
CCSchedulerStateMachine::COMMIT_STATE_IDLE,
CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES,
CCSchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
};
class StateMachine : public CCSchedulerStateMachine {
public:
void setCommitState(CommitState cs) { m_commitState = cs; }
CommitState commitState() const { return m_commitState; }
void setNeedsCommit(bool b) { m_needsCommit = b; }
bool needsCommit() const { return m_needsCommit; }
void setNeedsForcedCommit(bool b) { m_needsForcedCommit = b; }
bool needsForcedCommit() const { return m_needsForcedCommit; }
void setNeedsRedraw(bool b) { m_needsRedraw = b; }
bool needsRedraw() const { return m_needsRedraw; }
void setNeedsForcedRedraw(bool b) { m_needsForcedRedraw = b; }
bool needsForcedRedraw() const { return m_needsForcedRedraw; }
bool canDraw() const { return m_canDraw; }
bool insideVSync() const { return m_insideVSync; }
bool visible() const { return m_visible; }
void setUpdateMoreResourcesPending(bool b) { m_updateMoreResourcesPending = b; }
bool updateMoreResourcesPending() const { return m_updateMoreResourcesPending; }
};
TEST(CCSchedulerStateMachineTest, TestNextActionBeginsFrameIfNeeded)
{
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_IDLE);
state.setCanBeginFrame(true);
state.setNeedsRedraw(false);
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
EXPECT_FALSE(state.vsyncCallbackNeeded());
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
EXPECT_FALSE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_IDLE);
state.setNeedsRedraw(false);
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
EXPECT_FALSE(state.vsyncCallbackNeeded());
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
EXPECT_FALSE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_IDLE);
state.setCanBeginFrame(true);
state.setNeedsRedraw(false);
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
EXPECT_FALSE(state.vsyncCallbackNeeded());
}
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, state.commitState());
EXPECT_FALSE(state.needsCommit());
EXPECT_FALSE(state.vsyncCallbackNeeded());
}
}
TEST(CCSchedulerStateMachineTest, TestSetForcedRedrawDoesNotSetsNormalRedraw)
{
CCSchedulerStateMachine state;
state.setNeedsForcedRedraw();
EXPECT_FALSE(state.redrawPending());
EXPECT_TRUE(state.vsyncCallbackNeeded());
}
TEST(CCSchedulerStateMachineTest, TestFailedDrawSetsNeedsCommitAndDoesNotDrawAgain)
{
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsRedraw();
EXPECT_TRUE(state.redrawPending());
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
EXPECT_FALSE(state.redrawPending());
EXPECT_FALSE(state.commitPending());
state.didDrawIfPossibleCompleted(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_TRUE(state.redrawPending());
EXPECT_TRUE(state.commitPending());
}
TEST(CCSchedulerStateMachineTest, TestSetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw)
{
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsRedraw();
EXPECT_TRUE(state.redrawPending());
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
EXPECT_FALSE(state.redrawPending());
EXPECT_FALSE(state.commitPending());
state.setNeedsRedraw();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didDrawIfPossibleCompleted(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
EXPECT_TRUE(state.redrawPending());
}
TEST(CCSchedulerStateMachineTest, TestCommitAfterFailedDrawAllowsDrawInSameFrame)
{
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_TRUE(state.commitPending());
state.setNeedsRedraw();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
EXPECT_TRUE(state.redrawPending());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didDrawIfPossibleCompleted(false);
EXPECT_TRUE(state.redrawPending());
EXPECT_TRUE(state.commitPending());
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
EXPECT_TRUE(state.redrawPending());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestCommitAfterFailedAndSuccessfulDrawDoesNotAllowDrawInSameFrame)
{
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_TRUE(state.commitPending());
state.setNeedsRedraw();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
EXPECT_TRUE(state.redrawPending());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didDrawIfPossibleCompleted(false);
EXPECT_TRUE(state.redrawPending());
EXPECT_TRUE(state.commitPending());
state.setNeedsForcedRedraw();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_FORCED, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_FORCED);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
EXPECT_FALSE(state.redrawPending());
EXPECT_TRUE(state.commitPending());
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
EXPECT_TRUE(state.redrawPending());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestFailedDrawIsRetriedNextVSync)
{
CCSchedulerStateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsRedraw();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
EXPECT_TRUE(state.redrawPending());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didDrawIfPossibleCompleted(false);
EXPECT_TRUE(state.redrawPending());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.didLeaveVSync();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame)
{
CCSchedulerStateMachine state;
state.setVisible(true);
state.setNeedsRedraw();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
state.setNeedsRedraw();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didDrawIfPossibleCompleted(true);
state.didLeaveVSync();
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
state.didDrawIfPossibleCompleted(true);
EXPECT_FALSE(state.vsyncCallbackNeeded());
}
TEST(CCSchedulerStateMachineTest, TestNextActionDrawsOnVSync)
{
size_t numCommitStates = sizeof(allCommitStates) / sizeof(CCSchedulerStateMachine::CommitState);
for (size_t i = 0; i < numCommitStates; ++i) {
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
state.setCommitState(allCommitStates[i]);
bool visible = j;
if (!visible) {
state.didEnterVSync();
state.setVisible(false);
} else
state.setVisible(true);
state.setNeedsCommit(false);
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.setNeedsCommit(true);
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
}
for (size_t i = 0; i < numCommitStates; ++i) {
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
state.setCommitState(allCommitStates[i]);
bool forcedDraw = j;
if (!forcedDraw) {
state.didEnterVSync();
state.setNeedsRedraw(true);
state.setVisible(true);
} else
state.setNeedsForcedRedraw(true);
CCSchedulerStateMachine::Action expectedAction;
if (allCommitStates[i] != CCSchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT)
expectedAction = forcedDraw ? CCSchedulerStateMachine::ACTION_DRAW_FORCED : CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE;
else
expectedAction = CCSchedulerStateMachine::ACTION_COMMIT;
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(true);
EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(true);
EXPECT_TRUE(state.vsyncCallbackNeeded());
EXPECT_EQ(expectedAction, state.nextAction());
}
}
}
TEST(CCSchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible)
{
size_t numCommitStates = sizeof(allCommitStates) / sizeof(CCSchedulerStateMachine::CommitState);
for (size_t i = 0; i < numCommitStates; ++i) {
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
state.setCommitState(allCommitStates[i]);
state.setVisible(false);
state.setNeedsRedraw(true);
state.setNeedsForcedRedraw(false);
if (j == 1)
state.didEnterVSync();
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(false);
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.setNeedsCommit(false);
state.setUpdateMoreResourcesPending(true);
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(false);
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.setNeedsCommit(true);
state.setUpdateMoreResourcesPending(true);
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
}
}
TEST(CCSchedulerStateMachineTest, TestCanRedraw_StopsDraw)
{
size_t numCommitStates = sizeof(allCommitStates) / sizeof(CCSchedulerStateMachine::CommitState);
for (size_t i = 0; i < numCommitStates; ++i) {
for (unsigned j = 0; j < 2; ++j) {
StateMachine state;
state.setCommitState(allCommitStates[i]);
state.setVisible(false);
state.setNeedsRedraw(true);
state.setNeedsForcedRedraw(false);
if (j == 1)
state.didEnterVSync();
state.setCanDraw(false);
EXPECT_NE(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
}
}
}
TEST(CCSchedulerStateMachineTest, TestCanRedrawWithWaitingForFirstDrawMakesProgress)
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
state.setCanBeginFrame(true);
state.setNeedsCommit(true);
state.setNeedsRedraw(true);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
state.setCanDraw(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestUpdates_NoRedraw_OneRoundOfUpdates)
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES);
state.setNeedsRedraw(false);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginUpdateMoreResourcesComplete(false);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestUpdates_NoRedraw_TwoRoundsOfUpdates)
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES);
state.setNeedsRedraw(false);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginUpdateMoreResourcesComplete(true);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.beginUpdateMoreResourcesComplete(false);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestVSyncNeededWhenUpdatesPendingButInvisible)
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES);
state.setNeedsRedraw(false);
state.setVisible(false);
state.setUpdateMoreResourcesPending(true);
EXPECT_TRUE(state.vsyncCallbackNeeded());
state.setUpdateMoreResourcesPending(false);
EXPECT_TRUE(state.vsyncCallbackNeeded());
}
TEST(CCSchedulerStateMachineTest, TestUpdates_WithRedraw_OneRoundOfUpdates)
{
StateMachine state;
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES);
state.setNeedsRedraw(true);
state.setUpdateMoreResourcesPending(false);
state.setVisible(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
state.didDrawIfPossibleCompleted(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didLeaveVSync();
state.beginUpdateMoreResourcesComplete(true);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.didEnterVSync();
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.didLeaveVSync();
state.beginUpdateMoreResourcesComplete(false);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestSetNeedsCommitIsNotLost)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setNeedsCommit(true);
state.setVisible(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, state.commitState());
state.setNeedsCommit(true);
EXPECT_TRUE(state.needsCommit());
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, state.commitState());
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, state.commitState());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
state.didDrawIfPossibleCompleted(true);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestFullCycle)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, state.commitState());
EXPECT_FALSE(state.needsCommit());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_IDLE, state.commitState());
EXPECT_TRUE(state.needsRedraw());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
state.didDrawIfPossibleCompleted(true);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_IDLE, state.commitState());
EXPECT_FALSE(state.needsRedraw());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, state.commitState());
EXPECT_FALSE(state.needsCommit());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, state.commitState());
EXPECT_TRUE(state.needsRedraw());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
state.didDrawIfPossibleCompleted(true);
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_IDLE, state.commitState());
EXPECT_FALSE(state.needsRedraw());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestRequestCommitInvisible)
{
StateMachine state;
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestGoesInvisibleMidCommit)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_FRAME);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, state.commitState());
EXPECT_FALSE(state.needsCommit());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.setVisible(false);
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_UPDATING_RESOURCES, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES);
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(CCSchedulerStateMachine::ACTION_COMMIT);
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, state.commitState());
EXPECT_TRUE(state.needsRedraw());
EXPECT_FALSE(state.needsCommit());
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestContextLostWhenCompletelyIdle)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.didLoseContext();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didRecreateContext();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestContextLostWhenIdleAndCommitRequestedWhileRecreating)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.didLoseContext();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.didRecreateContext();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(state.nextAction());
state.setNeedsRedraw(true);
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.setCanDraw(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.setCanDraw(true);
state.didLeaveVSync();
}
TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgress)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(state.nextAction());
state.setNeedsRedraw(true);
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(state.nextAction());
state.didLeaveVSync();
state.didLoseContext();
state.setNeedsRedraw(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION, state.nextAction());
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestContextLostWhileCommitInProgressAndAnotherCommitRequested)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
state.updateState(state.nextAction());
state.setNeedsRedraw(true);
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(state.nextAction());
state.didLeaveVSync();
state.didLoseContext();
state.setNeedsRedraw(true);
state.setNeedsCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.nextAction());
state.updateState(state.nextAction());
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION, state.nextAction());
state.didLeaveVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost)
{
StateMachine state;
state.setVisible(true);
state.didLoseContext();
state.setNeedsForcedRedraw(true);
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_FORCED, state.nextAction());
state.didLeaveVSync();
state.setNeedsForcedRedraw(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION, state.nextAction());
state.updateState(state.nextAction());
state.setNeedsForcedRedraw(true);
state.didEnterVSync();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_DRAW_FORCED, state.nextAction());
state.didLeaveVSync();
}
TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenInvisibleAndForceCommit)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(false);
state.setNeedsCommit(true);
state.setNeedsForcedCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenCanBeginFrameFalseAndForceCommit)
{
StateMachine state;
state.setVisible(true);
state.setNeedsCommit(true);
state.setNeedsForcedCommit(true);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenCommitInProgress)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(false);
state.setCommitState(CCSchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS);
state.setNeedsCommit(true);
state.setNeedsForcedCommit(true);
state.beginFrameComplete();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_NONE, state.nextAction());
state.beginUpdateMoreResourcesComplete(false);
EXPECT_EQ(CCSchedulerStateMachine::ACTION_COMMIT, state.nextAction());
state.updateState(state.nextAction());
EXPECT_EQ(CCSchedulerStateMachine::COMMIT_STATE_IDLE, state.commitState());
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
TEST(CCSchedulerStateMachineTest, TestBeginFrameWhenContextLost)
{
StateMachine state;
state.setCanBeginFrame(true);
state.setVisible(true);
state.setNeedsCommit(true);
state.setNeedsForcedCommit(true);
state.didLoseContext();
EXPECT_EQ(CCSchedulerStateMachine::ACTION_BEGIN_FRAME, state.nextAction());
}
}