VirtualTouchpad_test.cpp revision 43b5b06c8be24e465bd6a7b22a8d341db1ad50a2
1#include <android/input.h> 2#include <cstdio> 3#include <cstdlib> 4#include <cstring> 5#include <gtest/gtest.h> 6#include <linux/input.h> 7 8#include "EvdevInjector.h" 9#include "VirtualTouchpad.h" 10 11namespace android { 12namespace dvr { 13 14namespace { 15 16class UInputForTesting : public EvdevInjector::UInput { 17 public: 18 void WriteInputEvent(uint16_t type, uint16_t code, int32_t value) { 19 struct input_event event; 20 memset(&event, 0, sizeof(event)); 21 event.type = type; 22 event.code = code; 23 event.value = value; 24 Write(&event, sizeof (event)); 25 } 26}; 27 28// Recording test implementation of UInput. 29// 30class UInputRecorder : public UInputForTesting { 31 public: 32 UInputRecorder() {} 33 virtual ~UInputRecorder() {} 34 35 const std::string& GetString() const { return s_; } 36 void Reset() { s_.clear(); } 37 38 // UInput overrides: 39 40 int Open() override { 41 s_ += "o;"; 42 return 0; 43 } 44 45 int Close() override { 46 s_ += "c;"; 47 return 0; 48 } 49 50 int Write(const void* buf, size_t count) override { 51 s_ += "w("; 52 s_ += Encode(&count, sizeof(count)); 53 s_ += ","; 54 s_ += Encode(buf, count); 55 s_ += ");"; 56 return 0; 57 } 58 59 int IoctlVoid(int request) override { 60 s_ += "i("; 61 s_ += Encode(&request, sizeof(request)); 62 s_ += ");"; 63 return 0; 64 } 65 66 int IoctlSetInt(int request, int value) override { 67 s_ += "i("; 68 s_ += Encode(&request, sizeof(request)); 69 s_ += ","; 70 s_ += Encode(&value, sizeof(value)); 71 s_ += ");"; 72 return 0; 73 } 74 75 private: 76 std::string s_; 77 78 std::string Encode(const void* buf, size_t count) { 79 const char* in = static_cast<const char*>(buf); 80 char out[2 * count + 1]; 81 for (size_t i = 0; i < count; ++i) { 82 snprintf(&out[2 * i], 3, "%02X", in[i]); 83 } 84 return out; 85 } 86}; 87 88class EvdevInjectorForTesting : public EvdevInjector { 89 public: 90 EvdevInjectorForTesting(UInput& uinput) { 91 SetUInputForTesting(&uinput); 92 } 93 const uinput_user_dev* GetUiDev() const { return GetUiDevForTesting(); } 94}; 95 96class VirtualTouchpadForTesting : public VirtualTouchpad { 97 public: 98 VirtualTouchpadForTesting(EvdevInjector& injector) { 99 SetEvdevInjectorForTesting(&injector); 100 } 101}; 102 103void DumpDifference(const char* expect, const char* actual) { 104 printf(" common: "); 105 while (*expect && *expect == *actual) { 106 putchar(*expect); 107 ++expect; 108 ++actual; 109 } 110 printf("\n expect: %s\n", expect); 111 printf(" actual: %s\n", actual); 112} 113 114} // anonymous namespace 115 116class VirtualTouchpadTest : public testing::Test { 117}; 118 119TEST_F(VirtualTouchpadTest, Goodness) { 120 UInputRecorder expect; 121 UInputRecorder record; 122 EvdevInjectorForTesting injector(record); 123 VirtualTouchpadForTesting touchpad(injector); 124 125 const int initialization_status = touchpad.Initialize(); 126 EXPECT_EQ(0, initialization_status); 127 128 // Check some aspects of uinput_user_dev. 129 const uinput_user_dev* uidev = injector.GetUiDev(); 130 for (int i = 0; i < ABS_CNT; ++i) { 131 EXPECT_EQ(0, uidev->absmin[i]); 132 EXPECT_EQ(0, uidev->absfuzz[i]); 133 EXPECT_EQ(0, uidev->absflat[i]); 134 if (i != ABS_MT_POSITION_X && i != ABS_MT_POSITION_Y && i != ABS_MT_SLOT) { 135 EXPECT_EQ(0, uidev->absmax[i]); 136 } 137 } 138 const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X]; 139 const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y]; 140 const int32_t slots = uidev->absmax[ABS_MT_SLOT]; 141 142 // Check the system calls performed by initialization. 143 // From ConfigureBegin(): 144 expect.Open(); 145 // From ConfigureInputProperty(INPUT_PROP_DIRECT): 146 expect.IoctlSetInt(UI_SET_PROPBIT, INPUT_PROP_DIRECT); 147 // From ConfigureMultiTouchXY(0, 0, kWidth - 1, kHeight - 1): 148 expect.IoctlSetInt(UI_SET_EVBIT, EV_ABS); 149 expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_X); 150 expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_POSITION_Y); 151 // From ConfigureAbsSlots(kSlots): 152 expect.IoctlSetInt(UI_SET_ABSBIT, ABS_MT_SLOT); 153 // From ConfigureKey(BTN_TOUCH): 154 expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY); 155 expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH); 156 // From ConfigureEnd(): 157 expect.Write(uidev, sizeof (uinput_user_dev)); 158 expect.IoctlVoid(UI_DEV_CREATE); 159 EXPECT_EQ(expect.GetString(), record.GetString()); 160 161 expect.Reset(); 162 record.Reset(); 163 int touch_status = touchpad.Touch(0, 0, 0); 164 EXPECT_EQ(0, touch_status); 165 expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0); 166 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); 167 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0); 168 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0); 169 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 170 EXPECT_EQ(expect.GetString(), record.GetString()); 171 172 expect.Reset(); 173 record.Reset(); 174 touch_status = touchpad.Touch(0.25f, 0.75f, 0.5f); 175 EXPECT_EQ(0, touch_status); 176 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); 177 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.25f * width); 178 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.75f * height); 179 expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_PRESS); 180 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 181 EXPECT_EQ(expect.GetString(), record.GetString()); 182 183 expect.Reset(); 184 record.Reset(); 185 touch_status = touchpad.Touch(1.0f, 1.0f, 1.0f); 186 EXPECT_EQ(0, touch_status); 187 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0); 188 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, width); 189 expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, height); 190 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 191 EXPECT_EQ(expect.GetString(), record.GetString()); 192 193 expect.Reset(); 194 record.Reset(); 195 touch_status = touchpad.Touch(0.25f, 0.75f, -0.01f); 196 EXPECT_EQ(0, touch_status); 197 expect.WriteInputEvent(EV_KEY, BTN_TOUCH, EvdevInjector::KEY_RELEASE); 198 expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, -1); 199 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 200 EXPECT_EQ(expect.GetString(), record.GetString()); 201 202 expect.Reset(); 203 record.Reset(); 204 touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_BACK); 205 EXPECT_EQ(0, touch_status); 206 expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_PRESS); 207 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 208 EXPECT_EQ(expect.GetString(), record.GetString()); 209 210 expect.Reset(); 211 record.Reset(); 212 touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_BACK); 213 EXPECT_EQ(0, touch_status); 214 EXPECT_EQ(expect.GetString(), record.GetString()); 215 216 expect.Reset(); 217 record.Reset(); 218 touch_status = touchpad.ButtonState(0); 219 EXPECT_EQ(0, touch_status); 220 expect.WriteInputEvent(EV_KEY, BTN_BACK, EvdevInjector::KEY_RELEASE); 221 expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0); 222 EXPECT_EQ(expect.GetString(), record.GetString()); 223 224 expect.Reset(); 225 record.Reset(); 226} 227 228TEST_F(VirtualTouchpadTest, Badness) { 229 UInputRecorder expect; 230 UInputRecorder record; 231 EvdevInjectorForTesting injector(record); 232 VirtualTouchpadForTesting touchpad(injector); 233 234 // Touch before initialization should return an error, 235 // and should not result in any system calls. 236 expect.Reset(); 237 record.Reset(); 238 int touch_status = touchpad.Touch(0.25f, 0.75f, -0.01f); 239 EXPECT_NE(0, touch_status); 240 EXPECT_EQ(expect.GetString(), record.GetString()); 241 242 // Button change before initialization should return an error, 243 // and should not result in any system calls. 244 expect.Reset(); 245 record.Reset(); 246 touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_BACK); 247 EXPECT_NE(0, touch_status); 248 EXPECT_EQ(expect.GetString(), record.GetString()); 249 250 expect.Reset(); 251 record.Reset(); 252 touchpad.Initialize(); 253 254 // Repeated initialization should return an error, 255 // and should not result in any system calls. 256 expect.Reset(); 257 record.Reset(); 258 const int initialization_status = touchpad.Initialize(); 259 EXPECT_NE(0, initialization_status); 260 EXPECT_EQ(expect.GetString(), record.GetString()); 261 262 // Touch off-screen should return an error, 263 // and should not result in any system calls. 264 expect.Reset(); 265 record.Reset(); 266 touch_status = touchpad.Touch(-0.25f, 0.75f, 1.0f); 267 EXPECT_NE(0, touch_status); 268 touch_status = touchpad.Touch(0.25f, -0.75f, 1.0f); 269 EXPECT_NE(0, touch_status); 270 touch_status = touchpad.Touch(1.25f, 0.75f, 1.0f); 271 EXPECT_NE(0, touch_status); 272 touch_status = touchpad.Touch(0.25f, 1.75f, 1.0f); 273 EXPECT_NE(0, touch_status); 274 EXPECT_EQ(expect.GetString(), record.GetString()); 275 276 // Unsupported button should return an error, 277 // and should not result in any system calls. 278 expect.Reset(); 279 record.Reset(); 280 touch_status = touchpad.ButtonState(AMOTION_EVENT_BUTTON_FORWARD); 281 EXPECT_NE(0, touch_status); 282 EXPECT_EQ(expect.GetString(), record.GetString()); 283} 284 285} // namespace dvr 286} // namespace android 287