summaryrefslogtreecommitdiffstats
path: root/ui/chromeos
diff options
context:
space:
mode:
authorevy@chromium.org <evy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-03 06:43:15 +0000
committerevy@chromium.org <evy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-03 06:43:15 +0000
commitb3e92dae88ed3434902858ac8df9a5af61a9663a (patch)
treeb0a03205e09d1e71c6279b4a1729f031a2bb73e9 /ui/chromeos
parent97ca375c27fecf3c365b67b080a3b422c3992fe5 (diff)
downloadchromium_src-b3e92dae88ed3434902858ac8df9a5af61a9663a.zip
chromium_src-b3e92dae88ed3434902858ac8df9a5af61a9663a.tar.gz
chromium_src-b3e92dae88ed3434902858ac8df9a5af61a9663a.tar.bz2
Added touch event permutations test to touch_exploration_controller.
All permutations of three fingers pressing, moving, and releasing are now being tested. Fingers that were recorded as pressed during the permutation but not released yet are released, and then there is a check for no fingers down. BUG=388520 Review URL: https://codereview.chromium.org/358693004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@281195 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/chromeos')
-rw-r--r--ui/chromeos/touch_exploration_controller.cc44
-rw-r--r--ui/chromeos/touch_exploration_controller.h7
-rw-r--r--ui/chromeos/touch_exploration_controller_unittest.cc128
3 files changed, 165 insertions, 14 deletions
diff --git a/ui/chromeos/touch_exploration_controller.cc b/ui/chromeos/touch_exploration_controller.cc
index 1a77b97..74dfa5c 100644
--- a/ui/chromeos/touch_exploration_controller.cc
+++ b/ui/chromeos/touch_exploration_controller.cc
@@ -23,7 +23,8 @@ TouchExplorationController::TouchExplorationController(
: root_window_(root_window),
state_(NO_FINGERS_DOWN),
event_handler_for_testing_(NULL),
- prev_state_(NO_FINGERS_DOWN) {
+ prev_state_(NO_FINGERS_DOWN),
+ VLOG_on_(true) {
CHECK(root_window);
root_window->GetHost()->GetEventSource()->AddEventRewriter(this);
}
@@ -39,6 +40,13 @@ void TouchExplorationController::CallTapTimerNowForTesting() {
OnTapTimerFired();
}
+void TouchExplorationController::CallTapTimerNowIfRunningForTesting() {
+ if (tap_timer_.IsRunning()) {
+ tap_timer_.Stop();
+ OnTapTimerFired();
+ }
+}
+
void TouchExplorationController::SetEventHandlerForTesting(
ui::EventHandler* event_handler_for_testing) {
event_handler_for_testing_ = event_handler_for_testing;
@@ -48,14 +56,18 @@ bool TouchExplorationController::IsInNoFingersDownStateForTesting() const {
return state_ == NO_FINGERS_DOWN;
}
+void TouchExplorationController::SuppressVLOGsForTesting(bool suppress) {
+ VLOG_on_ = !suppress;
+}
+
ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
const ui::Event& event,
scoped_ptr<ui::Event>* rewritten_event) {
if (!event.IsTouchEvent()) {
if (event.IsKeyEvent()) {
const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event);
- VLOG(0) << "\nKeyboard event: " << key_event.name() << "\n"
- << " Key code: " << key_event.key_code()
+ VLOG(0) << "\nKeyboard event: " << key_event.name()
+ << "\n Key code: " << key_event.key_code()
<< ", Flags: " << key_event.flags()
<< ", Is char: " << key_event.is_char();
}
@@ -156,7 +168,7 @@ ui::EventRewriteStatus TouchExplorationController::InNoFingersDown(
VLOG_STATE();
return ui::EVENT_REWRITE_DISCARD;
}
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();;
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -196,7 +208,7 @@ ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed(
}
return EVENT_REWRITE_DISCARD;
}
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();;
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -228,8 +240,10 @@ TouchExplorationController::InSingleTapOrTouchExploreReleased(
ResetToNoFingersDown();
}
return ui::EVENT_REWRITE_DISCARD;
+ } else if (type == ui::ET_TOUCH_MOVED){
+ return ui::EVENT_REWRITE_DISCARD;
}
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -255,7 +269,7 @@ ui::EventRewriteStatus TouchExplorationController::InDoubleTapPressed(
} else if (type == ui::ET_TOUCH_MOVED) {
return ui::EVENT_REWRITE_DISCARD;
}
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -286,7 +300,7 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploration(
state_ = TOUCH_EXPLORE_RELEASED;
VLOG_STATE();
} else if (type != ui::ET_TOUCH_MOVED) {
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -296,7 +310,6 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploration(
return ui::EVENT_REWRITE_REWRITTEN;
}
-
ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger(
const ui::TouchEvent& event,
scoped_ptr<ui::Event>* rewritten_event) {
@@ -355,7 +368,7 @@ ui::EventRewriteStatus TouchExplorationController::InTwoToOneFinger(
return ui::EVENT_REWRITE_REWRITTEN;
}
}
- NOTREACHED() << "Unexpected event type received";
+ NOTREACHED() << "Unexpected event type received: " << event.name();
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -366,7 +379,7 @@ ui::EventRewriteStatus TouchExplorationController::InPassthrough(
if (!(type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED ||
type == ui::ET_TOUCH_MOVED || type == ui::ET_TOUCH_PRESSED)) {
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -418,7 +431,7 @@ ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress(
VLOG_STATE();
return ui::EVENT_REWRITE_REWRITTEN;
}
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();
return ui::EVENT_REWRITE_CONTINUE;
}
@@ -428,7 +441,7 @@ ui::EventRewriteStatus TouchExplorationController::InWaitForRelease(
ui::EventType type = event.type();
if (!(type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED ||
type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED)) {
- NOTREACHED() << "Unexpected event type received.";
+ NOTREACHED() << "Unexpected event type received: " << event.name();
return ui::EVENT_REWRITE_CONTINUE;
}
if (current_touch_ids_.size() == 0) {
@@ -500,6 +513,8 @@ void TouchExplorationController::ResetToNoFingersDown() {
}
void TouchExplorationController::VlogState(const char* function_name) {
+ if (!VLOG_on_)
+ return;
if (prev_state_ == state_)
return;
prev_state_ = state_;
@@ -510,6 +525,9 @@ void TouchExplorationController::VlogState(const char* function_name) {
void TouchExplorationController::VlogEvent(const ui::TouchEvent& touch_event,
const char* function_name) {
+ if (!VLOG_on_)
+ return;
+
CHECK(touch_event.IsTouchEvent());
if (prev_event_ != NULL &&
prev_event_->type() == touch_event.type() &&
diff --git a/ui/chromeos/touch_exploration_controller.h b/ui/chromeos/touch_exploration_controller.h
index 100a47a..75db3a73 100644
--- a/ui/chromeos/touch_exploration_controller.h
+++ b/ui/chromeos/touch_exploration_controller.h
@@ -90,8 +90,12 @@ class UI_CHROMEOS_EXPORT TouchExplorationController
virtual ~TouchExplorationController();
void CallTapTimerNowForTesting();
+ void CallTapTimerNowIfRunningForTesting();
void SetEventHandlerForTesting(ui::EventHandler* event_handler_for_testing);
bool IsInNoFingersDownStateForTesting() const;
+ // VLOGs should be suppressed in tests that generate a lot of logs,
+ // for example permutations of nine touch events.
+ void SuppressVLOGsForTesting(bool suppress);
private:
// Overridden from ui::EventRewriter
@@ -250,6 +254,9 @@ class UI_CHROMEOS_EXPORT TouchExplorationController
// A copy of the previous event passed.
scoped_ptr<ui::TouchEvent> prev_event_;
+ // This toggles whether VLOGS are turned on or not.
+ bool VLOG_on_;
+
DISALLOW_COPY_AND_ASSIGN(TouchExplorationController);
};
diff --git a/ui/chromeos/touch_exploration_controller_unittest.cc b/ui/chromeos/touch_exploration_controller_unittest.cc
index 10da4b1..e98ebac 100644
--- a/ui/chromeos/touch_exploration_controller_unittest.cc
+++ b/ui/chromeos/touch_exploration_controller_unittest.cc
@@ -13,6 +13,7 @@
#include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/events/test/events_test_utils.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
@@ -57,6 +58,14 @@ class EventCapturer : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(EventCapturer);
};
+int Factorial(int n) {
+ if (n <= 0)
+ return 0;
+ if (n == 1)
+ return 1;
+ return n * Factorial(n - 1);
+}
+
} // namespace
class TouchExplorationTest : public aura::test::AuraTestBase {
@@ -111,6 +120,15 @@ class TouchExplorationTest : public aura::test::AuraTestBase {
touch_exploration_controller_->CallTapTimerNowForTesting();
}
+ void AdvanceSimulatedTimePastPotentialTapDelay() {
+ simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
+ touch_exploration_controller_->CallTapTimerNowIfRunningForTesting();
+ }
+
+ void SuppressVLOGs(bool suppress) {
+ touch_exploration_controller_->SuppressVLOGsForTesting(suppress);
+ }
+
void SwitchTouchExplorationMode(bool on) {
if (!on && touch_exploration_controller_.get()) {
touch_exploration_controller_.reset();
@@ -841,7 +859,6 @@ TEST_F(TouchExplorationTest, TwoToOneFingerRelaseFirst) {
ClearCapturedEvents();
// Actions before release have already been tested in the previous test.
-
// A release of the first finger should send an event, as the state
// changes to the wait state.
ui::TouchEvent first_touch_release(
@@ -948,4 +965,113 @@ TEST_F(TouchExplorationTest, Passthrough) {
EXPECT_TRUE(IsInNoFingersDownState());
}
+TEST_F(TouchExplorationTest, AllFingerPermutations) {
+ SwitchTouchExplorationMode(true);
+ SuppressVLOGs(true);
+ // We will test all permutations of events from three different fingers
+ // to ensure that we return to NO_FINGERS_DOWN when fingers have been
+ // released.
+ ScopedVector<ui::TouchEvent> all_events;
+ for (int touch_id = 0; touch_id < 3; touch_id++){
+ int x = 10*touch_id + 1;
+ int y = 10*touch_id + 2;
+ all_events.push_back(new TouchEvent(
+ ui::ET_TOUCH_PRESSED, gfx::Point(x++, y++), touch_id, Now()));
+ all_events.push_back(new TouchEvent(
+ ui::ET_TOUCH_MOVED, gfx::Point(x++, y++), touch_id, Now()));
+ all_events.push_back(new TouchEvent(
+ ui::ET_TOUCH_RELEASED, gfx::Point(x, y), touch_id, Now()));
+ }
+
+ // I'm going to explain this algorithm, and use an example in parentheses.
+ // The example will be all permutations of a b c d.
+ // There are four letters and 4! = 24 permutations.
+ const int num_events = all_events.size();
+ const int num_permutations = Factorial(num_events);
+
+ for (int p = 0; p < num_permutations; p++) {
+ std::vector<ui::TouchEvent*> queued_events = all_events.get();
+ std::vector<bool> fingers_pressed(3, false);
+
+ int current_num_permutations = num_permutations;
+ for (int events_left = num_events; events_left > 0; events_left--) {
+ // |p| indexes to each permutation when there are num_permutations
+ // permutations. (e.g. 0 is abcd, 1 is abdc, 2 is acbd, 3 is acdb...)
+ // But how do we find the index for the current number of permutations?
+ // To find the permutation within the part of the sequence we're
+ // currently looking at, we need a number between 0 and
+ // |current_num_permutations| - 1.
+ // (e.g. if we already chose the first letter, there are 3! = 6
+ // options left, so we do p % 6. So |current_permutation| would go
+ // from 0 to 5 and then reset to 0 again, for all combinations of
+ // whichever three letters are remaining, as we loop through the
+ // permutations)
+ int current_permutation = p % current_num_permutations;
+
+ // Since this is is the total number of permutations starting with
+ // this event and including future events, there could be multiple
+ // values of current_permutation that will generate the same event
+ // in this iteration.
+ // (e.g. If we chose 'a' but have b c d to choose from, we choose b when
+ // |current_permutation| = 0, 1 and c when |current_permutation| = 2, 3.
+ // Note that each letter gets two numbers, which is the next
+ // current_num_permutations, 2! for the two letters left.)
+
+ // Branching out from the first event, there are num_permutations
+ // permutations, and each value of |p| is associated with one of these
+ // permutations. However, once the first event is chosen, there
+ // are now |num_events| - 1 events left, so the number of permutations
+ // for the rest of the events changes, and will always be equal to
+ // the factorial of the events_left.
+ // (e.g. There are 3! = 6 permutations that start with 'a', so if we
+ // start with 'a' there will be 6 ways to then choose from b c d.)
+ // So we now set-up for the next iteration by setting
+ // current_num_permutations to the factorial of the next number of
+ // events left.
+ current_num_permutations /= events_left;
+
+ // To figure out what current event we want to choose, we integer
+ // divide the current permutation by the next current_num_permutations.
+ // (e.g. If there are 4 letters a b c d and 24 permutations, we divide
+ // by 24/4 = 6. Values 0 to 5 when divided by 6 equals 0, so the first
+ // 6 permutations start with 'a', and the last 6 will start with 'd'.
+ // Note that there are 6 that start with 'a' because there are 6
+ // permutations for the next three letters that follow 'a'.)
+ int index = current_permutation / current_num_permutations;
+
+ ui::TouchEvent* next_dispatch = queued_events[index];
+ ASSERT_TRUE(next_dispatch != NULL);
+
+ // |next_dispatch| has to be put in this container so that its time
+ // stamp can be changed to this point in the test, when it is being
+ // dispatched..
+ EventTestApi test_dispatch(next_dispatch);
+ test_dispatch.set_time_stamp(Now());
+ generator_->Dispatch(next_dispatch);
+ queued_events.erase(queued_events.begin() + index);
+
+ // Keep track of what fingers have been pressed, to release
+ // only those fingers at the end, so the check for being in
+ // no fingers down can be accurate.
+ if (next_dispatch->type() == ET_TOUCH_PRESSED) {
+ fingers_pressed[next_dispatch->touch_id()] = true;
+ } else if (next_dispatch->type() == ET_TOUCH_RELEASED) {
+ fingers_pressed[next_dispatch->touch_id()] = false;
+ }
+ }
+ ASSERT_EQ(queued_events.size(), 0u);
+
+ // Release fingers recorded as pressed.
+ for(int j = 0; j < int(fingers_pressed.size()); j++){
+ if (fingers_pressed[j] == true) {
+ generator_->ReleaseTouchId(j);
+ fingers_pressed[j] = false;
+ }
+ }
+ AdvanceSimulatedTimePastPotentialTapDelay();
+ EXPECT_TRUE(IsInNoFingersDownState());
+ ClearCapturedEvents();
+ }
+}
+
} // namespace ui