virtual:add virtual backend
[platform/core/uifw/libtdm.git] / haltests / src / tc_tdm_client.cpp
1 /**************************************************************************
2  *
3  * Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved.
4  *
5  * Contact: Konstantin Drabeniuk <k.drabeniuk@samsung.com>
6  * Contact: Andrii Sokolenko <a.sokolenko@samsung.com>
7  * Contact: Roman Marchenko <r.marchenko@samsung.com>
8  * Contact: Sergey Sizonov <s.sizonov@samsung.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the
12  * "Software"), to deal in the Software without restriction, including
13  * without limitation the rights to use, copy, modify, merge, publish,
14  * distribute, sub license, and/or sell copies of the Software, and to
15  * permit persons to whom the Software is furnished to do so, subject to
16  * the following conditions:
17  *
18  * The above copyright notice and this permission notice (including the
19  * next paragraph) shall be included in all copies or substantial portions
20  * of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  *
30 **************************************************************************/
31
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <sys/signalfd.h>
35 #include <poll.h>
36 #include <sys/prctl.h>
37
38 #include "tc_tdm.h"
39 #include "tdm_client.h"
40
41 /* LCOV_EXCL_START */
42
43 enum {
44         TDM_UT_PIPE_MSG_NONE,
45         TDM_UT_PIPE_MSG_REPLY,
46         TDM_UT_PIPE_MSG_SERVER_READY,
47         TDM_UT_PIPE_MSG_SERVER_FAILED,
48         TDM_UT_PIPE_MSG_DPMS_ON,
49         TDM_UT_PIPE_MSG_DPMS_OFF,
50         TDM_UT_PIPE_MSG_TERMINATE_SERVER,
51 };
52
53 static int _tc_tdm_pipe_read_msg(int fd);
54 static bool _tc_tdm_pipe_write_msg(int fd, int reply_fd, int msg);
55 static pid_t _tc_tdm_client_server_fork(int *pipe_to_parent, int *pipe_to_child);
56
57 class TDMClient : public TDMEnv
58 {
59 public:
60         static pid_t server_pid;
61
62         /* 0: read, 1: write */
63         static int pipe_parent[2];
64         static int pipe_child[2];
65
66         tdm_client *client;
67         tdm_client_output *output;
68         tdm_client_vblank *vblank;
69         tdm_client_voutput *voutput;
70
71         double vrefresh_interval, start, end;
72
73         TDMClient();
74
75         void SetUp(void);
76         void TearDown(void);
77         bool PrepareClient(void);
78         bool PrepareOutput(void);
79         bool PrepareVblank(void);
80
81         static void TearDownTestCase(void);
82         static void ServerFork(void);
83         static void ServerKill(void);
84 };
85
86 pid_t TDMClient::server_pid = -1;
87 int TDMClient::pipe_parent[2] = {-1, -1};
88 int TDMClient::pipe_child[2] = {-1, -1};
89
90 void TDMClient::TearDownTestCase(void)
91 {
92         ServerKill();
93 }
94
95 void TDMClient::ServerFork(void)
96 {
97         if (server_pid > 0)
98                 return;
99
100         server_pid = _tc_tdm_client_server_fork(pipe_parent, pipe_child);
101         ASSERT_GT(server_pid, 0);
102 }
103
104 void TDMClient::ServerKill(void)
105 {
106         if (pipe_child[0] >= 0)
107                 close(pipe_child[0]);
108         if (pipe_child[1] >= 0) {
109                 if (server_pid > 0) {
110                         bool ret = _tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_TERMINATE_SERVER);
111                         if (ret) {
112                                 if (waitpid(server_pid, NULL, 0) == server_pid)
113                                         TDM_INFO("*** server terminated ***");
114                                 else
115                                         TDM_ERR("*** failed to terminate server ***");
116                         } else {
117                                 if (kill(server_pid, 9) < 0)
118                                         TDM_ERR("*** failed to kill server ***");
119                         }
120                 }
121                 close(pipe_child[1]);
122         }
123
124         if (pipe_parent[0] >= 0)
125                 close(pipe_parent[0]);
126         if (pipe_parent[1] >= 0)
127                 close(pipe_parent[1]);
128
129         server_pid = -1;
130         pipe_parent[0] = pipe_parent[1] = -1;
131         pipe_child[0] = pipe_child[1] = -1;
132 }
133
134 TDMClient::TDMClient()
135 {
136         client = NULL;
137         output = NULL;
138         vblank = NULL;
139         vrefresh_interval = start = end = 0.0;
140 }
141
142 void TDMClient::SetUp(void)
143 {
144         TDMEnv::SetUp();
145
146         if (server_pid == -1)
147                 ServerFork();
148 }
149
150 void TDMClient::TearDown(void)
151 {
152         if (vblank)
153                 tdm_client_vblank_destroy(vblank);
154         if (client)
155                 tdm_client_destroy(client);
156
157         TDMEnv::TearDown();
158 }
159
160 bool TDMClient::PrepareClient(void)
161 {
162         tdm_error ret;
163         client = tdm_client_create(&ret);
164         TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
165         TDM_UT_RETURN_FALSE_IF_FAIL(client != NULL);
166
167         return true;
168 }
169
170 bool TDMClient::PrepareOutput(void)
171 {
172         tdm_error ret;
173
174         TDM_UT_RETURN_FALSE_IF_FAIL(client != NULL);
175
176         output = tdm_client_get_output(client, NULL, &ret);
177         TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
178         TDM_UT_RETURN_FALSE_IF_FAIL(output != NULL);
179
180         return true;
181 }
182
183 bool TDMClient::PrepareVblank(void)
184 {
185         tdm_error ret;
186         unsigned int refresh;
187
188         TDM_UT_RETURN_FALSE_IF_FAIL(output != NULL);
189
190         vblank = tdm_client_output_create_vblank(output, &ret);
191         TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
192         TDM_UT_RETURN_FALSE_IF_FAIL(vblank != NULL);
193
194         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_client_output_get_refresh_rate(output, &refresh) == TDM_ERROR_NONE);
195         TDM_UT_RETURN_FALSE_IF_FAIL(refresh > 0);
196
197         vrefresh_interval = 1.0 / (double)refresh;
198         TDM_UT_RETURN_FALSE_IF_FAIL(vrefresh_interval > 0);
199
200         return true;
201 }
202
203 static int
204 _tc_tdm_pipe_read_msg(int fd)
205 {
206         ssize_t len;
207         int msg;
208
209         do {
210                 len = read(fd, &msg, sizeof msg);
211         } while (len < 0 && errno == EINTR);
212
213         if (len <= 0)
214                 msg = TDM_UT_PIPE_MSG_NONE;
215
216         return msg;
217 }
218
219 static bool
220 _tc_tdm_pipe_write_msg(int fd, int reply_fd, int msg)
221 {
222         ssize_t len = write(fd, &msg, sizeof msg);
223         TDM_UT_RETURN_FALSE_IF_FAIL(len == sizeof msg);
224
225         if (reply_fd >= 0) {
226                 int reply = _tc_tdm_pipe_read_msg(reply_fd);
227                 TDM_UT_RETURN_FALSE_IF_FAIL(reply == TDM_UT_PIPE_MSG_REPLY);
228         }
229
230         return true;
231 }
232
233 static bool
234 _tc_tdm_server_set_output_dpms(tdm_display *dpy, int msg)
235 {
236         tdm_error ret;
237         tdm_output *output;
238         tdm_output_dpms dpms;
239
240         output = tdm_display_find_output(dpy, "primary", &ret);
241         TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
242         TDM_UT_RETURN_FALSE_IF_FAIL(output != NULL);
243
244         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_get_dpms(output, &dpms) == TDM_ERROR_NONE);
245
246         switch (msg) {
247         case TDM_UT_PIPE_MSG_DPMS_ON:
248                 if (dpms != TDM_OUTPUT_DPMS_ON)
249                         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON) == TDM_ERROR_NONE);
250                 break;
251         case TDM_UT_PIPE_MSG_DPMS_OFF:
252                 if (dpms != TDM_OUTPUT_DPMS_OFF)
253                         TDM_UT_RETURN_FALSE_IF_FAIL(tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF) == TDM_ERROR_NONE);
254                 break;
255         default:
256                 break;
257         }
258
259         return true;
260 }
261
262 static void
263 _tc_tdm_server_run(int *pipe_parent, int *pipe_child)
264 {
265         tdm_display *dpy = NULL;
266         tdm_error ret;
267         struct pollfd fds[2];
268         int tdm_fd, err;
269         int output_count = 0;
270
271         dpy = tdm_display_init(&ret);
272         TDM_UT_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, failed);
273         TDM_UT_GOTO_IF_FAIL(dpy != NULL, failed);
274
275         TDM_UT_GOTO_IF_FAIL(tdm_display_get_output_count(dpy, &output_count) == TDM_ERROR_NONE, failed);
276
277         for (int o = 0; o < output_count; o++) {
278                 tdm_output *output = tdm_display_get_output(dpy, o, &ret);
279                 TDM_UT_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, failed);
280                 TDM_UT_GOTO_IF_FAIL(output != NULL, failed);
281
282                 if (!tc_tdm_output_is_connected(output))
283                         continue;
284
285                 TDM_UT_GOTO_IF_FAIL(tc_tdm_output_prepare(dpy, output, true) == true, failed);
286         }
287
288         TDM_UT_GOTO_IF_FAIL(_tc_tdm_pipe_write_msg(pipe_parent[1], -1, TDM_UT_PIPE_MSG_SERVER_READY) == true, done);
289
290         TDM_INFO("*** server ready ***");
291
292         ret = tdm_display_get_fd(dpy, &tdm_fd);
293         TDM_UT_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
294
295         fds[0].events = POLLIN;
296         fds[0].fd = tdm_fd;
297         fds[0].revents = 0;
298
299         fds[1].events = POLLIN;
300         fds[1].fd = pipe_child[0];
301         fds[1].revents = 0;
302
303         while (1) {
304                 /* make sure all events are flushed to clients before falling in sleep */
305                 tdm_display_flush(dpy);
306
307                 err = poll(fds, 2, -1);
308                 if (err < 0) {
309                         if (errno == EINTR || errno == EAGAIN) {
310                                 continue;
311                         } else {
312                                 TDM_ERR("server-process: poll failed: %m\n");
313                                 goto done;
314                         }
315                 }
316
317                 if (fds[0].revents & POLLIN)
318                         ret = tc_tdm_display_handle_events(dpy);
319
320                 if (fds[1].revents & POLLIN) {
321                         int msg = _tc_tdm_pipe_read_msg(pipe_child[0]);
322                         _tc_tdm_pipe_write_msg(pipe_parent[1], -1, TDM_UT_PIPE_MSG_REPLY);
323
324                         switch (msg) {
325                         case TDM_UT_PIPE_MSG_DPMS_ON:
326                         case TDM_UT_PIPE_MSG_DPMS_OFF:
327                                 _tc_tdm_server_set_output_dpms(dpy, msg);
328                                 break;
329                         case TDM_UT_PIPE_MSG_TERMINATE_SERVER:
330                                 goto done;
331                         default:
332                                 break;
333                         }
334                 }
335         }
336
337 done:
338         if (dpy)
339                 tdm_display_deinit(dpy);
340         return;
341
342 failed:
343         TDM_UT_GOTO_IF_FAIL(_tc_tdm_pipe_write_msg(pipe_parent[1], -1, TDM_UT_PIPE_MSG_SERVER_FAILED) == true, done);
344         TDM_INFO("*** server failed ***");
345
346         if (dpy)
347                 tdm_display_deinit(dpy);
348         return;
349
350 }
351
352 static void _tc_tdm_client_sig_handler(int sig)
353 {
354         TDM_UT_ERR("got signal: %d", sig);
355         kill(TDMClient::server_pid, 9);
356         abort();
357 }
358
359 static pid_t
360 _tc_tdm_client_server_fork(int *pipe_parent, int *pipe_child)
361 {
362         pid_t pid;
363         int msg;
364
365         TDM_UT_GOTO_IF_FAIL(pipe(pipe_parent) == 0, failed);
366         TDM_UT_GOTO_IF_FAIL(pipe(pipe_child) == 0, failed);
367
368         signal(SIGCHLD, SIG_IGN);
369         signal(SIGSEGV, _tc_tdm_client_sig_handler);
370
371         prctl(PR_SET_PDEATHSIG, SIGHUP);
372
373         pid = fork();
374         TDM_UT_GOTO_IF_FAIL(pid >= 0, failed);
375
376         if (pid == 0) {
377                 _tc_tdm_server_run(pipe_parent, pipe_child);
378                 close(pipe_child[0]);
379                 close(pipe_child[1]);
380                 close(pipe_parent[0]);
381                 close(pipe_parent[1]);
382
383 #ifdef TIZEN_TEST_GCOV
384                 __gcov_flush();
385 #endif
386
387                 exit(0);
388         }
389
390         msg = _tc_tdm_pipe_read_msg(pipe_parent[0]);
391         TDM_UT_GOTO_IF_FAIL(msg == TDM_UT_PIPE_MSG_SERVER_READY, failed);
392
393         TDM_INFO("*** server fork done ***");
394
395         return pid;
396
397 failed:
398         return -1;
399 }
400
401 TEST_P(TDMClient, ClientCreate)
402 {
403         tdm_error ret;
404
405         client = tdm_client_create(&ret);
406         ASSERT_EQ(ret, TDM_ERROR_NONE);
407         ASSERT_NE(client, NULL);
408 }
409
410 TEST_P(TDMClient, ClientCreateNullOther)
411 {
412         client = tdm_client_create(NULL);
413         ASSERT_NE(client, NULL);
414 }
415
416 TEST_P(TDMClient, ClientDestroy)
417 {
418         tdm_error ret;
419
420         client = tdm_client_create(&ret);
421         ASSERT_EQ(ret, TDM_ERROR_NONE);
422         ASSERT_NE(client, NULL);
423
424         tdm_client_destroy(client);
425         client = NULL;
426 }
427
428 TEST_P(TDMClient, ClientNullObject)
429 {
430         tdm_client_destroy(NULL);
431 }
432
433 /* tdm_client_get_fd */
434 TEST_P(TDMClient, ClientGetFd)
435 {
436         int fd = TDM_UT_INVALID_VALUE;
437
438         ASSERT_EQ(PrepareClient(), true);
439
440         ASSERT_EQ(tdm_client_get_fd(client, &fd), TDM_ERROR_NONE);
441         ASSERT_GE(fd, 0);
442 }
443
444 TEST_P(TDMClient, ClientGetFdNullObject)
445 {
446         int fd = TDM_UT_INVALID_VALUE;
447         ASSERT_EQ(tdm_client_get_fd(NULL, &fd), TDM_ERROR_INVALID_PARAMETER);
448         ASSERT_EQ(fd, TDM_UT_INVALID_VALUE);
449 }
450
451 TEST_P(TDMClient, ClientGetFdNullOther)
452 {
453         ASSERT_EQ(PrepareClient(), true);
454
455         ASSERT_EQ(tdm_client_get_fd(client, NULL), TDM_ERROR_INVALID_PARAMETER);
456 }
457
458 static void
459 _tc_tdm_client_vblank_cb(unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
460 {
461         bool *done = (bool *)user_data;
462         if (done)
463                 *done = true;
464 }
465
466 /* tdm_client_handle_events_timeout */
467 TEST_P(TDMClient, ClientHandleEvent)
468 {
469         bool done = false;
470
471         ASSERT_EQ(PrepareClient(), true);
472
473         ASSERT_EQ(tdm_client_wait_vblank(client, NULL, 1, 1, 0, _tc_tdm_client_vblank_cb, &done), TDM_ERROR_NONE);
474         ASSERT_EQ(done, false);
475
476         while (!done)
477                 ASSERT_EQ(tdm_client_handle_events(client), TDM_ERROR_NONE);
478 }
479
480 TEST_P(TDMClient, ClientHandleEventNullObject)
481 {
482         ASSERT_EQ(tdm_client_handle_events(NULL), TDM_ERROR_INVALID_PARAMETER);
483 }
484
485 /* tdm_client_wait_vblank, deprecated */
486 TEST_P(TDMClient, ClientWaitVblank)
487 {
488         bool done = false;
489
490         ASSERT_EQ(PrepareClient(), true);
491
492         ASSERT_EQ(tdm_client_wait_vblank(client, NULL, 1, 1, 0, _tc_tdm_client_vblank_cb, &done), TDM_ERROR_NONE);
493         ASSERT_EQ(done, false);
494
495         while (!done)
496                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
497 }
498
499 /* tdm_client_get_output */
500 TEST_P(TDMClient, ClientGetOutput)
501 {
502         tdm_error ret;
503
504         ASSERT_EQ(PrepareClient(), true);
505
506         output = tdm_client_get_output(client, NULL, &ret);
507         ASSERT_EQ(ret, TDM_ERROR_NONE);
508         ASSERT_NE(output, NULL);
509 }
510
511 TEST_P(TDMClient, ClientGetOutputPrimary)
512 {
513         tdm_error ret;
514
515         ASSERT_EQ(PrepareClient(), true);
516
517         output = tdm_client_get_output(client, (char*)"primary", &ret);
518         ASSERT_EQ(ret, TDM_ERROR_NONE);
519         ASSERT_NE(output, NULL);
520 }
521
522 TEST_P(TDMClient, ClientGetOutputDefault)
523 {
524         tdm_error ret;
525
526         ASSERT_EQ(PrepareClient(), true);
527
528         output = tdm_client_get_output(client, (char*)"default", &ret);
529         ASSERT_EQ(ret, TDM_ERROR_NONE);
530         ASSERT_NE(output, NULL);
531 }
532
533 TEST_P(TDMClient, ClientGetOutputInvalidName)
534 {
535         tdm_error ret;
536
537         ASSERT_EQ(PrepareClient(), true);
538
539         output = tdm_client_get_output(client, (char*)"invalid", &ret);
540         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
541         ASSERT_EQ(output, NULL);
542 }
543
544 TEST_P(TDMClient, ClientGetOutputNullObject)
545 {
546         tdm_error ret;
547
548         output = tdm_client_get_output(NULL, NULL, &ret);
549         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
550         ASSERT_EQ(output, NULL);
551 }
552
553 TEST_P(TDMClient, ClientGetOutputNullOther)
554 {
555         ASSERT_EQ(PrepareClient(), true);
556
557         output = tdm_client_get_output(client, NULL, NULL);
558         ASSERT_NE(output, NULL);
559 }
560
561 static void
562 _tc_tdm_client_output_change_dpms_cb(tdm_client_output *output,
563                                                                          tdm_output_change_type type,
564                                                                          tdm_value value,
565                                                                          void *user_data)
566 {
567         bool *done = (bool *)user_data;
568
569         switch (type) {
570         case TDM_OUTPUT_CHANGE_DPMS:
571                 if (done)
572                         *done = true;
573                 break;
574         default:
575                 break;
576         }
577 }
578
579 /* tdm_client_output_add_change_handler */
580 TEST_P(TDMClient, ClientOutputAddChangeHandler)
581 {
582         bool done = false;
583         tdm_output_dpms dpms;
584
585         ASSERT_EQ(PrepareClient(), true);
586         ASSERT_EQ(PrepareOutput(), true);
587
588         ASSERT_EQ(tdm_client_output_add_change_handler(output, _tc_tdm_client_output_change_dpms_cb, &done), TDM_ERROR_NONE);
589         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_OFF), true);
590
591         while (!done)
592                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
593
594         ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
595         ASSERT_EQ(dpms, TDM_OUTPUT_DPMS_OFF);
596
597         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_ON), true);
598         while (dpms != TDM_OUTPUT_DPMS_ON) {
599                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
600                 ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
601         }
602 }
603
604 TEST_P(TDMClient, ClientOutputAddChangeHandlerTwice)
605 {
606         ASSERT_EQ(PrepareClient(), true);
607         ASSERT_EQ(PrepareOutput(), true);
608
609         ASSERT_EQ(tdm_client_output_add_change_handler(output, _tc_tdm_client_output_change_dpms_cb, NULL), TDM_ERROR_NONE);
610         ASSERT_EQ(tdm_client_output_add_change_handler(output, _tc_tdm_client_output_change_dpms_cb, NULL), TDM_ERROR_BAD_REQUEST);
611 }
612
613 TEST_P(TDMClient, ClientOutputAddChangeHandlerNullObject)
614 {
615         ASSERT_EQ(tdm_client_output_add_change_handler(NULL, _tc_tdm_client_output_change_dpms_cb, NULL), TDM_ERROR_INVALID_PARAMETER);
616 }
617
618 TEST_P(TDMClient, ClientOutputAddChangeHandlerNullOther)
619 {
620         ASSERT_EQ(PrepareClient(), true);
621         ASSERT_EQ(PrepareOutput(), true);
622
623         ASSERT_EQ(tdm_client_output_add_change_handler(output, NULL, NULL), TDM_ERROR_INVALID_PARAMETER);
624 }
625
626 /* tdm_client_output_remove_change_handler */
627 TEST_P(TDMClient, ClientOutputRemoveChangeHandler)
628 {
629         ASSERT_EQ(PrepareClient(), true);
630         ASSERT_EQ(PrepareOutput(), true);
631
632         ASSERT_EQ(tdm_client_output_add_change_handler(output, _tc_tdm_client_output_change_dpms_cb, NULL), TDM_ERROR_NONE);
633         tdm_client_output_remove_change_handler(output, _tc_tdm_client_output_change_dpms_cb, NULL);
634 }
635
636 TEST_P(TDMClient, ClientOutputRemoveChangeHandlerDifferentData)
637 {
638         bool done = (bool)TDM_UT_INVALID_VALUE;
639
640         ASSERT_EQ(PrepareClient(), true);
641         ASSERT_EQ(PrepareOutput(), true);
642
643         ASSERT_EQ(tdm_client_output_add_change_handler(output, _tc_tdm_client_output_change_dpms_cb, &done), TDM_ERROR_NONE);
644         tdm_client_output_remove_change_handler(output, _tc_tdm_client_output_change_dpms_cb, NULL);
645 }
646
647 static void
648 _tc_tdm_client_output_change_dpms_cb2(tdm_client_output *output,
649                                                                           tdm_output_change_type type,
650                                                                           tdm_value value,
651                                                                           void *user_data)
652 {
653         switch (type) {
654         case TDM_OUTPUT_CHANGE_DPMS:
655                 tdm_client_output_remove_change_handler(output, _tc_tdm_client_output_change_dpms_cb2, user_data);
656                 break;
657         default:
658                 break;
659         }
660 }
661
662 TEST_P(TDMClient, ClientOutputRemoveChangeHandlerInHandler)
663 {
664         tdm_output_dpms dpms = TDM_OUTPUT_DPMS_ON;
665
666         ASSERT_EQ(PrepareClient(), true);
667         ASSERT_EQ(PrepareOutput(), true);
668
669         ASSERT_EQ(tdm_client_output_add_change_handler(output, _tc_tdm_client_output_change_dpms_cb2, NULL), TDM_ERROR_NONE);
670         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_OFF), true);
671         ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
672         while (dpms != TDM_OUTPUT_DPMS_OFF) {
673                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
674                 ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
675         }
676
677         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_ON), true);
678         while (dpms != TDM_OUTPUT_DPMS_ON)
679                 ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
680 }
681
682 TEST_P(TDMClient, ClientOutputRemoveChangeHandlerNullObject)
683 {
684         tdm_client_output_remove_change_handler(NULL, _tc_tdm_client_output_change_dpms_cb, NULL);
685 }
686
687 TEST_P(TDMClient, ClientOutputRemoveChangeHandlerNullOther)
688 {
689         ASSERT_EQ(PrepareClient(), true);
690         ASSERT_EQ(PrepareOutput(), true);
691
692         tdm_client_output_remove_change_handler(output, NULL, NULL);
693 }
694
695 /* tdm_client_output_get_refresh_rate */
696 TEST_P(TDMClient, ClientOutputGetRefreshRate)
697 {
698         unsigned int refresh = 0;
699
700         ASSERT_EQ(PrepareClient(), true);
701         ASSERT_EQ(PrepareOutput(), true);
702
703         ASSERT_EQ(tdm_client_output_get_refresh_rate(output, &refresh), TDM_ERROR_NONE);
704         ASSERT_GT(refresh, 0);
705 }
706
707 TEST_P(TDMClient, ClientOutputGetRefreshRateNullObject)
708 {
709         unsigned int refresh = (unsigned int)TDM_UT_INVALID_VALUE;
710
711         ASSERT_EQ(tdm_client_output_get_refresh_rate(NULL, &refresh), TDM_ERROR_INVALID_PARAMETER);
712         ASSERT_EQ(refresh, (unsigned int)TDM_UT_INVALID_VALUE);
713 }
714
715 TEST_P(TDMClient, ClientOutputGetRefreshRateNullOther)
716 {
717         ASSERT_EQ(PrepareClient(), true);
718         ASSERT_EQ(PrepareOutput(), true);
719
720         ASSERT_EQ(tdm_client_output_get_refresh_rate(output, NULL), TDM_ERROR_INVALID_PARAMETER);
721 }
722
723 /* tdm_client_output_get_refresh_rate */
724 TEST_P(TDMClient, ClientOutputGetConnStatus)
725 {
726         tdm_output_conn_status status = (tdm_output_conn_status)TDM_UT_INVALID_VALUE;
727
728         ASSERT_EQ(PrepareClient(), true);
729         ASSERT_EQ(PrepareOutput(), true);
730
731         ASSERT_EQ(tdm_client_output_get_conn_status(output, &status), TDM_ERROR_NONE);
732         ASSERT_NE(status, (tdm_output_conn_status)TDM_UT_INVALID_VALUE);
733 }
734
735 TEST_P(TDMClient, ClientOutputGetConnStatusNullObject)
736 {
737         tdm_output_conn_status status = (tdm_output_conn_status)TDM_UT_INVALID_VALUE;
738
739         ASSERT_EQ(tdm_client_output_get_conn_status(NULL, &status), TDM_ERROR_INVALID_PARAMETER);
740         ASSERT_EQ(status, (tdm_output_conn_status)TDM_UT_INVALID_VALUE);
741 }
742
743 TEST_P(TDMClient, ClientOutputGetConnStatusNullOther)
744 {
745         ASSERT_EQ(PrepareClient(), true);
746         ASSERT_EQ(PrepareOutput(), true);
747
748         ASSERT_EQ(tdm_client_output_get_conn_status(output, NULL), TDM_ERROR_INVALID_PARAMETER);
749 }
750
751 /* tdm_client_output_get_dpms */
752 TEST_P(TDMClient, ClientOutputGetDpms)
753 {
754         tdm_output_dpms dpms = (tdm_output_dpms)TDM_UT_INVALID_VALUE;
755
756         ASSERT_EQ(PrepareClient(), true);
757         ASSERT_EQ(PrepareOutput(), true);
758
759         ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
760         ASSERT_NE(dpms, (tdm_output_dpms)TDM_UT_INVALID_VALUE);
761 }
762
763 TEST_P(TDMClient, ClientOutputGetDpmsNullObject)
764 {
765         tdm_output_dpms dpms = (tdm_output_dpms)TDM_UT_INVALID_VALUE;
766
767         ASSERT_EQ(tdm_client_output_get_dpms(NULL, &dpms), TDM_ERROR_INVALID_PARAMETER);
768         ASSERT_EQ(dpms, (tdm_output_dpms)TDM_UT_INVALID_VALUE);
769 }
770
771 TEST_P(TDMClient, ClientOutputGetDpmsNullOther)
772 {
773         ASSERT_EQ(PrepareClient(), true);
774         ASSERT_EQ(PrepareOutput(), true);
775
776         ASSERT_EQ(tdm_client_output_get_dpms(output, NULL), TDM_ERROR_INVALID_PARAMETER);
777 }
778
779 /* tdm_client_output_create_vblank */
780 TEST_P(TDMClient, ClientOutputCreateVblank)
781 {
782         tdm_error ret;
783
784         ASSERT_EQ(PrepareClient(), true);
785         ASSERT_EQ(PrepareOutput(), true);
786
787         vblank = tdm_client_output_create_vblank(output, &ret);
788         ASSERT_EQ(ret, TDM_ERROR_NONE);
789         ASSERT_NE(vblank, NULL);
790 }
791
792 TEST_P(TDMClient, ClientOutputCreateVblankNullObject)
793 {
794         tdm_error ret;
795
796         vblank = tdm_client_output_create_vblank(NULL, &ret);
797         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
798         ASSERT_EQ(vblank, NULL);
799 }
800
801 TEST_P(TDMClient, ClientOutputCreateVblankNullOther)
802 {
803         ASSERT_EQ(PrepareClient(), true);
804         ASSERT_EQ(PrepareOutput(), true);
805
806         vblank = tdm_client_output_create_vblank(output, NULL);
807         ASSERT_NE(vblank, NULL);
808 }
809
810 /* tdm_client_vblank_destroy */
811 TEST_P(TDMClient, ClientVblankDestroy)
812 {
813         tdm_error ret;
814
815         ASSERT_EQ(PrepareClient(), true);
816         ASSERT_EQ(PrepareOutput(), true);
817
818         vblank = tdm_client_output_create_vblank(output, &ret);
819         ASSERT_EQ(ret, TDM_ERROR_NONE);
820         ASSERT_NE(vblank, NULL);
821
822         tdm_client_vblank_destroy(vblank);
823         vblank = NULL;
824 }
825
826 TEST_P(TDMClient, ClientVblankDestroyNullObject)
827 {
828         tdm_client_vblank_destroy(NULL);
829 }
830
831 /* tdm_client_vblank_set_name */
832 TEST_P(TDMClient, ClientVblankSetName)
833 {
834         ASSERT_EQ(PrepareClient(), true);
835         ASSERT_EQ(PrepareOutput(), true);
836         ASSERT_EQ(PrepareVblank(), true);
837
838         ASSERT_EQ(tdm_client_vblank_set_name(vblank, TDM_UT_VBLANK_NAME), TDM_ERROR_NONE);
839 }
840
841 TEST_P(TDMClient, ClientVblankSetNameTwice)
842 {
843         ASSERT_EQ(PrepareClient(), true);
844         ASSERT_EQ(PrepareOutput(), true);
845         ASSERT_EQ(PrepareVblank(), true);
846
847         ASSERT_EQ(tdm_client_vblank_set_name(vblank, TDM_UT_VBLANK_NAME), TDM_ERROR_NONE);
848         ASSERT_EQ(tdm_client_vblank_set_name(vblank, TDM_UT_VBLANK_NAME), TDM_ERROR_NONE);
849 }
850
851 TEST_P(TDMClient, ClientVblankSetNameNullObject)
852 {
853         ASSERT_EQ(tdm_client_vblank_set_name(NULL, TDM_UT_VBLANK_NAME), TDM_ERROR_INVALID_PARAMETER);
854 }
855
856 /* tdm_client_vblank_set_sync */
857 TEST_P(TDMClient, ClientVblankSetSync)
858 {
859         ASSERT_EQ(PrepareClient(), true);
860         ASSERT_EQ(PrepareOutput(), true);
861         ASSERT_EQ(PrepareVblank(), true);
862
863         ASSERT_EQ(tdm_client_vblank_set_sync(vblank, 1), TDM_ERROR_NONE);
864 }
865
866 TEST_P(TDMClient, ClientVblankSetSyncTwice)
867 {
868         ASSERT_EQ(PrepareClient(), true);
869         ASSERT_EQ(PrepareOutput(), true);
870         ASSERT_EQ(PrepareVblank(), true);
871
872         ASSERT_EQ(tdm_client_vblank_set_sync(vblank, 1), TDM_ERROR_NONE);
873         ASSERT_EQ(tdm_client_vblank_set_sync(vblank, 1), TDM_ERROR_NONE);
874 }
875
876 TEST_P(TDMClient, ClientVblankSetSyncNullObject)
877 {
878         ASSERT_EQ(tdm_client_vblank_set_sync(NULL, 1), TDM_ERROR_INVALID_PARAMETER);
879 }
880
881 /* tdm_client_vblank_set_fps */
882 TEST_P(TDMClient, ClientVblankSetFps)
883 {
884         ASSERT_EQ(PrepareClient(), true);
885         ASSERT_EQ(PrepareOutput(), true);
886         ASSERT_EQ(PrepareVblank(), true);
887
888         ASSERT_EQ(tdm_client_vblank_set_fps(vblank, 30), TDM_ERROR_NONE);
889 }
890
891 TEST_P(TDMClient, ClientVblankSetFpsTwice)
892 {
893         ASSERT_EQ(PrepareClient(), true);
894         ASSERT_EQ(PrepareOutput(), true);
895         ASSERT_EQ(PrepareVblank(), true);
896
897         ASSERT_EQ(tdm_client_vblank_set_fps(vblank, 30), TDM_ERROR_NONE);
898         ASSERT_EQ(tdm_client_vblank_set_fps(vblank, 30), TDM_ERROR_NONE);
899 }
900
901 TEST_P(TDMClient, ClientVblankSetFpsNullObject)
902 {
903         ASSERT_EQ(tdm_client_vblank_set_fps(NULL, 30), TDM_ERROR_INVALID_PARAMETER);
904 }
905
906 /* tdm_client_vblank_set_offset */
907 TEST_P(TDMClient, ClientVblankSetOffset)
908 {
909         ASSERT_EQ(PrepareClient(), true);
910         ASSERT_EQ(PrepareOutput(), true);
911         ASSERT_EQ(PrepareVblank(), true);
912
913         ASSERT_EQ(tdm_client_vblank_set_offset(vblank, 10), TDM_ERROR_NONE);
914 }
915
916 TEST_P(TDMClient, ClientVblankSetOffsetTwice)
917 {
918         ASSERT_EQ(PrepareClient(), true);
919         ASSERT_EQ(PrepareOutput(), true);
920         ASSERT_EQ(PrepareVblank(), true);
921
922         ASSERT_EQ(tdm_client_vblank_set_offset(vblank, 10), TDM_ERROR_NONE);
923         ASSERT_EQ(tdm_client_vblank_set_offset(vblank, 10), TDM_ERROR_NONE);
924 }
925
926 TEST_P(TDMClient, ClientVblankSetOffsetNullObject)
927 {
928         ASSERT_EQ(tdm_client_vblank_set_offset(NULL, 10), TDM_ERROR_INVALID_PARAMETER);
929 }
930
931 /* tdm_client_vblank_set_enable_fake */
932 TEST_P(TDMClient, ClientVblankSetEnableFake)
933 {
934         ASSERT_EQ(PrepareClient(), true);
935         ASSERT_EQ(PrepareOutput(), true);
936         ASSERT_EQ(PrepareVblank(), true);
937
938         ASSERT_EQ(tdm_client_vblank_set_enable_fake(vblank, 1), TDM_ERROR_NONE);
939 }
940
941 TEST_P(TDMClient, ClientVblankSetEnableFakeTwice)
942 {
943         ASSERT_EQ(PrepareClient(), true);
944         ASSERT_EQ(PrepareOutput(), true);
945         ASSERT_EQ(PrepareVblank(), true);
946
947         ASSERT_EQ(tdm_client_vblank_set_enable_fake(vblank, 1), TDM_ERROR_NONE);
948         ASSERT_EQ(tdm_client_vblank_set_enable_fake(vblank, 1), TDM_ERROR_NONE);
949 }
950
951 TEST_P(TDMClient, ClientVblankSetEnableFakeNullObject)
952 {
953         ASSERT_EQ(tdm_client_vblank_set_enable_fake(NULL, 1), TDM_ERROR_INVALID_PARAMETER);
954 }
955
956 static void
957 _tc_tdm_client_vblank_cb2(tdm_client_vblank *vblank,
958                                                   tdm_error error,
959                                                   unsigned int sequence,
960                                                   unsigned int tv_sec,
961                                                   unsigned int tv_usec,
962                                                   void *user_data)
963 {
964         bool *done = (bool *)user_data;
965         if (done)
966                 *done = true;
967 }
968
969 /* tdm_client_vblank_wait */
970 TEST_P(TDMClient, ClientVblankWait)
971 {
972         bool done;
973
974         ASSERT_EQ(PrepareClient(), true);
975         ASSERT_EQ(PrepareOutput(), true);
976         ASSERT_EQ(PrepareVblank(), true);
977
978         done = false;
979         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done), TDM_ERROR_NONE);
980
981         start = tdm_helper_get_time();
982         while (!done)
983                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
984         end = tdm_helper_get_time();
985
986         /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
987         ASSERT_LT((end - start), (vrefresh_interval + vrefresh_interval));
988 }
989
990 TEST_P(TDMClient, ClientVblankWaitFewTime)
991 {
992         bool done1, done2, done3;
993
994         ASSERT_EQ(PrepareClient(), true);
995         ASSERT_EQ(PrepareOutput(), true);
996         ASSERT_EQ(PrepareVblank(), true);
997
998         done1 = done2 = done3 = false;
999         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done1), TDM_ERROR_NONE);
1000         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done2), TDM_ERROR_NONE);
1001         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done3), TDM_ERROR_NONE);
1002
1003         start = tdm_helper_get_time();
1004         while (!done1 || !done2 || !done3)
1005                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1006         end = tdm_helper_get_time();
1007
1008         /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1009         ASSERT_LT((end - start), (vrefresh_interval + vrefresh_interval));
1010
1011 }
1012
1013 TEST_P(TDMClient, ClientVblankWaitInterval0)
1014 {
1015         ASSERT_EQ(PrepareClient(), true);
1016         ASSERT_EQ(PrepareOutput(), true);
1017         ASSERT_EQ(PrepareVblank(), true);
1018
1019         ASSERT_EQ(tdm_client_vblank_wait(vblank, 0, _tc_tdm_client_vblank_cb2, NULL), TDM_ERROR_INVALID_PARAMETER);
1020 }
1021
1022 TEST_P(TDMClient, ClientVblankWaitInterval)
1023 {
1024         bool done;
1025
1026         ASSERT_EQ(PrepareClient(), true);
1027         ASSERT_EQ(PrepareOutput(), true);
1028         ASSERT_EQ(PrepareVblank(), true);
1029
1030         /* start from 1 */
1031         for (int t = 1; t < 10; t++) {
1032                 done = false;
1033                 ASSERT_EQ(tdm_client_vblank_wait(vblank, t, _tc_tdm_client_vblank_cb2, &done), TDM_ERROR_NONE);
1034
1035                 start = tdm_helper_get_time();
1036                 while (!done)
1037                         ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1038                 end = tdm_helper_get_time();
1039
1040                 /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1041                 ASSERT_GT((end - start), (vrefresh_interval * (t - 1)));
1042                 ASSERT_LT((end - start), (vrefresh_interval * t + vrefresh_interval));
1043         }
1044 }
1045
1046 static void
1047 _tc_tdm_client_vblank_cb3(tdm_client_vblank *vblank,
1048                                                   tdm_error error,
1049                                                   unsigned int sequence,
1050                                                   unsigned int tv_sec,
1051                                                   unsigned int tv_usec,
1052                                                   void *user_data)
1053 {
1054         unsigned int *cur_seq = (unsigned int *)user_data;
1055         if (cur_seq)
1056                 *cur_seq = sequence;
1057 }
1058
1059 TEST_P(TDMClient, ClientVblankWaitSeq)
1060 {
1061         ASSERT_EQ(PrepareClient(), true);
1062         ASSERT_EQ(PrepareOutput(), true);
1063         ASSERT_EQ(PrepareVblank(), true);
1064
1065         for (int t = 0; t < 10; t++) {
1066                 unsigned int cur_seq = 0, temp = 0;
1067
1068                 ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb3, &cur_seq), TDM_ERROR_NONE);
1069                 while (cur_seq == 0)
1070                         ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1071
1072                 start = tdm_helper_get_time();
1073                 ASSERT_EQ(tdm_client_vblank_wait_seq(vblank, cur_seq + 1, _tc_tdm_client_vblank_cb3, &temp), TDM_ERROR_NONE);
1074                 while (temp == 0)
1075                         ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1076                 end = tdm_helper_get_time();
1077
1078                 /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1079                 ASSERT_LT((end - start), (vrefresh_interval + vrefresh_interval));
1080         }
1081 }
1082
1083 TEST_P(TDMClient, ClientVblankWaitSeqInterval)
1084 {
1085         ASSERT_EQ(PrepareClient(), true);
1086         ASSERT_EQ(PrepareOutput(), true);
1087         ASSERT_EQ(PrepareVblank(), true);
1088
1089         /* start from 1 */
1090         for (int t = 1; t < 10; t++) {
1091                 unsigned int cur_seq = 0, temp = 0;
1092
1093                 ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb3, &cur_seq), TDM_ERROR_NONE);
1094                 while (cur_seq == 0)
1095                         ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1096
1097                 start = tdm_helper_get_time();
1098                 ASSERT_EQ(tdm_client_vblank_wait_seq(vblank, cur_seq + t, _tc_tdm_client_vblank_cb3, &temp), TDM_ERROR_NONE);
1099                 while (temp == 0)
1100                         ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1101                 end = tdm_helper_get_time();
1102
1103                 /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1104                 ASSERT_GT((end - start), (vrefresh_interval * (t - 1)));
1105                 ASSERT_LT((end - start), (vrefresh_interval * t + vrefresh_interval));
1106         }
1107 }
1108
1109 TEST_P(TDMClient, ClientVblankWaitSetOffset)
1110 {
1111         bool done;
1112
1113         ASSERT_EQ(PrepareClient(), true);
1114         ASSERT_EQ(PrepareOutput(), true);
1115         ASSERT_EQ(PrepareVblank(), true);
1116
1117         ASSERT_EQ(tdm_client_vblank_set_offset(vblank, 100), TDM_ERROR_NONE);
1118
1119         done = false;
1120         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done), TDM_ERROR_NONE);
1121
1122         start = tdm_helper_get_time();
1123         while (!done)
1124                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1125         end = tdm_helper_get_time();
1126
1127         /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1128         ASSERT_GT((end - start), (0.1));
1129         ASSERT_LT((end - start), (vrefresh_interval + vrefresh_interval + 0.1));
1130 }
1131
1132 TEST_P(TDMClient, ClientVblankWaitSetFps)
1133 {
1134         bool done;
1135         double interval;
1136         unsigned int fps = 10;
1137
1138         ASSERT_EQ(PrepareClient(), true);
1139         ASSERT_EQ(PrepareOutput(), true);
1140         ASSERT_EQ(PrepareVblank(), true);
1141
1142         ASSERT_EQ(tdm_client_vblank_set_fps(vblank, fps), TDM_ERROR_NONE);
1143         interval = 1.0 / (double)fps;
1144
1145         done = false;
1146         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done), TDM_ERROR_NONE);
1147
1148         start = tdm_helper_get_time();
1149         while (!done)
1150                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1151         end = tdm_helper_get_time();
1152
1153         /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1154         ASSERT_GT((end - start), (interval - vrefresh_interval));
1155         ASSERT_LT((end - start), (interval + vrefresh_interval));
1156 }
1157
1158 #if 0
1159
1160 TEST_P(TDMVblank, VblankWaitEnableDisableGlobalFps)
1161 {
1162         TDM_UT_SKIP_FLAG(has_outputs);
1163
1164         unsigned int fps = (unsigned int)TDM_UT_INVALID_VALUE;
1165         double vrefresh_interval;
1166         unsigned int cur_seq[3];
1167         unsigned int global_fps = 5;
1168         double start, end, interval;
1169
1170         ASSERT_EQ(TestPrepareOutput(), true);
1171         ASSERT_EQ(TestCreateVblanks3(), true);
1172         ASSERT_EQ(vblank_count, 3);
1173
1174         ASSERT_EQ(tdm_vblank_get_fps(vblanks[0], &fps), TDM_ERROR_NONE);
1175         ASSERT_TRUE(fps >= 30 && fps != (unsigned int)TDM_UT_INVALID_VALUE);
1176         vrefresh_interval = 1.0 / (double)fps;
1177
1178         for (int v = 0; v < 3; v++)
1179                 ASSERT_EQ(tdm_vblank_set_fixed_fps(vblanks[v], 10 * (v + 1)), TDM_ERROR_NONE);
1180
1181         /* enable test */
1182         tdm_vblank_enable_global_fps(1, global_fps);
1183         interval = 1.0 / (double)global_fps;
1184
1185         for (int v = 0; v < 3; v++) {
1186                 cur_seq[v] = 0;
1187                 ASSERT_EQ(tdm_vblank_wait(vblanks[v], 0, 0, 1, _tc_tdm_vblank_cb, &cur_seq[v]), TDM_ERROR_NONE);
1188         }
1189
1190         start = tdm_helper_get_time();
1191         while (cur_seq[0] == 0)
1192                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1193         end = tdm_helper_get_time();
1194
1195         ASSERT_NE(cur_seq[1], 0);
1196         ASSERT_NE(cur_seq[2], 0);
1197
1198         /* "+- vrefresh_interval" consider the delay of socket communication between kernel and platform */
1199         ASSERT_GT((end - start), (interval - vrefresh_interval));
1200         ASSERT_LT((end - start), (interval + vrefresh_interval));
1201
1202         /* disable test */
1203         tdm_vblank_enable_global_fps(0, 0);
1204
1205         for (int v = 0; v < 3; v++) {
1206                 cur_seq[v] = 0;
1207                 ASSERT_EQ(tdm_vblank_wait(vblanks[v], 0, 0, 1, _tc_tdm_vblank_cb, &cur_seq[v]), TDM_ERROR_NONE);
1208         }
1209
1210         while (cur_seq[0] == 0)
1211                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1212         ASSERT_EQ(cur_seq[1], 0);
1213         ASSERT_EQ(cur_seq[2], 0);
1214
1215         while (cur_seq[1] == 0)
1216                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1217         ASSERT_EQ(cur_seq[2], 0);
1218 }
1219
1220 TEST_P(TDMVblank, VblankWaitIgnoreGlobalFps)
1221 {
1222         TDM_UT_SKIP_FLAG(has_outputs);
1223
1224         unsigned int fps = (unsigned int)TDM_UT_INVALID_VALUE;
1225         unsigned int cur_seq[3];
1226         unsigned int global_fps = 5;
1227         double start, end, interval;
1228
1229         ASSERT_EQ(TestPrepareOutput(), true);
1230         ASSERT_EQ(TestCreateVblanks3(), true);
1231         ASSERT_EQ(vblank_count, 3);
1232
1233         ASSERT_EQ(tdm_vblank_get_fps(vblanks[0], &fps), TDM_ERROR_NONE);
1234         ASSERT_TRUE(fps >= 30 && fps != (unsigned int)TDM_UT_INVALID_VALUE);
1235         interval = 1.0 / (double)fps;
1236
1237         /* 2nd vblank will ignore the global fps. */
1238         ASSERT_EQ(tdm_vblank_ignore_global_fps(vblanks[1], 1), TDM_ERROR_NONE);
1239
1240         tdm_vblank_enable_global_fps(1, global_fps);
1241
1242         for (int v = 0; v < 3; v++) {
1243                 cur_seq[v] = 0;
1244                 ASSERT_EQ(tdm_vblank_wait(vblanks[v], 0, 0, 1, _tc_tdm_vblank_cb, &cur_seq[v]), TDM_ERROR_NONE);
1245         }
1246
1247         start = tdm_helper_get_time();
1248         while (cur_seq[1] == 0)
1249                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1250         end = tdm_helper_get_time();
1251
1252         ASSERT_EQ(cur_seq[0], 0);
1253         ASSERT_EQ(cur_seq[2], 0);
1254
1255         /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1256         ASSERT_LT((end - start), (interval + interval));
1257
1258         while (cur_seq[0] == 0)
1259                 ASSERT_EQ(tc_tdm_display_handle_events(dpy), TDM_ERROR_NONE);
1260         ASSERT_NE(cur_seq[2], 0);
1261 }
1262
1263 #endif
1264
1265 TEST_P(TDMClient, ClientVblankWaitNullObject)
1266 {
1267         unsigned int cur_seq = 0;
1268
1269         ASSERT_EQ(tdm_client_vblank_wait(NULL, 1, _tc_tdm_client_vblank_cb3, &cur_seq), TDM_ERROR_INVALID_PARAMETER);
1270 }
1271
1272 TEST_P(TDMClient, ClientVblankWaitNullOther)
1273 {
1274         ASSERT_EQ(PrepareClient(), true);
1275         ASSERT_EQ(PrepareOutput(), true);
1276         ASSERT_EQ(PrepareVblank(), true);
1277
1278         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, NULL, NULL), TDM_ERROR_INVALID_PARAMETER);
1279 }
1280
1281 TEST_P(TDMClient, ClientVblankWaitDpmsOff)
1282 {
1283         tdm_output_dpms dpms = (tdm_output_dpms)TDM_UT_INVALID_VALUE;
1284
1285         ASSERT_EQ(PrepareClient(), true);
1286         ASSERT_EQ(PrepareOutput(), true);
1287         ASSERT_EQ(PrepareVblank(), true);
1288
1289         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_OFF), true);
1290         while (dpms != TDM_OUTPUT_DPMS_OFF)
1291                 ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
1292         ASSERT_EQ(dpms, TDM_OUTPUT_DPMS_OFF);
1293
1294         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, NULL), TDM_ERROR_DPMS_OFF);
1295
1296         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_ON), true);
1297         while (dpms != TDM_OUTPUT_DPMS_ON)
1298                 ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
1299 }
1300
1301 TEST_P(TDMClient, ClientVblankWaitSetEnableFakeDpmsOff)
1302 {
1303         tdm_output_dpms dpms = (tdm_output_dpms)TDM_UT_INVALID_VALUE;
1304         bool done;
1305
1306         ASSERT_EQ(PrepareClient(), true);
1307         ASSERT_EQ(PrepareOutput(), true);
1308         ASSERT_EQ(PrepareVblank(), true);
1309
1310         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_OFF), true);
1311         while (dpms != TDM_OUTPUT_DPMS_OFF)
1312                 ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
1313
1314         ASSERT_EQ(tdm_client_vblank_set_enable_fake(vblank, 1), TDM_ERROR_NONE);
1315
1316         done = false;
1317         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done), TDM_ERROR_NONE);
1318
1319         while (!done)
1320                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1321
1322         ASSERT_EQ(_tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_DPMS_ON), true);
1323         while (dpms != TDM_OUTPUT_DPMS_ON)
1324                 ASSERT_EQ(tdm_client_output_get_dpms(output, &dpms), TDM_ERROR_NONE);
1325 }
1326
1327 /* tdm_client_vblank_wait */
1328 TEST_P(TDMClient, ClientVblankIsWaiting)
1329 {
1330         bool done;
1331         unsigned int waiting;
1332
1333         ASSERT_EQ(PrepareClient(), true);
1334         ASSERT_EQ(PrepareOutput(), true);
1335         ASSERT_EQ(PrepareVblank(), true);
1336
1337         done = false;
1338         ASSERT_EQ(tdm_client_vblank_wait(vblank, 1, _tc_tdm_client_vblank_cb2, &done), TDM_ERROR_NONE);
1339
1340         waiting = tdm_client_vblank_is_waiting(vblank);
1341         ASSERT_EQ(waiting, 1);
1342
1343         start = tdm_helper_get_time();
1344         while (!done)
1345                 ASSERT_EQ(tdm_client_handle_events_timeout(client, 3000), TDM_ERROR_NONE);
1346         end = tdm_helper_get_time();
1347
1348         /* "+ vrefresh_interval" consider the delay of socket communication between kernel and platform */
1349         ASSERT_LT((end - start), (vrefresh_interval + vrefresh_interval));
1350
1351         waiting = tdm_client_vblank_is_waiting(vblank);
1352         ASSERT_EQ(waiting, 0);
1353 }
1354
1355 /* tdm_client_vblank_wait */
1356 TEST_P(TDMClient, ClientVblankIsWaitingNullObject)
1357 {
1358         unsigned int waiting = tdm_client_vblank_is_waiting(NULL);
1359         ASSERT_EQ(waiting, 0);
1360 }
1361
1362 TEST_P(TDMClient, ClientCreateVOutput)
1363 {
1364         tdm_error ret;
1365         const char name[TDM_NAME_LEN] = "Virtual Output";
1366
1367         ASSERT_EQ(PrepareClient(), true);
1368         
1369         voutput = tdm_client_create_voutput(client, name, &ret);
1370         ASSERT_EQ(ret, TDM_ERROR_NONE);
1371         ASSERT_NE(voutput, NULL);
1372
1373         tdm_client_voutput_destroy(voutput);
1374 }
1375
1376 class TDMVirtualOutput : public ::testing::Test
1377 {
1378 public:
1379         TDMVirtualOutput() {};
1380         ~TDMVirtualOutput() {};
1381
1382         static void SetUpTestCase();
1383         static void TearDownTestCase();
1384         static bool PrepareVOutput(void);
1385
1386 protected:
1387         static tdm_client *client;
1388         static tdm_client_voutput *voutput;
1389         const int MODE_COUNT = 1;
1390
1391 private:
1392         static pid_t server_pid;
1393
1394         /* 0: read, 1: write */
1395         static int pipe_parent[2];
1396         static int pipe_child[2];
1397
1398         static void ServerFork(void);
1399         static void ServerKill(void);
1400 };
1401
1402 pid_t TDMVirtualOutput::server_pid = -1;
1403 int TDMVirtualOutput::pipe_parent[2] = {-1, -1};
1404 int TDMVirtualOutput::pipe_child[2] = {-1, -1};
1405 tdm_client* TDMVirtualOutput::client = nullptr;
1406 tdm_client_voutput* TDMVirtualOutput::voutput = nullptr;
1407
1408 void TDMVirtualOutput::ServerKill(void)
1409 {
1410         if (pipe_child[0] >= 0)
1411                 close(pipe_child[0]);
1412         if (pipe_child[1] >= 0) {
1413                 if (server_pid > 0) {
1414                         bool ret = _tc_tdm_pipe_write_msg(pipe_child[1], pipe_parent[0], TDM_UT_PIPE_MSG_TERMINATE_SERVER);
1415                         if (ret) {
1416                                 if (waitpid(server_pid, NULL, 0) == server_pid)
1417                                         TDM_INFO("*** server terminated ***");
1418                                 else
1419                                         TDM_ERR("*** failed to terminate server ***");
1420                         } else {
1421                                 if (kill(server_pid, 9) < 0)
1422                                         TDM_ERR("*** failed to kill server ***");
1423                         }
1424                 }
1425                 close(pipe_child[1]);
1426         }
1427
1428         if (pipe_parent[0] >= 0)
1429                 close(pipe_parent[0]);
1430         if (pipe_parent[1] >= 0)
1431                 close(pipe_parent[1]);
1432
1433         server_pid = -1;
1434         pipe_parent[0] = pipe_parent[1] = -1;
1435         pipe_child[0] = pipe_child[1] = -1;
1436 }
1437
1438 void TDMVirtualOutput::ServerFork(void)
1439 {
1440         if (server_pid > 0)
1441                 return;
1442
1443         server_pid = _tc_tdm_client_server_fork(pipe_parent, pipe_child);
1444         ASSERT_GT(server_pid, 0);
1445 }
1446
1447 void TDMVirtualOutput::SetUpTestCase(void)
1448 {
1449         setenv("XDG_RUNTIME_DIR", "/run", 1);
1450         setenv("TBM_DISPLAY_SERVER", "1", 1);
1451
1452         if (server_pid == -1)
1453                 ServerFork();
1454
1455         ASSERT_EQ(PrepareVOutput(), true);
1456 }
1457
1458 void TDMVirtualOutput::TearDownTestCase(void)
1459 {
1460         if (voutput)
1461                 tdm_client_voutput_destroy(voutput);
1462
1463         if (client)
1464                 tdm_client_destroy(client);
1465
1466         ServerKill();
1467
1468         unsetenv("XDG_RUNTIME_DIR");
1469         unsetenv("TBM_DISPLAY_SERVER");
1470 }
1471
1472 bool TDMVirtualOutput::PrepareVOutput(void)
1473 {
1474         tdm_error ret;
1475         const char name[TDM_NAME_LEN] = "Virtual Output";
1476
1477         client = tdm_client_create(&ret);
1478         TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
1479         TDM_UT_RETURN_FALSE_IF_FAIL(client != NULL);
1480
1481         voutput = tdm_client_create_voutput(client, name, &ret);
1482         TDM_UT_RETURN_FALSE_IF_FAIL(ret == TDM_ERROR_NONE);
1483         TDM_UT_RETURN_FALSE_IF_FAIL(voutput != NULL);
1484         return true;
1485 }
1486
1487 TEST_F(TDMVirtualOutput, SetAvailableModes)
1488 {
1489         tdm_error ret;
1490         tdm_client_output_mode modes[this->MODE_COUNT];
1491         int i, count = this->MODE_COUNT;
1492
1493         for (i = 0; i < count; i++)
1494         {
1495                 modes[i].mmHeight = 1234;
1496                 modes[i].mmWidth = 1234;
1497                 modes[i].mode_count = 0;
1498                 modes[i].prop_count = 0;
1499                 modes[i].subpixel = 0;
1500                 snprintf(modes[i].name, TDM_NAME_LEN, "TestModeSetting");
1501         }
1502
1503         ret = tdm_client_voutput_set_available_modes(this->voutput, modes, count);
1504         ASSERT_EQ(ret, TDM_ERROR_NONE);
1505 }
1506
1507 TEST_F(TDMVirtualOutput, FailTestSetAvailableModes)
1508 {
1509         tdm_error ret;
1510         tdm_client_output_mode modes[this->MODE_COUNT];
1511         int count = this->MODE_COUNT;
1512
1513         ret = tdm_client_voutput_set_available_modes(NULL, modes, count);
1514         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
1515
1516         ret = tdm_client_voutput_set_available_modes(this->voutput, NULL, count);
1517         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
1518
1519         ret = tdm_client_voutput_set_available_modes(this->voutput, modes, 0);
1520         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
1521 }
1522
1523 TEST_F(TDMVirtualOutput, SetPhysicalSize)
1524 {
1525         tdm_error ret;
1526         int mmWidth = 1234, mmHeight = 1234;
1527         
1528         ret = tdm_client_voutput_set_physical_size(this->voutput, mmWidth, mmHeight);
1529         ASSERT_EQ(ret, TDM_ERROR_NONE);
1530 }
1531
1532 TEST_F(TDMVirtualOutput, FailTestSetPhysicalSize)
1533 {
1534         tdm_error ret;
1535         int invalid_mmWidth = -1, invalid_mmHeight = -1;
1536         
1537         ret = tdm_client_voutput_set_physical_size(this->voutput, invalid_mmWidth, invalid_mmHeight);
1538         ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER);
1539 }
1540
1541 TEST_F(TDMVirtualOutput, GetClientOutput)
1542 {
1543         tdm_error ret;
1544         tdm_client_output *output;
1545
1546         output = tdm_client_voutput_get_client_output(this->voutput, &ret);
1547         ASSERT_EQ(ret, TDM_ERROR_NONE);
1548         ASSERT_NE(output, NULL);
1549 }
1550
1551 #if 0
1552 TEST_F(TDMVirtualOutput, FailTestGetClientOutput)
1553 {
1554         tdm_error ret;
1555 }
1556
1557 TEST_F(TDMVirtualOutput, SetBufferQueue)
1558 {
1559         tdm_error ret;
1560 }
1561
1562 TEST_F(TDMVirtualOutput, FailTestSetBufferQueue)
1563 {
1564         tdm_error ret;
1565 }
1566
1567 #endif
1568
1569 #ifdef TDM_UT_TEST_WITH_PARAMS
1570 INSTANTIATE_TEST_CASE_P(TDMClientParams,
1571                                                 TDMClient,
1572                                                 Combine(Bool(), Bool(), Values(TDM_DEFAULT_MODULE)));
1573 #else
1574 INSTANTIATE_TEST_CASE_P(TDMClientParams,
1575                                                 TDMClient,
1576                                                 Values(TDM_DEFAULT_MODULE));
1577 #endif
1578
1579 /* LCOV_EXCL_END */