1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_ 6 #define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_ 7 8 #include <sstream> 9 10 #include "base/basictypes.h" 11 #include "base/compiler_specific.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "build/build_config.h" 14 15 class Browser; 16 class FullscreenController; 17 class FullscreenNotificationObserver; 18 19 // Utility definition for mapping enum values to strings in switch statements. 20 #define ENUM_TO_STRING(enum) case enum: return #enum 21 22 // Test fixture used to test Fullscreen Controller through exhaustive sequences 23 // of events in unit and interactive tests. 24 // 25 // Because operating system window managers are too unreliable (they result in 26 // flakiness at around 1 out of 1000 runs) this fixture is designed to be run 27 // on testing infrastructure in unit tests mocking out the platforms' behavior. 28 // To verify that behavior interactive tests exist but are left disabled and 29 // only run manually when verifying the consistency of the 30 // FullscreenControllerTestWindow. 31 class FullscreenControllerStateTest { 32 public: 33 // Events names for FullscreenController methods. 34 enum Event { 35 TOGGLE_FULLSCREEN, // ToggleFullscreenMode() 36 TOGGLE_FULLSCREEN_CHROME, // ToggleFullscreenWithChrome() 37 TAB_FULLSCREEN_TRUE, // ToggleFullscreenModeForTab(, true) 38 TAB_FULLSCREEN_FALSE, // ToggleFullscreenModeForTab(, false) 39 METRO_SNAP_TRUE, // SetMetroSnapMode(true) 40 METRO_SNAP_FALSE, // SetMetroSnapMode(false) 41 BUBBLE_EXIT_LINK, // ExitTabOrBrowserFullscreenToPreviousState() 42 BUBBLE_ALLOW, // OnAcceptFullscreenPermission() 43 BUBBLE_DENY, // OnDenyFullscreenPermission() 44 WINDOW_CHANGE, // ChangeWindowFullscreenState() 45 NUM_EVENTS, 46 EVENT_INVALID, 47 }; 48 49 // Conceptual states of the Fullscreen Controller, these do not correspond 50 // to particular implemenation details. 51 enum State { 52 // The window is not in fullscreen. 53 STATE_NORMAL, 54 // User-initiated fullscreen. 55 STATE_BROWSER_FULLSCREEN_NO_CHROME, 56 // Mac User-initiated 'Lion Fullscreen' with browser chrome. OSX 10.7+ only. 57 STATE_BROWSER_FULLSCREEN_WITH_CHROME, 58 // Windows 8 Metro Snap mode, which puts the window at 20% screen-width. 59 // No TO_ state for Metro, as the windows implementation is only reentrant. 60 STATE_METRO_SNAP, 61 // HTML5 tab-initiated fullscreen. 62 STATE_TAB_FULLSCREEN, 63 // Both tab and browser fullscreen. 64 STATE_TAB_BROWSER_FULLSCREEN, 65 // Both tab and browser fullscreen, displayed without chrome, but exits tab 66 // fullscreen to STATE_BROWSER_FULLSCREEN_WITH_CHROME. 67 STATE_TAB_BROWSER_FULLSCREEN_CHROME, 68 // TO_ states are asynchronous states waiting for window state change 69 // before transitioning to their named state. 70 STATE_TO_NORMAL, 71 STATE_TO_BROWSER_FULLSCREEN_NO_CHROME, 72 STATE_TO_BROWSER_FULLSCREEN_WITH_CHROME, 73 STATE_TO_TAB_FULLSCREEN, 74 NUM_STATES, 75 STATE_INVALID, 76 }; 77 78 static const int kMaxStateNameLength = 39; 79 static const int kMaxEventNameLength = 24; 80 81 FullscreenControllerStateTest(); 82 virtual ~FullscreenControllerStateTest(); 83 84 static const char* GetStateString(State state); 85 static const char* GetEventString(Event event); 86 87 // Returns true if FullscreenController::WindowFullscreenStateChanged() 88 // will be called and re-enter FullscreenController before 89 // FullscreenController methods complete. 90 static bool IsWindowFullscreenStateChangedReentrant(); 91 92 // Returns true if |state| can be persistent. This is true for all of the 93 // states without "_TO_" in their name. 94 static bool IsPersistentState(State state); 95 96 // Causes Fullscreen Controller to transition to an arbitrary state. 97 void TransitionToState(State state); 98 99 // Makes one state change to approach |destination_state| via shortest path. 100 // Returns true if a state change is made. 101 // Repeated calls are needed to reach the destination. 102 bool TransitionAStepTowardState(State destination_state); 103 104 // Calls FullscreenController::ChangeWindowFullscreenState if needed because 105 // a mock BrowserWindow is being used. 106 virtual void ChangeWindowFullscreenState() {} 107 108 // Returns a description of the window's state, may return NULL. 109 // FullscreenControllerStateTest owns the returned pointer. 110 virtual const char* GetWindowStateString(); 111 112 // Causes the |event| to occur and return true on success. 113 virtual bool InvokeEvent(Event event); 114 115 // Checks that window state matches the expected controller state. 116 virtual void VerifyWindowState(); 117 118 // Wait for NOTIFICATION_FULLSCREEN_CHANGED if a notification should have been 119 // sent in transitioning to |state_| from the previous persistent state. 120 void MaybeWaitForNotification(); 121 122 // Tests all states with all permutations of multiple events to detect 123 // lingering state issues that would bleed over to other states. 124 // I.E. for each state test all combinations of events E1, E2, E3. 125 // 126 // This produces coverage for event sequences that may happen normally but 127 // would not be exposed by traversing to each state via TransitionToState(). 128 // TransitionToState() always takes the same path even when multiple paths 129 // exist. 130 void TestTransitionsForEachState(); 131 132 // Log transition_table_ to a string for debugging. 133 std::string GetTransitionTableAsString() const; 134 // Log state_transitions_ to a string for debugging. 135 std::string GetStateTransitionsAsString() const; 136 137 protected: 138 // Set of enumerations (created with a helper macro) for _FALSE, _TRUE, and 139 // _NO_EXPECTATION values to be passed to VerifyWindowStateExpectations(). 140 #define EXPECTATION_ENUM(enum_name, enum_prefix) \ 141 enum enum_name { \ 142 enum_prefix##_FALSE, \ 143 enum_prefix##_TRUE, \ 144 enum_prefix##_NO_EXPECTATION \ 145 } 146 EXPECTATION_ENUM(FullscreenWithChromeExpectation, FULLSCREEN_WITH_CHROME); 147 EXPECTATION_ENUM(FullscreenWithoutChromeExpectation, 148 FULLSCREEN_WITHOUT_CHROME); 149 EXPECTATION_ENUM(FullscreenForBrowserExpectation, FULLSCREEN_FOR_BROWSER); 150 EXPECTATION_ENUM(FullscreenForTabExpectation, FULLSCREEN_FOR_TAB); 151 EXPECTATION_ENUM(InMetroSnapExpectation, IN_METRO_SNAP); 152 153 // Generated information about the transitions between states. 154 struct StateTransitionInfo { 155 StateTransitionInfo() 156 : event(EVENT_INVALID), 157 state(STATE_INVALID), 158 distance(NUM_STATES) {} 159 Event event; // The |Event| that will cause the state transition. 160 State state; // The adjacent |State| transitioned to; not the final state. 161 int distance; // Steps to final state. NUM_STATES represents unknown. 162 }; 163 164 // Returns next transition info for shortest path from source to destination. 165 StateTransitionInfo NextTransitionInShortestPath(State source, 166 State destination, 167 int search_limit); 168 169 // Returns a detailed log of what FullscreenControllerStateTest has done 170 // up to this point, to be reported when tests fail. 171 std::string GetAndClearDebugLog(); 172 173 // Returns true if the |state| & |event| pair should be skipped. 174 virtual bool ShouldSkipStateAndEventPair(State state, Event event); 175 176 // Returns true if a test should be skipped entirely, e.g. due to platform. 177 virtual bool ShouldSkipTest(State state, Event event); 178 179 // Runs one test of transitioning to a state and invoking an event. 180 virtual void TestStateAndEvent(State state, Event event); 181 182 // Checks that window state matches the expected controller state. 183 virtual void VerifyWindowStateExpectations( 184 FullscreenWithChromeExpectation fullscreen_with_chrome, 185 FullscreenWithoutChromeExpectation fullscreen_without_chrome, 186 FullscreenForBrowserExpectation fullscreen_for_browser, 187 FullscreenForTabExpectation fullscreen_for_tab, 188 InMetroSnapExpectation in_metro_snap); 189 190 191 virtual Browser* GetBrowser() = 0; 192 FullscreenController* GetFullscreenController(); 193 194 // The state the FullscreenController is expected to be in. 195 State state() const { return state_; } 196 197 private: 198 // The state the FullscreenController is expected to be in. 199 State state_; 200 201 // The state when the previous NOTIFICATION_FULLSCREEN_CHANGED notification 202 // was received. 203 State last_notification_received_state_; 204 205 // Listens for the NOTIFICATION_FULLSCREEN_CHANGED notification. 206 scoped_ptr<FullscreenNotificationObserver> fullscreen_notification_observer_; 207 208 // Human defined |State| that results given each [state][event] pair. 209 State transition_table_[NUM_STATES][NUM_EVENTS]; 210 211 // Generated information about the transitions between states [from][to]. 212 // View generated data with: out/Release/unit_tests 213 // --gtest_filter="FullscreenController*DebugLogStateTables" 214 // --gtest_also_run_disabled_tests 215 StateTransitionInfo state_transitions_[NUM_STATES][NUM_STATES]; 216 217 // Log of operations reported on errors via GetAndClearDebugLog(). 218 std::ostringstream debugging_log_; 219 220 DISALLOW_COPY_AND_ASSIGN(FullscreenControllerStateTest); 221 }; 222 223 #endif // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_STATE_TEST_H_ 224