Chromium Code Reviews| Index: ui/chromeos/touch_exploration_controller_unittest.cc |
| diff --git a/ui/chromeos/touch_exploration_controller_unittest.cc b/ui/chromeos/touch_exploration_controller_unittest.cc |
| index 10da4b1f3a7f5a272d86d88d1a10daae2f1d1e22..d2b627d06871ce2c09c54f2e2eb14da4ae432292 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,16 @@ class EventCapturer : public ui::EventHandler { |
| DISALLOW_COPY_AND_ASSIGN(EventCapturer); |
| }; |
| +int Factorial(int n) { |
| + if (n <= 0) |
| + return 0; |
| + if (n == 1) |
| + return 1; |
| + if (n == 2) |
| + return 2; |
| + return n * Factorial(n - 1); |
| +} |
| + |
| } // namespace |
| class TouchExplorationTest : public aura::test::AuraTestBase { |
| @@ -948,4 +959,108 @@ TEST_F(TouchExplorationTest, Passthrough) { |
| EXPECT_TRUE(IsInNoFingersDownState()); |
| } |
| +TEST_F(TouchExplorationTest, AllFingerPermutations) { |
| + SwitchTouchExplorationMode(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++){ |
| + all_events.push_back( |
| + new TouchEvent(ui::ET_TOUCH_PRESSED, |
| + gfx::Point(10 * touch_id + 1, 10 * touch_id + 2), |
|
aboxhall
2014/06/27 22:37:26
Suggestion: you could just have x and y values tha
evy
2014/06/30 17:33:08
Done.
|
| + touch_id, |
| + Now())); |
| + all_events.push_back( |
| + new TouchEvent(ui::ET_TOUCH_MOVED, |
| + gfx::Point(10 * touch_id + 3, 10 * touch_id + 4), |
| + touch_id, |
| + Now())); |
| + all_events.push_back( |
| + new TouchEvent(ui::ET_TOUCH_RELEASED, |
| + gfx::Point(10 * touch_id + 5, 10 * touch_id + 6), |
| + touch_id, |
| + Now())); |
| + } |
| + 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); |
| + // current_factorial starts at factorial(num_events - 1) |
|
aboxhall
2014/06/27 22:37:26
This comment is now out of date.
evy
2014/06/30 17:33:08
Done.
|
| + // and decreases each iteration |
| + int current_num_permutations = num_permutations; |
| + for (int events_left = num_events; events_left > 0; events_left--) { |
| + VLOG(0) << "\nEvents left: " << events_left; |
| + int index = 0; |
| + if (events_left == num_events) { |
| + // This is the first event generated. We divide the number |
| + // of possible permutations by the number of events to choose from |
| + // (which is currently all of them). We then integer divide p by |
| + // this new value to decide which event will be first in this |
| + // permutation. e.g. If there are 4 events and 24 permutations, |
| + // the first 6 permutations will start with the first event. |
| + index = p / (current_num_permutations / events_left); |
|
aboxhall
2014/06/27 22:37:26
Thanks, I actually mostly understand this now! How
evy
2014/06/30 17:33:08
Done. I'm not sure if this is clear enough yet. Ca
|
| + // Now we have one fewer event to deal with. So there are fewer |
| + // permuations to consider for the remaining events. |
| + // e.g. If now there are 3 events left, there were 24 permutations |
| + // but there are now 6 permutations. |
| + // Note that the first 2 permutations of these 6 will start with |
| + // the first of the remaining events. |
| + current_num_permutations /= events_left; |
| + } else if (events_left > 1) { |
| + // The logic here is similar to the case where there are num_events |
| + // left, but we need to adjust the value of p because we are |
| + // working with a smaller number of permutations of the fewer |
| + // events that are remaining. |
| + // e.g. If there are 3 events left, the number of permutations |
| + // should be 6. So we want to adjust p (currently 0 to 23 in the |
| + // big for loop) to get values between 0 and 5. So we do p % 6 |
| + VLOG(0) << "p " << p << " current num " << current_num_permutations; |
| + index = (p % current_num_permutations) / |
| + (current_num_permutations / events_left); |
| + current_num_permutations /= events_left; |
| + } else if (events_left == 1) { |
| + // When there is only one event left to be queued, there is only |
| + // one index available. |
| + index = 0; |
| + } |
| + ui::TouchEvent* next_dispatch = queued_events[index]; |
| + ASSERT_TRUE(next_dispatch != NULL); |
| + EventTestApi test_dispatch(next_dispatch); |
| + test_dispatch.set_time_stamp(Now()); |
| + generator_->Dispatch(next_dispatch); |
| + queued_events.erase(queued_events.begin() + index); |
| + // Note: it is possible to send a touched move event in the state |
| + // SINGLE_TAP_RELEASED or TOUCH_EXPLORE_RELEASED |
| + // because the events are not always generated in a sensical |
| + // order. If there is a LOG(ERROR) for touch moved hit in |
| + // InSingleTapOrTouchExploreReleased, that is fine here. |
| + |
| + // 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; |
| + } |
| + } |
| + AdvanceSimulatedTimePastTapDelay(); |
| + EXPECT_TRUE(IsInNoFingersDownState()); |
| + ClearCapturedEvents(); |
| + } |
| +} |
| + |
| } // namespace ui |