• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 #include <fstream>
18 #include <string>
19 #include <map>
20 
21 #include "event_replayer.h"
22 
23 namespace OHOS {
24 namespace MMI {
25 namespace {
26 using namespace testing::ext;
27 
28 const std::string SANDBOX_PATH = "/data/service/el1/public/multimodalinput/";
29 const std::string TEST_FILE_PATH = SANDBOX_PATH + "mmi_test_events.rec";
30 const std::string INVALID_FILE_PATH = SANDBOX_PATH + "mmi_invalid_events.rec";
31 const std::string EMPTY_FILE_PATH = SANDBOX_PATH + "mmi_empty_events.rec";
32 const std::string PARTIAL_FILE_PATH = SANDBOX_PATH + "mmi_partial_events.rec";
33 
CreateTestEventFile(const std::string & path)34 bool CreateTestEventFile(const std::string& path)
35 {
36     std::ofstream file(path);
37     if (!file.is_open()) {
38         return false;
39     }
40     file << "EVENTS_BEGIN" << std::endl;
41     file << "[1, 1, 30, 1, 1682345678, 123456] # EV_KEY / KEY_A 1" << std::endl;
42     file << "[1, 0, 0, 0, 1682345678, 123456] # EV_SYN / SYN_REPORT 0" << std::endl;
43     file << "[1, 1, 30, 0, 1682345678, 223456] # EV_KEY / KEY_A 0" << std::endl;
44     file << "[1, 0, 0, 0, 1682345678, 223456] # EV_SYN / SYN_REPORT 0" << std::endl;
45     file << "EVENTS_END" << std::endl;
46     file << std::endl;
47     file << "DEVICES: 1" << std::endl;
48     file << "DEVICE: 1|/dev/input/event2|Test Keyboard" << std::endl;
49     file.close();
50     return true;
51 }
52 
CreateTestDeviceFile(const std::string & path)53 bool CreateTestDeviceFile(const std::string& path)
54 {
55     std::ofstream file(path);
56     if (!file.is_open()) {
57         return false;
58     }
59     file << "EVENTS_BEGIN" << std::endl;
60     file << "[1, 1, 30, 1, 1682345678, 123456] # EV_KEY / KEY_A 1" << std::endl;
61     file << "[1, 0, 0, 0, 1682345678, 123456] # EV_SYN / SYN_REPORT 0" << std::endl;
62     file << "[1, 1, 30, 0, 1682345678, 223456] # EV_KEY / KEY_A 0" << std::endl;
63     file << "[1, 0, 0, 0, 1682345678, 223456] # EV_SYN / SYN_REPORT 0" << std::endl;
64     file << "EVENTS_END" << std::endl;
65     file << std::endl;
66     file << "DEVICES: 1" << std::endl;
67     file << "DEVICE: 1|/dev/input/event2|Test Keyboard|123124a" << std::endl;
68     file.close();
69     return true;
70 }
71 
CreateInvalidEventFile(const std::string & path)72 bool CreateInvalidEventFile(const std::string& path)
73 {
74     std::ofstream file(path);
75     if (!file.is_open()) {
76         return false;
77     }
78     file << "INVALID CONTENT" << std::endl;
79     file.close();
80     return true;
81 }
82 
CreateEmptyEventFile(const std::string & path)83 bool CreateEmptyEventFile(const std::string& path)
84 {
85     std::ofstream file(path);
86     if (!file.is_open()) {
87         return false;
88     }
89     file.close();
90     return true;
91 }
92 
CreatePartialEventFile(const std::string & path,bool includeDevices,bool includeEvents)93 bool CreatePartialEventFile(const std::string& path, bool includeDevices, bool includeEvents)
94 {
95     std::ofstream file(path);
96     if (!file.is_open()) {
97         return false;
98     }
99     file << "HEADER INFORMATION" << std::endl;
100     if (includeEvents) {
101         file << "EVENTS_BEGIN" << std::endl;
102         file << "[4, 2, 0, -2, 1501837700, 841124] # EV_REL / REL_X -2" << std::endl;
103         file << "[4, 0, 0, 0, 1501837700, 841124] # EV_SYN / SYN_REPORT 0" << std::endl;
104         file << "EVENTS_END" << std::endl;
105     }
106     if (includeDevices) {
107         file << "DEVICES: 2" << std::endl;
108         file << "DEVICE: 4|/dev/input/event4|Compx 2.4G Receiver Mouse" << std::endl;
109         file << "DEVICE: 10|/dev/input/event10|VSoC touchscreen" << std::endl;
110     }
111     file.close();
112     return true;
113 }
114 
CleanupTestFiles()115 void CleanupTestFiles()
116 {
117     std::remove(TEST_FILE_PATH.c_str());
118     std::remove(INVALID_FILE_PATH.c_str());
119     std::remove(EMPTY_FILE_PATH.c_str());
120     std::remove(PARTIAL_FILE_PATH.c_str());
121 }
122 } // namespace
123 
124 class EventReplayerTest : public testing::Test {
125 public:
SetUpTestCase(void)126     static void SetUpTestCase(void) {}
TearDownTestCase(void)127     static void TearDownTestCase(void)
128     {
129         CleanupTestFiles();
130     }
SetUp()131     void SetUp() {}
TearDown()132     void TearDown()
133     {
134         CleanupTestFiles();
135     }
136 };
137 
138 /**
139  * @tc.name: EventReplayerTest_Constructor
140  * @tc.desc: Test constructor of EventReplayer
141  * @tc.type: FUNC
142  * @tc.require:
143  */
144 HWTEST_F(EventReplayerTest, EventReplayerTest_Constructor, TestSize.Level1)
145 {
146     EventReplayer replayer1(TEST_FILE_PATH);
147     SUCCEED();
148 
149     std::map<uint16_t, uint16_t> deviceMapping = {{1, 3}, {2, 4}};
150     EventReplayer replayer2(TEST_FILE_PATH, deviceMapping);
151     SUCCEED();
152 }
153 
154 /**
155  * @tc.name: EventReplayerTest_ParseInputLine_Valid
156  * @tc.desc: Test parsing valid input lines
157  * @tc.type: FUNC
158  * @tc.require:
159  */
160 HWTEST_F(EventReplayerTest, EventReplayerTest_ParseInputLine_Valid, TestSize.Level1)
161 {
162     uint32_t deviceId;
163     input_event event;
164 
165     EXPECT_TRUE(EventReplayer::ParseInputLine("[1, 1, 30, 1, 1682345678, 123456] # EV_KEY / KEY_A 1",
166         deviceId, event));
167     EXPECT_EQ(deviceId, 1);
168     EXPECT_EQ(event.type, 1);
169     EXPECT_EQ(event.code, 30);
170     EXPECT_EQ(event.value, 1);
171     EXPECT_EQ(event.input_event_sec, 1682345678);
172     EXPECT_EQ(event.input_event_usec, 123456);
173 
174     EXPECT_TRUE(EventReplayer::ParseInputLine("[  2,  3,  40,  0,  1682345679,  234567  ] # Comment",
175         deviceId, event));
176     EXPECT_EQ(deviceId, 2);
177     EXPECT_EQ(event.type, 3);
178     EXPECT_EQ(event.code, 40);
179     EXPECT_EQ(event.value, 0);
180     EXPECT_EQ(event.input_event_sec, 1682345679);
181     EXPECT_EQ(event.input_event_usec, 234567);
182 
183     EXPECT_TRUE(EventReplayer::ParseInputLine("[3, 0, 0, 0, 1682345680, 345678]",
184         deviceId, event));
185     EXPECT_EQ(deviceId, 3);
186     EXPECT_EQ(event.type, 0);
187     EXPECT_EQ(event.code, 0);
188     EXPECT_EQ(event.value, 0);
189     EXPECT_EQ(event.input_event_sec, 1682345680);
190     EXPECT_EQ(event.input_event_usec, 345678);
191 }
192 
193 /**
194  * @tc.name: EventReplayerTest_ParseInputLine_Invalid
195  * @tc.desc: Test parsing invalid input lines
196  * @tc.type: FUNC
197  * @tc.require:
198  */
199 HWTEST_F(EventReplayerTest, EventReplayerTest_ParseInputLine_Invalid, TestSize.Level1)
200 {
201     uint32_t deviceId;
202     input_event event;
203 
204     EXPECT_FALSE(EventReplayer::ParseInputLine("", deviceId, event));
205     EXPECT_FALSE(EventReplayer::ParseInputLine("1, 1, 30, 1, 1682345678, 123456", deviceId, event));
206     EXPECT_FALSE(EventReplayer::ParseInputLine("[1, 1, 30]", deviceId, event));
207     EXPECT_FALSE(EventReplayer::ParseInputLine("[a, 1, 30, 1, 1682345678, 123456]", deviceId, event));
208     EXPECT_FALSE(EventReplayer::ParseInputLine("[ 1, 1, 30, 1, 1682345678, 123456", deviceId, event));
209     EXPECT_FALSE(EventReplayer::ParseInputLine("1, 1, 30, 1, 1682345678, 123456 ]", deviceId, event));
210     EXPECT_FALSE(EventReplayer::ParseInputLine("[1 1, 30, 1, 1682345678, 123456]", deviceId, event));
211 }
212 
213 /**
214  * @tc.name: EventReplayerTest_FileOpenError
215  * @tc.desc: Test file opening error cases
216  * @tc.type: FUNC
217  * @tc.require:
218  */
219 HWTEST_F(EventReplayerTest, EventReplayerTest_FileOpenError, TestSize.Level1)
220 {
221     std::string nonExistentPath = SANDBOX_PATH + "non_existent_file.rec";
222     EventReplayer replayer(nonExistentPath);
223     EXPECT_FALSE(replayer.Replay());
224 }
225 
226 /**
227  * @tc.name: EventReplayerTest_EmptyFileError
228  * @tc.desc: Test with empty file error cases
229  * @tc.type: FUNC
230  * @tc.require:
231  */
232 HWTEST_F(EventReplayerTest, EventReplayerTest_EmptyFileError, TestSize.Level1)
233 {
234     if (!CreateEmptyEventFile(EMPTY_FILE_PATH)) {
235         GTEST_SKIP() << "Failed to create test file, skipping test";
236     }
237     EventReplayer replayer(EMPTY_FILE_PATH);
238     EXPECT_FALSE(replayer.Replay());
239 }
240 
241 /**
242  * @tc.name: EventReplayerTest_InvalidFileFormat
243  * @tc.desc: Test with invalid file format
244  * @tc.type: FUNC
245  * @tc.require:
246  */
247 HWTEST_F(EventReplayerTest, EventReplayerTest_InvalidFileFormat, TestSize.Level1)
248 {
249     if (!CreateInvalidEventFile(INVALID_FILE_PATH)) {
250         GTEST_SKIP() << "Failed to create test file, skipping test";
251     }
252     EventReplayer replayer(INVALID_FILE_PATH);
253     EXPECT_FALSE(replayer.Replay());
254 }
255 
256 /**
257  * @tc.name: EventReplayerTest_InvaildFilePath
258  * @tc.desc: Test with invalid file path
259  * @tc.type: FUNC
260  * @tc.require:
261  */
262 HWTEST_F(EventReplayerTest, EventReplayerTest_InvaildFilePath, TestSize.Level1)
263 {
264     EventReplayer replayer("/invaild/path");
265     EXPECT_FALSE(replayer.Replay());
266 }
267 
268 /**
269  * @tc.name: EventReplayerTest_VaildFilePath
270  * @tc.desc: Test with valid file path but no available device
271  * @tc.type: FUNC
272  * @tc.require:
273  */
274 HWTEST_F(EventReplayerTest, EventReplayerTest_VaildFilePath, TestSize.Level1)
275 {
276     if (!CreateTestDeviceFile(TEST_FILE_PATH)) {
277     GTEST_SKIP() << "Failed to create test file, skipping test";
278     }
279     EventReplayer replayer(TEST_FILE_PATH);
280     EXPECT_FALSE(replayer.Replay());
281 }
282 
283 /**
284  * @tc.name: EventReplayerTest_DeviceMapping
285  * @tc.desc: Test device mapping functionality
286  * @tc.type: FUNC
287  * @tc.require:
288  */
289 HWTEST_F(EventReplayerTest, EventReplayerTest_DeviceMapping, TestSize.Level1)
290 {
291     std::map<uint16_t, uint16_t> deviceMapping = {{1, 3}, {2, 4}};
292     EventReplayer replayer(TEST_FILE_PATH, deviceMapping);
293     SUCCEED();
294 }
295 
296 /**
297  * @tc.name: EventReplayerTest_InvalidDeviceError
298  * @tc.desc: Test error handling when device is invalid
299  * @tc.type: FUNC
300  * @tc.require:
301  */
302 HWTEST_F(EventReplayerTest, EventReplayerTest_InvalidDeviceError, TestSize.Level1)
303 {
304     if (!CreateTestEventFile(TEST_FILE_PATH)) {
305         GTEST_SKIP() << "Failed to create test file, skipping test";
306     }
307     std::map<uint16_t, uint16_t> deviceMapping = {{2, 3}, {3, 4}};
308     EventReplayer replayer(TEST_FILE_PATH, deviceMapping);
309     ASSERT_NO_FATAL_FAILURE({
310         replayer.Replay();
311     });
312 }
313 
314 /**
315  * @tc.name: EventReplayerTest_SeekToDevicesSection_Found
316  * @tc.desc: Test seeking to DEVICES section when it exists
317  * @tc.type: FUNC
318  * @tc.require:
319  */
320 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToDevicesSection_Found, TestSize.Level1)
321 {
322     if (!CreatePartialEventFile(PARTIAL_FILE_PATH, true, false)) {
323         GTEST_SKIP() << "Failed to create test file, skipping test";
324     }
325     EventReplayer replayer(PARTIAL_FILE_PATH);
326     std::ifstream inputFile(PARTIAL_FILE_PATH);
327     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
328     EXPECT_TRUE(replayer.SeekToDevicesSection(inputFile));
329     // Verify we're at the right position
330     std::string line;
331     std::getline(inputFile, line);
332     EXPECT_EQ(line, "DEVICES: 2") << "File position should be at DEVICES line";
333 
334     inputFile.close();
335 }
336 
337 /**
338  * @tc.name: EventReplayerTest_SeekToDevicesSection_NotFound
339  * @tc.desc: Test seeking to DEVICES section when it doesn't exist
340  * @tc.type: FUNC
341  * @tc.require:
342  */
343 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToDevicesSection_NotFound, TestSize.Level1)
344 {
345     if (!CreatePartialEventFile(PARTIAL_FILE_PATH, false, true)) {
346         GTEST_SKIP() << "Failed to create test file, skipping test";
347     }
348     EventReplayer replayer(PARTIAL_FILE_PATH);
349     std::ifstream inputFile(PARTIAL_FILE_PATH);
350     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
351     EXPECT_FALSE(replayer.SeekToDevicesSection(inputFile));
352     inputFile.close();
353 }
354 
355 /**
356  * @tc.name: EventReplayerTest_SeekToEventsSection_Found
357  * @tc.desc: Test seeking to EVENTS_BEGIN section when it exists
358  * @tc.type: FUNC
359  * @tc.require:
360  */
361 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToEventsSection_Found, TestSize.Level1)
362 {
363     if (!CreatePartialEventFile(PARTIAL_FILE_PATH, false, true)) {
364         GTEST_SKIP() << "Failed to create test file, skipping test";
365     }
366     EventReplayer replayer(PARTIAL_FILE_PATH);
367     std::ifstream inputFile(PARTIAL_FILE_PATH);
368     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
369     EXPECT_TRUE(replayer.SeekToEventsSection(inputFile));
370     // Verify we're at the right position (after EVENTS_BEGIN)
371     std::string line;
372     std::getline(inputFile, line);
373     EXPECT_EQ(line, "[4, 2, 0, -2, 1501837700, 841124] # EV_REL / REL_X -2") <<
374         "File position should be after EVENTS_BEGIN line";
375     inputFile.close();
376 }
377 
378 /**
379  * @tc.name: EventReplayerTest_SeekToEventsSection_NotFound
380  * @tc.desc: Test seeking to EVENTS_BEGIN section when it doesn't exist
381  * @tc.type: FUNC
382  * @tc.require:
383  */
384 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToEventsSection_NotFound, TestSize.Level1)
385 {
386     if (!CreatePartialEventFile(PARTIAL_FILE_PATH, true, false)) {
387         GTEST_SKIP() << "Failed to create test file, skipping test";
388     }
389     EventReplayer replayer(PARTIAL_FILE_PATH);
390     std::ifstream inputFile(PARTIAL_FILE_PATH);
391     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
392     EXPECT_FALSE(replayer.SeekToEventsSection(inputFile));
393     inputFile.close();
394 }
395 
396 /**
397  * @tc.name: EventReplayerTest_SeekToDevicesSection_BadStream
398  * @tc.desc: Test seeking to DEVICES section with a bad file stream
399  * @tc.type: FUNC
400  * @tc.require:
401  */
402 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToDevicesSection_BadStream, TestSize.Level1)
403 {
404     EventReplayer replayer(INVALID_FILE_PATH);
405     std::ifstream inputFile(INVALID_FILE_PATH);
406     inputFile.close(); // Deliberately close to make it bad
407     EXPECT_FALSE(replayer.SeekToDevicesSection(inputFile));
408 }
409 
410 /**
411  * @tc.name: EventReplayerTest_SeekToEventsSection_BadStream
412  * @tc.desc: Test seeking to EVENTS_BEGIN section with a bad file stream
413  * @tc.type: FUNC
414  * @tc.require:
415  */
416 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToEventsSection_BadStream, TestSize.Level1)
417 {
418     EventReplayer replayer(INVALID_FILE_PATH);
419     std::ifstream inputFile(INVALID_FILE_PATH);
420     inputFile.close(); // Deliberately close to make it bad
421     EXPECT_FALSE(replayer.SeekToEventsSection(inputFile));
422 }
423 
424 /**
425  * @tc.name: EventReplayerTest_SeekToDevicesSection_CompleteFile
426  * @tc.desc: Test seeking to DEVICES section in a complete file with both sections
427  * @tc.type: FUNC
428  * @tc.require:
429  */
430 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToDevicesSection_CompleteFile, TestSize.Level1)
431 {
432     if (!CreateTestEventFile(TEST_FILE_PATH)) {
433         GTEST_SKIP() << "Failed to create test file, skipping test";
434     }
435     EventReplayer replayer(TEST_FILE_PATH);
436     std::ifstream inputFile(TEST_FILE_PATH);
437     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
438     EXPECT_TRUE(replayer.SeekToDevicesSection(inputFile));
439     // Verify we're at the right position
440     std::string line;
441     std::getline(inputFile, line);
442     EXPECT_EQ(line, "DEVICES: 1") << "File position should be at DEVICES line";
443     inputFile.close();
444 }
445 
446 /**
447  * @tc.name: EventReplayerTest_SeekToEventsSection_CompleteFile
448  * @tc.desc: Test seeking to EVENTS_BEGIN section in a complete file with both sections
449  * @tc.type: FUNC
450  * @tc.require:
451  */
452 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToEventsSection_CompleteFile, TestSize.Level1)
453 {
454     if (!CreateTestEventFile(TEST_FILE_PATH)) {
455         GTEST_SKIP() << "Failed to create test file, skipping test";
456     }
457     EventReplayer replayer(TEST_FILE_PATH);
458     std::ifstream inputFile(TEST_FILE_PATH);
459     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
460     EXPECT_TRUE(replayer.SeekToEventsSection(inputFile));
461     // Verify we're at the right position (after EVENTS_BEGIN)
462     std::string line;
463     std::getline(inputFile, line);
464     EXPECT_EQ(line, "[1, 1, 30, 1, 1682345678, 123456] # EV_KEY / KEY_A 1") <<
465         "File position should be after EVENTS_BEGIN line";
466     inputFile.close();
467 }
468 
469 /**
470  * @tc.name: EventReplayerTest_SeekToDevicesSection_EmptyFile
471  * @tc.desc: Test seeking to DEVICES section in an empty file
472  * @tc.type: FUNC
473  * @tc.require:
474  */
475 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToDevicesSection_EmptyFile, TestSize.Level1)
476 {
477     if (!CreateEmptyEventFile(EMPTY_FILE_PATH)) {
478         GTEST_SKIP() << "Failed to create test file, skipping test";
479     }
480     EventReplayer replayer(EMPTY_FILE_PATH);
481     std::ifstream inputFile(EMPTY_FILE_PATH);
482     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
483     EXPECT_FALSE(replayer.SeekToDevicesSection(inputFile));
484     inputFile.close();
485 }
486 
487 /**
488  * @tc.name: EventReplayerTest_SeekToEventsSection_EmptyFile
489  * @tc.desc: Test seeking to EVENTS_BEGIN section in an empty file
490  * @tc.type: FUNC
491  * @tc.require:
492  */
493 HWTEST_F(EventReplayerTest, EventReplayerTest_SeekToEventsSection_EmptyFile, TestSize.Level1)
494 {
495     if (!CreateEmptyEventFile(EMPTY_FILE_PATH)) {
496         GTEST_SKIP() << "Failed to create test file, skipping test";
497     }
498     EventReplayer replayer(EMPTY_FILE_PATH);
499     std::ifstream inputFile(EMPTY_FILE_PATH);
500     EXPECT_TRUE(inputFile.is_open()) << "Failed to open test file";
501     EXPECT_FALSE(replayer.SeekToEventsSection(inputFile));
502     inputFile.close();
503 }
504 } // namespace MMI
505 } // namespace OHOS