~chasedouglas/grail/work-in-progress

« back to all changes in this revision

Viewing changes to test/x11/atomic-timeout.cpp

  • Committer: Chase Douglas
  • Date: 2012-03-19 16:55:49 UTC
  • mfrom: (199.1.5 gesture-end-fix)
  • Revision ID: chase.douglas@ubuntu.com-20120319165549-n0orytbxe1rd0a3x
Merge fixes for atomic gesture timeout handling and gesture end handling

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 *
 
3
 * grail - Gesture Recognition And Instantiation Library
 
4
 *
 
5
 * Copyright (C) 2012 Canonical Ltd.
 
6
 *
 
7
 * This program is free software: you can redistribute it and/or modify it
 
8
 * under the terms of the GNU General Public License as published by the
 
9
 * Free Software Foundation, either version 3 of the License, or (at your
 
10
 * option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along
 
18
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 *
 
20
 ****************************************************************************/
 
21
 
 
22
/**
 
23
 * @internal
 
24
 * @file Atomic Timout Test
 
25
 *
 
26
 * This test plays a two-touch tap and checks that the appropriate events are
 
27
 * generated for a two-touch atomic tap subscription.
 
28
 *
 
29
 * Regression test for lp:949855 and lp:957437.
 
30
 */
 
31
 
 
32
#include <cmath>
 
33
#include <map>
 
34
#include <memory>
 
35
#include <stdexcept>
 
36
#include <future>
 
37
 
 
38
#include <gtest/gtest.h>
 
39
 
 
40
#include "device.h"
 
41
#include "events.h"
 
42
#include "recording.h"
 
43
#include "x11/fixture.h"
 
44
#include "utouch/frame_x11.h"
 
45
 
 
46
using namespace utouch::grail::x11::testing;
 
47
 
 
48
class AtomicTap : public Test {
 
49
 public:
 
50
  AtomicTap() : device_(NULL), step_(0) {}
 
51
 
 
52
 protected:
 
53
  static utouch::grail::testing::Events events_;
 
54
 
 
55
  virtual void ProcessFrameEvents();
 
56
  virtual void ProcessGrailEvents();
 
57
  void Subscribe();
 
58
  void CheckSlice(UGSlice);
 
59
 
 
60
  UFDevice device_;
 
61
  unsigned int step_;
 
62
};
 
63
 
 
64
void AtomicTap::ProcessFrameEvents() {
 
65
  UFEvent event;
 
66
 
 
67
  UFStatus status;
 
68
  while ((status = frame_get_event(frame_handle(), &event)) == UFStatusSuccess) {
 
69
    grail_process_frame_event(grail_handle(), event);
 
70
 
 
71
    if (frame_event_get_type(event) == UFEventTypeDeviceAdded) {
 
72
      UFDevice device;
 
73
      ASSERT_EQ(UFStatusSuccess,
 
74
                frame_event_get_property(event, UFEventPropertyDevice,
 
75
                                         &device));
 
76
 
 
77
      const char* name;
 
78
      ASSERT_EQ(UFStatusSuccess,
 
79
                frame_device_get_property(device, UFDevicePropertyName, &name));
 
80
      if (strcmp(name, "N-Trig MultiTouch (Virtual Test Device)") == 0) {
 
81
        EXPECT_EQ(NULL, device_);
 
82
        device_ = device;
 
83
        Subscribe();
 
84
      }
 
85
    }
 
86
 
 
87
    frame_event_unref(event);
 
88
  }
 
89
 
 
90
  EXPECT_EQ(UFStatusErrorNoEvent, status);
 
91
}
 
92
 
 
93
void AtomicTap::ProcessGrailEvents() {
 
94
  UGEvent event;
 
95
 
 
96
  UGStatus status;
 
97
  while ((status = grail_get_event(grail_handle(), &event)) == UGStatusSuccess) {
 
98
    ASSERT_EQ(UGEventTypeSlice, grail_event_get_type(event));
 
99
 
 
100
    UGSlice slice;
 
101
    status = grail_event_get_property(event, UGEventPropertySlice, &slice);
 
102
    ASSERT_EQ(UGStatusSuccess, status);
 
103
 
 
104
    CheckSlice(slice);
 
105
 
 
106
    grail_event_unref(event);
 
107
  }
 
108
 
 
109
  EXPECT_EQ(UGStatusErrorNoEvent, status);
 
110
}
 
111
 
 
112
void AtomicTap::Subscribe() {
 
113
  UGSubscription subscription;
 
114
  UGStatus status = grail_subscription_new(&subscription);
 
115
  ASSERT_EQ(UGStatusSuccess, status);
 
116
 
 
117
  status = grail_subscription_set_property(subscription,
 
118
                                           UGSubscriptionPropertyDevice,
 
119
                                           &device_);
 
120
  ASSERT_EQ(UGStatusSuccess, status);
 
121
 
 
122
  const UFWindowId window_id =
 
123
      frame_x11_create_window_id(DefaultRootWindow(Display()));
 
124
  status = grail_subscription_set_property(subscription,
 
125
                                           UGSubscriptionPropertyWindow,
 
126
                                           &window_id);
 
127
  ASSERT_EQ(UGStatusSuccess, status);
 
128
 
 
129
  const UGGestureTypeMask mask = UGGestureTypeTap;
 
130
  status = grail_subscription_set_property(subscription,
 
131
                                           UGSubscriptionPropertyMask,
 
132
                                           &mask);
 
133
  ASSERT_EQ(UGStatusSuccess, status);
 
134
 
 
135
  const int atomic = true;
 
136
  status = grail_subscription_set_property(subscription,
 
137
                                           UGSubscriptionPropertyAtomicGestures,
 
138
                                           &atomic);
 
139
 
 
140
  status = grail_subscription_activate(grail_handle(), subscription);
 
141
  ASSERT_EQ(UGStatusSuccess, status);
 
142
}
 
143
 
 
144
void AtomicTap::CheckSlice(UGSlice slice) {
 
145
  ASSERT_LT(step_, events_.size()) << "Received too many frame events";
 
146
 
 
147
  /* Ensure we got a device addition event first */
 
148
  if (step_ == 0)
 
149
    EXPECT_NE(nullptr, device_);
 
150
 
 
151
  if (!events_[step_].skip) {
 
152
    EXPECT_EQ(events_[step_].id, grail_slice_get_id(slice)) << "step " << step_;
 
153
    EXPECT_EQ(events_[step_].state, grail_slice_get_state(slice)) << "step "
 
154
                                                                  << step_;
 
155
    EXPECT_EQ(events_[step_].recognized, grail_slice_get_recognized(slice))
 
156
        << "step " << step_;
 
157
    EXPECT_EQ(events_[step_].num_touches, grail_slice_get_num_touches(slice))
 
158
        << "step " << step_;
 
159
  }
 
160
 
 
161
  if (grail_slice_get_state(slice) == UGGestureStateEnd) {
 
162
    UGSubscription subscription = grail_slice_get_subscription(slice);
 
163
    grail_subscription_deactivate(grail_handle(), subscription);
 
164
    grail_subscription_delete(subscription);
 
165
  }
 
166
 
 
167
  ++step_;
 
168
}
 
169
 
 
170
TEST_F(AtomicTap, Recording) {
 
171
  utouch::evemu::Device device("recordings/ntrig_dell_xt2/device.prop");
 
172
 
 
173
  /* Pump once to ensure the X server has initialized the device */
 
174
  PumpEvents();
 
175
  ASSERT_NE(nullptr, device_) << "X server failed to initialize touchscreen";
 
176
 
 
177
  utouch::evemu::Recording recording(device,
 
178
                                     "recordings/ntrig_dell_xt2/2_tap.record");
 
179
 
 
180
  /* We use the c++11 future module so any exceptions thrown by the thread can
 
181
   * be caught later on. If we used the thread module, exceptions would take the
 
182
   * whole thing down. */
 
183
  std::future<void> future = std::async(std::launch::async,
 
184
                                        &utouch::evemu::Recording::Play,
 
185
                                        &recording);
 
186
 
 
187
  PumpEvents();
 
188
 
 
189
  future.wait();
 
190
 
 
191
  EXPECT_EQ(events_.size(), step_) << "Failed to receive all frame events for "
 
192
                                      "touchscreen";
 
193
}
 
194
 
 
195
/* Construct the expected events */
 
196
namespace {
 
197
 
 
198
using namespace utouch::grail::testing;
 
199
 
 
200
const Events ConstructEvents() {
 
201
  Events events;
 
202
 
 
203
  {
 
204
    Slice slice = {
 
205
      false, /* skip */
 
206
      0, /* UGSlicePropertyID */
 
207
      UGGestureStateBegin, /* UGSlicePropertyState */
 
208
      0, /* UGSlicePropertyRecognized */
 
209
      2, /* UGSlicePropertyNumTouches */
 
210
      0, /* UGSlicePropertyOriginalCenterX */
 
211
      0, /* UGSlicePropertyOriginalCenterY */
 
212
      0, /* UGSlicePropertyOriginalRadius */
 
213
      {}, /* UGSlicePropertyTransform */
 
214
      {}, /* UGSlicePropertyCumulativeTransform */
 
215
      0, /* UGSlicePropertyCenterOfRotationX */
 
216
      0, /* UGSlicePropertyCenterOfRotationY */
 
217
      false, /* UGSlicePropertyConstructionFinished */
 
218
    };
 
219
    events.push_back(slice);
 
220
  }
 
221
 
 
222
  {
 
223
    Slice slice = {
 
224
      false, /* skip */
 
225
      0, /* UGSlicePropertyID */
 
226
      UGGestureStateUpdate, /* UGSlicePropertyState */
 
227
      0, /* UGSlicePropertyRecognized */
 
228
      2, /* UGSlicePropertyNumTouches */
 
229
      0, /* UGSlicePropertyOriginalCenterX */
 
230
      0, /* UGSlicePropertyOriginalCenterY */
 
231
      0, /* UGSlicePropertyOriginalRadius */
 
232
      {}, /* UGSlicePropertyTransform */
 
233
      {}, /* UGSlicePropertyCumulativeTransform */
 
234
      0, /* UGSlicePropertyCenterOfRotationX */
 
235
      0, /* UGSlicePropertyCenterOfRotationY */
 
236
      false, /* UGSlicePropertyConstructionFinished */
 
237
    };
 
238
    events.push_back(slice);
 
239
  }
 
240
 
 
241
  {
 
242
    Slice slice = {
 
243
      false, /* skip */
 
244
      0, /* UGSlicePropertyID */
 
245
      UGGestureStateUpdate, /* UGSlicePropertyState */
 
246
      UGGestureTypeTap, /* UGSlicePropertyRecognized */
 
247
      2, /* UGSlicePropertyNumTouches */
 
248
      0, /* UGSlicePropertyOriginalCenterX */
 
249
      0, /* UGSlicePropertyOriginalCenterY */
 
250
      0, /* UGSlicePropertyOriginalRadius */
 
251
      {}, /* UGSlicePropertyTransform */
 
252
      {}, /* UGSlicePropertyCumulativeTransform */
 
253
      0, /* UGSlicePropertyCenterOfRotationX */
 
254
      0, /* UGSlicePropertyCenterOfRotationY */
 
255
      false, /* UGSlicePropertyConstructionFinished */
 
256
    };
 
257
    events.push_back(slice);
 
258
  }
 
259
 
 
260
  {
 
261
    Slice slice = {
 
262
      false, /* skip */
 
263
      0, /* UGSlicePropertyID */
 
264
      UGGestureStateEnd, /* UGSlicePropertyState */
 
265
      UGGestureTypeTap, /* UGSlicePropertyRecognized */
 
266
      2, /* UGSlicePropertyNumTouches */
 
267
      0, /* UGSlicePropertyOriginalCenterX */
 
268
      0, /* UGSlicePropertyOriginalCenterY */
 
269
      0, /* UGSlicePropertyOriginalRadius */
 
270
      {}, /* UGSlicePropertyTransform */
 
271
      {}, /* UGSlicePropertyCumulativeTransform */
 
272
      0, /* UGSlicePropertyCenterOfRotationX */
 
273
      0, /* UGSlicePropertyCenterOfRotationY */
 
274
      true, /* UGSlicePropertyConstructionFinished */
 
275
    };
 
276
    events.push_back(slice);
 
277
  }
 
278
 
 
279
  return events;
 
280
}
 
281
 
 
282
} // namespace
 
283
 
 
284
/* Now initialize the static test fixture member */
 
285
utouch::grail::testing::Events AtomicTap::events_(ConstructEvents());