blob: 943ba2ca7827a71a17fd52e3037bb607fdff3d84 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_
#define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_
#include <sstream>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
class Browser;
class FullscreenController;
class FullscreenNotificationObserver;
// Utility definition for mapping enum values to strings in switch statements.
#define ENUM_TO_STRING(enum) case enum: return #enum
// Test fixture used to test Fullscreen Controller through exhaustive sequences
// of events in unit and interactive tests.
//
// Because operating system window managers are too unreliable (they result in
// flakiness at around 1 out of 1000 runs) this fixture is designed to be run
// on testing infrastructure in unit tests mocking out the platforms' behavior.
// To verify that behavior interactive tests exist but are left disabled and
// only run manually when verifying the consistency of the
// FullscreenControllerTestWindow.
class FullscreenControllerStateTest {
public:
// Events names for FullscreenController methods.
enum Event {
TOGGLE_FULLSCREEN, // ToggleBrowserFullscreenMode()
TOGGLE_FULLSCREEN_CHROME, // ToggleBrowserFullscreenWithChrome()
TAB_FULLSCREEN_TRUE, // ToggleFullscreenModeForTab(, true)
TAB_FULLSCREEN_FALSE, // ToggleFullscreenModeForTab(, false)
METRO_SNAP_TRUE, // SetMetroSnapMode(true)
METRO_SNAP_FALSE, // SetMetroSnapMode(false)
BUBBLE_EXIT_LINK, // ExitTabOrBrowserFullscreenToPreviousState()
BUBBLE_ALLOW, // OnAcceptFullscreenPermission()
BUBBLE_DENY, // OnDenyFullscreenPermission()
WINDOW_CHANGE, // ChangeWindowFullscreenState()
NUM_EVENTS,
EVENT_INVALID,
};
// Conceptual states of the Fullscreen Controller, these do not correspond
// to particular implemenation details.
enum State {
// The window is not in fullscreen.
STATE_NORMAL,
// User-initiated fullscreen.
STATE_BROWSER_FULLSCREEN_NO_CHROME,
// Mac User-initiated 'Lion Fullscreen' with browser chrome. OSX 10.7+ only.
STATE_BROWSER_FULLSCREEN_WITH_CHROME,
// Windows 8 Metro Snap mode, which puts the window at 20% screen-width.
// No TO_ state for Metro, as the windows implementation is only reentrant.
STATE_METRO_SNAP,
// HTML5 tab-initiated fullscreen.
STATE_TAB_FULLSCREEN,
// Both tab and browser fullscreen.
STATE_TAB_BROWSER_FULLSCREEN,
// Both tab and browser fullscreen, displayed without chrome, but exits tab
// fullscreen to STATE_BROWSER_FULLSCREEN_WITH_CHROME.
STATE_TAB_BROWSER_FULLSCREEN_CHROME,
// TO_ states are asynchronous states waiting for window state change
// before transitioning to their named state.
STATE_TO_NORMAL,
STATE_TO_BROWSER_FULLSCREEN_NO_CHROME,
STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME,
STATE_TO_TAB_FULLSCREEN,
NUM_STATES,
STATE_INVALID,
};
static const int kMaxStateNameLength = 39;
static const int kMaxEventNameLength = 24;
FullscreenControllerStateTest();
virtual ~FullscreenControllerStateTest();
static const char* GetStateString(State state);
static const char* GetEventString(Event event);
// Returns true if FullscreenController::WindowFullscreenStateChanged()
// will be called and re-enter FullscreenController before
// FullscreenController methods complete.
static bool IsWindowFullscreenStateChangedReentrant();
// Returns true if |state| can be persistent. This is true for all of the
// states without "_TO_" in their name.
static bool IsPersistentState(State state);
// Causes Fullscreen Controller to transition to an arbitrary state.
void TransitionToState(State state);
// Makes one state change to approach |destination_state| via shortest path.
// Returns true if a state change is made.
// Repeated calls are needed to reach the destination.
bool TransitionAStepTowardState(State destination_state);
// Calls FullscreenController::ChangeWindowFullscreenState if needed because
// a mock BrowserWindow is being used.
virtual void ChangeWindowFullscreenState() {}
// Returns a description of the window's state, may return NULL.
// FullscreenControllerStateTest owns the returned pointer.
virtual const char* GetWindowStateString();
// Causes the |event| to occur and return true on success.
virtual bool InvokeEvent(Event event);
// Checks that window state matches the expected controller state.
virtual void VerifyWindowState();
// Wait for NOTIFICATION_FULLSCREEN_CHANGED if a notification should have been
// sent in transitioning to |state_| from the previous persistent state.
void MaybeWaitForNotification();
// Tests all states with all permutations of multiple events to detect
// lingering state issues that would bleed over to other states.
// I.E. for each state test all combinations of events E1, E2, E3.
//
// This produces coverage for event sequences that may happen normally but
// would not be exposed by traversing to each state via TransitionToState().
// TransitionToState() always takes the same path even when multiple paths
// exist.
void TestTransitionsForEachState();
// Log transition_table_ to a string for debugging.
std::string GetTransitionTableAsString() const;
// Log state_transitions_ to a string for debugging.
std::string GetStateTransitionsAsString() const;
protected:
// Set of enumerations (created with a helper macro) for _FALSE, _TRUE, and
// _NO_EXPECTATION values to be passed to VerifyWindowStateExpectations().
#define EXPECTATION_ENUM(enum_name, enum_prefix) \
enum enum_name { \
enum_prefix##_FALSE, \
enum_prefix##_TRUE, \
enum_prefix##_NO_EXPECTATION \
}
EXPECTATION_ENUM(FullscreenWithChromeExpectation, FULLSCREEN_WITH_CHROME);
EXPECTATION_ENUM(FullscreenWithoutChromeExpectation,
FULLSCREEN_WITHOUT_CHROME);
EXPECTATION_ENUM(FullscreenForBrowserExpectation, FULLSCREEN_FOR_BROWSER);
EXPECTATION_ENUM(FullscreenForTabExpectation, FULLSCREEN_FOR_TAB);
EXPECTATION_ENUM(InMetroSnapExpectation, IN_METRO_SNAP);
// Generated information about the transitions between states.
struct StateTransitionInfo {
StateTransitionInfo()
: event(EVENT_INVALID),
state(STATE_INVALID),
distance(NUM_STATES) {}
Event event; // The |Event| that will cause the state transition.
State state; // The adjacent |State| transitioned to; not the final state.
int distance; // Steps to final state. NUM_STATES represents unknown.
};
// Returns next transition info for shortest path from source to destination.
StateTransitionInfo NextTransitionInShortestPath(State source,
State destination,
int search_limit);
// Returns a detailed log of what FullscreenControllerStateTest has done
// up to this point, to be reported when tests fail.
std::string GetAndClearDebugLog();
// Returns true if the |state| & |event| pair should be skipped.
virtual bool ShouldSkipStateAndEventPair(State state, Event event);
// Returns true if a test should be skipped entirely, e.g. due to platform.
virtual bool ShouldSkipTest(State state, Event event);
// Runs one test of transitioning to a state and invoking an event.
virtual void TestStateAndEvent(State state, Event event);
// Checks that window state matches the expected controller state.
virtual void VerifyWindowStateExpectations(
FullscreenWithChromeExpectation fullscreen_with_chrome,
FullscreenWithoutChromeExpectation fullscreen_without_chrome,
FullscreenForBrowserExpectation fullscreen_for_browser,
FullscreenForTabExpectation fullscreen_for_tab,
InMetroSnapExpectation in_metro_snap);
virtual Browser* GetBrowser() = 0;
FullscreenController* GetFullscreenController();
// The state the FullscreenController is expected to be in.
State state() const { return state_; }
private:
// The state the FullscreenController is expected to be in.
State state_;
// The state when the previous NOTIFICATION_FULLSCREEN_CHANGED notification
// was received.
State last_notification_received_state_;
// Listens for the NOTIFICATION_FULLSCREEN_CHANGED notification.
scoped_ptr<FullscreenNotificationObserver> fullscreen_notification_observer_;
// Human defined |State| that results given each [state][event] pair.
State transition_table_[NUM_STATES][NUM_EVENTS];
// Generated information about the transitions between states [from][to].
// View generated data with: out/Release/unit_tests
// --gtest_filter="FullscreenController*DebugLogStateTables"
// --gtest_also_run_disabled_tests
StateTransitionInfo state_transitions_[NUM_STATES][NUM_STATES];
// Log of operations reported on errors via GetAndClearDebugLog().
std::ostringstream debugging_log_;
DISALLOW_COPY_AND_ASSIGN(FullscreenControllerStateTest);
};
#endif // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_