a793bc792eb5b6cb8e67fad5cd769f69edc66bd5
[platform/core/uifw/libtdm.git] / utests / src / ut_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 "gtest/gtest.h"
33 #include "ut_common.h"
34
35 #include <cstring>
36
37 #include <sys/eventfd.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <semaphore.h>
41 #include <sys/signalfd.h>
42 #include <poll.h>
43 #include <sys/prctl.h>
44 #include <sys/socket.h>
45 #include <sys/timerfd.h>
46
47 extern "C"
48 {
49 #include "tdm.h"
50 #include "tdm_client.h"
51
52 #include "tbm_surface.h"
53
54 #include "wayland-client.h"
55 }
56
57 class tdm_client_test_prepare
58 {
59 public:
60         tdm_client_test_prepare()
61         {
62                 /* we have to deal with a named semaphore to protect an access to tdm across several instances
63                  * of servers */
64                 semaphore = sem_open(semaphore_name.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR, 1);
65                 if (semaphore == SEM_FAILED)
66                 {
67                         if (errno == EEXIST)
68                                 sem_unlink(semaphore_name.c_str());
69                         else
70                         {
71                                 std::cout << "can't create semaphore(1): " << semaphore_name << ", errno: " << errno << ".\n";
72                                 exit(EXIT_FAILURE);
73                         }
74                 } else {
75                         return;
76                 }
77
78                 semaphore = sem_open(semaphore_name.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR, 1);
79                 if (semaphore == SEM_FAILED)
80                 {
81                         std::cout << "can't create semaphore(2): " << semaphore_name << ", errno: " << errno << ".\n";
82                         exit(EXIT_FAILURE);
83                 }
84         }
85
86         ~tdm_client_test_prepare()
87         {
88                 sem_close(semaphore);
89                 sem_unlink(semaphore_name.c_str());
90         }
91
92         static sem_t *semaphore;
93
94         /* /dev/shm/sem.tdm-client-utests */
95         static const std::string semaphore_name;
96 };
97
98 sem_t *tdm_client_test_prepare::semaphore;
99 const std::string tdm_client_test_prepare::semaphore_name = "/tdm-client-utests";
100
101 /* global object is created before main() */
102 tdm_client_test_prepare dont_use_it;
103
104 /* real mess, sorry... */
105 class TDMClientTest : public ::testing::Test
106 {
107 protected:
108         TDMClientTest() : error(TDM_ERROR_NONE), server_pid(0),
109                 dsp(nullptr), output(nullptr), layer(nullptr), buffer(nullptr), is_server_stopped(false)
110         {
111                 set_env_vars();
112                 start_server(); /* as a separate process */
113                 wait_till_server_ready();
114         }
115
116         ~TDMClientTest()
117         {
118                 stop_server();
119                 unset_env_vars();
120         }
121
122         void send_request_to_server(int req)
123         {
124                 switch(req)
125                 {
126                         case ChangeDPMS:
127                                 send_request(ChangeDPMS);
128                         break;
129
130                         default:
131                         break;
132                 }
133         }
134
135         /* to stop server by user demand */
136         void stop_server(void)
137         {
138                 _stop_server();
139                 wait_till_serv_is_over();
140
141                 /* TODO: maybe it makes a sense to use this approach in the dtor too */
142         }
143
144         enum
145         {
146                 ChangeDPMS,
147         };
148
149 private:
150         void set_env_vars(void)
151         {
152                 setenv("XDG_RUNTIME_DIR", "/run", 1);
153                 setenv("TBM_DISPLAY_SERVER", "1", 1);
154         }
155
156         void unset_env_vars(void)
157         {
158                 unsetenv("TBM_DISPLAY_SERVER");
159                 unsetenv("XDG_RUNTIME_DIR");
160         }
161
162         void start_server(void)
163         {
164                 cl_serv_lock_fd = eventfd(0, 0);
165                 socketpair(AF_UNIX, SOCK_STREAM, 0, reinterpret_cast<int*>(&socks_pair));
166
167                 server_pid = fork();
168
169                 if (server_pid)
170                 {
171                         close(socks_pair.server_socket);
172                         return;
173                 }
174
175                 close(socks_pair.client_socket);
176
177                 wait_till_serv_resources_available();
178                 run_server();
179         }
180
181         void _stop_server(void)
182         {
183                 if (is_server_stopped) return;
184
185                 close(socks_pair.client_socket);
186                 close(cl_serv_lock_fd);
187                 kill(server_pid, SIGINT);
188
189                 is_server_stopped = true;
190         }
191
192         void wait_till_server_ready(void)
193         {
194                 uint64_t val;
195
196                 if (read(cl_serv_lock_fd, &val, sizeof val) < 0)
197                         std::cout << "error while trying to read from cl_serv_lock_fd eventfd object.\n";
198         }
199
200         void notify_server_ready(void)
201         {
202                 uint64_t val;
203
204                 val = 1;
205
206                 if (write(cl_serv_lock_fd, &val, sizeof val) < 0)
207                         std::cout << "error while trying to write to cl_serv_lock_fd evenfd object.\n";
208         }
209
210         void wait_till_serv_resources_available(void)
211         {
212                 while (1)
213                 {
214                         int ret;
215
216                         ret = sem_wait(tdm_client_test_prepare::semaphore);
217                         if (ret < 0 && errno == EINTR)
218                                 continue;
219                         else
220                                 break;
221                 }
222         }
223
224         void notify_serv_resources_available(void)
225         {
226                 sem_post(tdm_client_test_prepare::semaphore);
227
228                 sem_close(tdm_client_test_prepare::semaphore);
229                 sem_unlink(tdm_client_test_prepare::semaphore_name.c_str());
230         }
231
232         void wait_till_serv_is_over(void)
233         {
234                 wait_till_serv_resources_available();
235                 sem_post(tdm_client_test_prepare::semaphore);
236         }
237
238         void send_request(int req)
239         {
240                 int count;
241
242                 count = send(socks_pair.client_socket, &req, sizeof req, 0);
243
244                 if (count != sizeof req)
245                         std::cout << "error while trying to send request to socks_pair.client_socket.\n";
246         }
247
248         void handle_client_request()
249         {
250                 int req;
251                 int count;
252
253                 count = recv(socks_pair.server_socket, &req, sizeof req, 0);
254
255                 if (count != sizeof req) {
256                         std::cout << "error while trying to reserve data from socks_pair.server_socket.\n";
257                         return;
258                 }
259
260                 switch(req)
261                 {
262                         case ChangeDPMS:
263                                 change_dpms_request_handler();
264                         break;
265
266                         default:
267                                 break;
268                 }
269         }
270
271         void run_server(void)
272         {
273                 sigset_t mask;
274                 int signal_fd;
275                 int tdm_fd;
276                 pollfd work_fds[3];
277
278                 /* ask kernel to notify us about parent's die via SIGHUP signal */
279                 prctl(PR_SET_PDEATHSIG, SIGHUP);
280
281                 sigemptyset(&mask);
282                 sigaddset(&mask, SIGINT);
283                 sigaddset(&mask, SIGHUP);
284
285                 sigprocmask(SIG_BLOCK, &mask, NULL);
286
287                 signal_fd = signalfd(-1, &mask, 0);
288
289                 init_tdm();
290                 tdm_display_get_fd(dsp, &tdm_fd);
291
292                 std::memset(&work_fds, 0, sizeof work_fds);
293
294                 work_fds[0].fd = signal_fd;
295                 work_fds[0].events = POLLIN;
296
297                 work_fds[1].fd = tdm_fd;
298                 work_fds[1].events = POLLIN;
299
300                 work_fds[2].fd = socks_pair.server_socket;
301                 work_fds[2].events = POLLIN;
302
303                 notify_server_ready();
304
305                 while (1)
306                 {
307                         int ret;
308
309                         ret = poll(work_fds, 3, -1);
310                         if (ret < 0 && errno == EINTR) continue;
311
312                         if (work_fds[0].revents == POLLIN)
313                         {
314                                 signal_hndl();
315                                 exit(EXIT_SUCCESS);
316                         }
317
318                         if(work_fds[1].revents == POLLIN)
319                                 tdm_display_handle_events(dsp);
320
321                         if(work_fds[2].revents == POLLIN)
322                                 handle_client_request();
323                 }
324         }
325
326         void signal_hndl(void)
327         {
328                 close(socks_pair.server_socket);
329                 close(cl_serv_lock_fd);
330
331                 deinit_tdm();
332                 notify_serv_resources_available();
333         }
334
335         void init_tdm(void);
336         void deinit_tdm(void);
337
338         void set_layer_geometry(int w, int h);
339         void set_image_on_screen(int w, int h);
340
341         void change_dpms_request_handler(void);
342
343         struct sockets_pair
344         {
345                 sockets_pair() : server_socket(0), client_socket(0) {}
346                 int server_socket;
347                 int client_socket;
348         };
349
350 protected:
351         tdm_error error;
352
353 private:
354         pid_t server_pid;
355         int cl_serv_lock_fd;
356         sockets_pair socks_pair;
357
358         tdm_display *dsp;
359         tdm_output *output;
360         tdm_layer *layer;
361
362         tbm_surface_h buffer;
363
364         bool is_server_stopped;
365 };
366
367 class TDMClientTestClient : public TDMClientTest
368 {
369 protected:
370         TDMClientTestClient() : TDMClientTest()
371         {
372                 tdm_cl = tdm_client_create(nullptr);
373         }
374         ~TDMClientTestClient()
375         {
376                 tdm_client_destroy(tdm_cl);
377         }
378
379 protected:
380         tdm_client *tdm_cl;
381 };
382
383 class TDMClientTestClientOutput : public TDMClientTestClient
384 {
385 protected:
386         TDMClientTestClientOutput() : TDMClientTestClient()
387         {
388                 cl_output = tdm_client_get_output(tdm_cl, const_cast<char*>("primary"), nullptr);
389         }
390         ~TDMClientTestClientOutput()
391         {
392         }
393
394 protected:
395         tdm_client_output* cl_output;
396 };
397
398 class TDMClientTestVblank : public TDMClientTestClientOutput
399 {
400 protected:
401         TDMClientTestVblank() : TDMClientTestClientOutput()
402         {
403                 cl_vblank =  tdm_client_output_create_vblank(cl_output, nullptr);
404         }
405         ~TDMClientTestVblank()
406         {
407                 tdm_client_vblank_destroy(cl_vblank);
408         }
409
410 protected:
411         tdm_client_vblank* cl_vblank;
412 };
413
414 typedef TDMClientTest TDMClientTestDeathTest;
415 typedef TDMClientTestClient TDMClientTestClientDeathTest;
416 typedef TDMClientTestClientOutput TDMClientTestClientOutputDeathTest;
417 typedef TDMClientTestVblank TDMClientTestVblankDeathTest;
418
419
420 void TDMClientTest::set_layer_geometry(int w, int h)
421 {
422         tdm_info_layer layer_info;
423
424         std::memset(&layer_info, 0, sizeof(tdm_info_layer));
425
426         layer_info.src_config.size.h = w;
427         layer_info.src_config.size.v = h;
428         layer_info.src_config.pos.x = 0;
429         layer_info.src_config.pos.y = 0;
430         layer_info.src_config.pos.w = w;
431         layer_info.src_config.pos.h = h;
432         layer_info.src_config.format = TBM_FORMAT_ARGB8888;
433         layer_info.dst_pos.x = 0;
434         layer_info.dst_pos.y = 0;
435         layer_info.dst_pos.w = w;
436         layer_info.dst_pos.h = h;
437         layer_info.transform = TDM_TRANSFORM_NORMAL;
438
439         tdm_layer_set_info(layer, &layer_info);
440 }
441
442 void TDMClientTest::set_image_on_screen(int w, int h)
443 {
444         tbm_surface_info_s tbm_surface_info;
445
446         /* to have a hw vblank we have to make at least one tdm_commit */
447         buffer = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
448
449         std::memset(&tbm_surface_info, 0, sizeof(tbm_surface_info_s));
450
451         tbm_surface_map(buffer, TBM_SURF_OPTION_WRITE, &tbm_surface_info);
452
453         int *img = (int *)tbm_surface_info.planes[0].ptr;
454
455         for (uint32_t i = 0; i < tbm_surface_info.height; i++)
456                 for (uint32_t j = 0; j < tbm_surface_info.planes[0].stride / 4; j++)
457                         *img++ = 0x0000000;
458
459         tbm_surface_unmap(buffer);
460
461         set_layer_geometry(w, h);
462         tdm_layer_set_buffer(layer, buffer);
463         tdm_output_commit(output, 0, nullptr, nullptr);
464 }
465
466 void TDMClientTest::init_tdm(void)
467 {
468         int outputs_cnt = 0;
469         tdm_output_type tdm_output_type;
470
471         int output_modes_cnt = 0;
472         const tdm_output_mode* output_modes;
473         const tdm_output_mode* preferred_mode = NULL;
474
475         int layers_cnt = 0;
476         tdm_layer_capability tdm_layer_capability;
477
478         dsp = tdm_display_init(nullptr);
479
480         tdm_display_get_output_count(dsp, &outputs_cnt);
481
482         /* this part is hardware dependent, how to resolve this issue ? */
483         for (int i = 0; i < outputs_cnt; i++)
484         {
485                 output = tdm_display_get_output(dsp, i, nullptr);
486                 if (output == NULL) {
487                         std::cout << "tdm_display_get_output faild, server's gonna be stopped.\n";
488                         deinit_tdm();
489                         exit(EXIT_FAILURE);
490                 }
491                 tdm_output_get_output_type(output, &tdm_output_type);
492
493                 /* we're not interesting about other outputs */
494                 if (tdm_output_type != TDM_OUTPUT_TYPE_VIRTUAL &&
495                         tdm_output_type != TDM_OUTPUT_TYPE_HDMIA)
496                         break;
497         }
498
499         /* get output's preferred mode to obtain width & height we'll use later to create surface */
500         tdm_output_get_available_modes(output, &output_modes, &output_modes_cnt);
501
502         /* look for output's preferred mode */
503         for (int i = 0; i < output_modes_cnt; i++)
504         {
505                 if (output_modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
506                 {
507                         preferred_mode = &output_modes[i];
508                         break;
509                 }
510         }
511
512         if (!preferred_mode)
513         {
514                 std::cout << "no preferred mode, server's gonna be stopped.\n";
515
516                 deinit_tdm();
517                 exit(EXIT_FAILURE);
518         }
519
520         tdm_output_set_mode(output, preferred_mode);
521
522         tdm_output_get_layer_count(output, &layers_cnt);
523
524         /* it supposed that output always has primary & graphic layer */
525         for (int i = 0; i < layers_cnt; i++)
526         {
527                 layer = tdm_output_get_layer(output, i, nullptr);
528                 tdm_layer_get_capabilities(layer, &tdm_layer_capability);
529
530                 if ((tdm_layer_capability & TDM_LAYER_CAPABILITY_PRIMARY) &&
531                         (tdm_layer_capability & TDM_LAYER_CAPABILITY_GRAPHIC))
532                         break;
533         }
534
535         tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON);
536
537         set_image_on_screen(preferred_mode->hdisplay, preferred_mode->vdisplay);
538 }
539
540 void TDMClientTest::deinit_tdm(void)
541 {
542         if (layer)
543         {
544                 tdm_layer_unset_buffer(layer);
545                 tdm_output_commit(output, 1, nullptr, nullptr);
546         }
547
548         if (buffer)
549                 tbm_surface_internal_unref(buffer);
550
551         if (dsp)
552                 tdm_display_deinit(dsp);
553 }
554
555 void TDMClientTest::change_dpms_request_handler(void)
556 {
557         std::cout << "tdm_output_set_dpms.\n";
558         tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF);
559 }
560
561 TEST_F(TDMClientTest, TdmClientCreateSuccessfulCheckClient)
562 {
563         tdm_client *tdm_cl = tdm_client_create(nullptr);
564         ASSERT_TRUE(nullptr != tdm_cl);
565
566         tdm_client_destroy(tdm_cl);
567 }
568
569 TEST_F(TDMClientTest, TdmClientCreateSuccessfulCheckError)
570 {
571         tdm_client* tdm_cl = tdm_client_create(&error);
572         ASSERT_TRUE(TDM_ERROR_NONE == error);
573
574         tdm_client_destroy(tdm_cl);
575 }
576
577 TEST_F(TDMClientTest, TdmClientCreateFailServerStoppedCheckError)
578 {
579         stop_server();
580
581         tdm_client_create(&error);
582         ASSERT_TRUE(TDM_ERROR_OPERATION_FAILED == error);
583 }
584
585 TEST_F(TDMClientTest, TdmClientCreateFailServerStopped)
586 {
587         stop_server();
588
589         tdm_client *tdm_cl = tdm_client_create(nullptr);
590         ASSERT_TRUE(nullptr == tdm_cl);
591 }
592
593 TEST_F(TDMClientTestDeathTest, TdmClientDestroySuccessful)
594 {
595         ASSERT_EXIT(
596                 {
597                         tdm_client_destroy(nullptr);
598
599                         exit(EXIT_SUCCESS);
600                 },
601                 ::testing::ExitedWithCode(EXIT_SUCCESS), "");
602 }
603
604 TEST_F(TDMClientTestDeathTest, TdmClientDestroySuccessfulServerStopped)
605 {
606         ASSERT_EXIT(
607                 {
608                         tdm_client *tdm_cl = tdm_client_create(nullptr);
609
610                         stop_server();
611
612                         tdm_client_destroy(tdm_cl);
613
614                         exit(EXIT_SUCCESS);
615                 },
616                 ::testing::ExitedWithCode(EXIT_SUCCESS), "");
617 }
618
619 TEST_F(TDMClientTestClient, TdmClientGetFdSuccessful)
620 {
621         int fd;
622
623         tdm_client_get_fd(tdm_cl, &fd);
624         ASSERT_TRUE(0 < fd);
625 }
626
627 TEST_F(TDMClientTestClient, TdmClientGetFdSuccessfulCheckError)
628 {
629         int fd;
630
631         error = tdm_client_get_fd(tdm_cl, &fd);
632         ASSERT_TRUE(TDM_ERROR_NONE == error);
633 }
634
635 TEST_F(TDMClientTestClient, TdmClientGetFdFailNullTdmClient)
636 {
637         int fd;
638
639         error = tdm_client_get_fd(nullptr, &fd);
640         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
641 }
642
643 TEST_F(TDMClientTestClient, TdmClientGetFdFailNullFd)
644 {
645         error = tdm_client_get_fd(nullptr, nullptr);
646         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
647 }
648
649 TEST_F(TDMClientTestClient, TdmClientHandleEventsSuccessful)
650 {
651         ASSERT_EXIT(
652         {
653                 pollfd work_fds[2];
654                 itimerspec times_up;
655
656                 std::memset(&work_fds, 0, sizeof work_fds);
657                 std::memset(&times_up, 0, sizeof times_up);
658
659                 tdm_client_get_fd(tdm_cl, &work_fds[0].fd);
660                 work_fds[0].events = POLLIN;
661
662                 work_fds[1].fd = timerfd_create(CLOCK_MONOTONIC, 0);
663                 work_fds[1].events = POLLIN;
664
665                 times_up.it_value.tv_nsec = 100000000;  /* 100ms */
666                 timerfd_settime(work_fds[1].fd, 0, &times_up, nullptr);
667
668                 while (1)
669                 {
670                         int ret;
671
672                         ret = poll(work_fds, 2, -1);
673                         if (ret < 0 && errno == EINTR) continue;
674
675                         if (work_fds[0].revents == POLLIN)
676                         {
677                                 tdm_client_handle_events(tdm_cl);
678                                 std::cout << "ha.\n";
679                         }
680
681                         if(work_fds[1].revents == POLLIN)
682                                 exit(EXIT_SUCCESS);
683                 }
684         },
685         ::testing::ExitedWithCode(EXIT_SUCCESS), "");
686 }
687
688 TEST_F(TDMClientTestClient, TdmClientHandleEventsFailNullTDMClient)
689 {
690         error = tdm_client_handle_events(nullptr);
691         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
692 }
693
694 TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessful)
695 {
696         tdm_client_output* cl_output;
697
698         cl_output = tdm_client_get_output(tdm_cl, const_cast<char*>("primary"), nullptr);
699         ASSERT_TRUE(nullptr != cl_output);
700 }
701
702 TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulCallTwice)
703 {
704         tdm_client_output* cl_output_1, *cl_output_2;
705
706         cl_output_1 = tdm_client_get_output(tdm_cl, const_cast<char*>("primary"), nullptr);
707         cl_output_2 = tdm_client_get_output(tdm_cl, const_cast<char*>("primary"), nullptr);
708         ASSERT_TRUE(cl_output_1 == cl_output_2);
709 }
710
711 TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulCheckError)
712 {
713         tdm_client_get_output(tdm_cl, const_cast<char*>("primary"), &error);
714         ASSERT_TRUE(TDM_ERROR_NONE == error);
715 }
716
717 TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulNullName)
718 {
719         tdm_client_output* cl_output;
720
721         cl_output = tdm_client_get_output(tdm_cl, nullptr, nullptr);
722         ASSERT_TRUE(nullptr != cl_output);
723 }
724
725 TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulNullNameCheckError)
726 {
727         tdm_client_get_output(tdm_cl, nullptr, &error);
728         ASSERT_TRUE(TDM_ERROR_NONE == error);
729 }
730
731 TEST_F(TDMClientTestClient, TdmClientGetOutputFailNullTdmClient)
732 {
733         tdm_client_output* cl_output;
734
735         cl_output = tdm_client_get_output(nullptr, const_cast<char*>("primary"), nullptr);
736         ASSERT_TRUE(nullptr == cl_output);
737 }
738
739 TEST_F(TDMClientTestClient, TdmClientGetOutputFailNullTdmClientCheckError)
740 {
741         tdm_client_get_output(nullptr, const_cast<char*>("primary"), &error);
742         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
743 }
744
745 TEST_F(TDMClientTestClientOutput, TdmClientOutputAddChangeHandlerSuccessful)
746 {
747         static bool got_an_event = false;
748         wl_display *wl_dsp;
749
750         /* is this function implemented fully? */
751         tdm_client_output_add_change_handler(cl_output, [] (tdm_client_output *output,
752                                                                         tdm_output_change_type type,
753                                                                         tdm_value value,
754                                                                         void *user_data) { got_an_event = true; }, nullptr);
755
756         /* force a requests flush */
757         wl_dsp = wl_display_connect("tdm-socket");
758         ASSERT_TRUE(nullptr != wl_dsp);
759         wl_display_flush(wl_dsp);
760         wl_display_roundtrip(wl_dsp);
761         wl_display_disconnect(wl_dsp);
762
763         send_request_to_server(TDMClientTest::ChangeDPMS);
764         tdm_client_handle_events(tdm_cl);
765
766         ASSERT_TRUE(true == got_an_event);
767 }
768
769 TEST_F(TDMClientTestClientOutput, TdmClientOutputAddChangeHandlerFailNullOutput)
770 {
771         error = tdm_client_output_add_change_handler(nullptr, [] (tdm_client_output *output,
772                                                                         tdm_output_change_type type,
773                                                                         tdm_value value,
774                                                                         void *user_data) {}, nullptr);
775         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
776 }
777
778 TEST_F(TDMClientTestClientOutput, TdmClientOutputAddChangeHandlerFailNullHandler)
779 {
780         error = tdm_client_output_add_change_handler(cl_output, nullptr, nullptr);
781         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
782 }
783
784 TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerSuccessful)
785 {
786         ASSERT_EXIT(
787         {
788                 auto func = [] (tdm_client_output *output, tdm_output_change_type type, tdm_value value,
789                                 void *user_data) {};
790
791                 tdm_client_output_add_change_handler(cl_output, func, nullptr);
792
793                 tdm_client_output_remove_change_handler(cl_output, func, nullptr);
794
795                 exit(EXIT_SUCCESS);
796         },
797         ::testing::ExitedWithCode(EXIT_SUCCESS), "");
798 }
799
800 TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerSuccessfulInvalidHandler)
801 {
802         ASSERT_EXIT(
803         {
804                 auto func = [] (tdm_client_output *output, tdm_output_change_type type, tdm_value value,
805                                 void *user_data) {};
806
807                 tdm_client_output_remove_change_handler(cl_output, func, nullptr);
808
809                 exit(EXIT_SUCCESS);
810         },
811         ::testing::ExitedWithCode(EXIT_SUCCESS), "");
812 }
813
814 TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerFailNullOutput)
815 {
816         ASSERT_EXIT(
817         {
818                 auto func = [] (tdm_client_output *output, tdm_output_change_type type, tdm_value value,
819                                 void *user_data) {};
820
821                 tdm_client_output_remove_change_handler(nullptr, func, nullptr);
822
823                 exit(EXIT_SUCCESS);
824         },
825         ::testing::ExitedWithCode(EXIT_SUCCESS), "");
826 }
827
828 TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerFailNullHandler)
829 {
830         ASSERT_EXIT(
831         {
832                 tdm_client_output_remove_change_handler(cl_output, nullptr, nullptr);
833
834                 exit(EXIT_SUCCESS);
835         },
836         ::testing::ExitedWithCode(EXIT_SUCCESS), "");
837 }
838
839 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetRefreshRateSuccessful)
840 {
841         uint32_t refresh_rate;
842
843         error = tdm_client_output_get_refresh_rate(cl_output, &refresh_rate);
844         ASSERT_TRUE(TDM_ERROR_NONE == error);
845 }
846
847 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetRefreshRateFailNullOutput)
848 {
849         uint32_t refresh_rate;
850
851         error = tdm_client_output_get_refresh_rate(nullptr, &refresh_rate);
852         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
853 }
854
855 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetRefreshRateFailNullRefreshRate)
856 {
857         error = tdm_client_output_get_refresh_rate(cl_output, nullptr);
858         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
859 }
860
861 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetConnectionStatusSuccessful)
862 {
863         tdm_output_conn_status conn_status;
864
865         error = tdm_client_output_get_conn_status(cl_output, &conn_status);
866         ASSERT_TRUE(TDM_ERROR_NONE == error);
867 }
868
869 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetConnectionStatusFailNullOutput)
870 {
871         tdm_output_conn_status conn_status;
872
873         error = tdm_client_output_get_conn_status(nullptr, &conn_status);
874         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
875 }
876
877 TEST_F(TDMClientTestClientOutput, TTdmClientOutputGetConnectionStatusFailNullConnState)
878 {
879         error = tdm_client_output_get_conn_status(cl_output, nullptr);
880         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
881 }
882
883 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetDpmsSuccessful)
884 {
885         tdm_output_dpms dpms_val;
886
887         error = tdm_client_output_get_dpms(cl_output, &dpms_val);
888         ASSERT_TRUE(TDM_ERROR_NONE == error);
889 }
890
891 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetDpmsFailNullOutput)
892 {
893         tdm_output_dpms dpms_val;
894
895         error = tdm_client_output_get_dpms(nullptr, &dpms_val);
896         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
897 }
898
899 TEST_F(TDMClientTestClientOutput, TdmClientOutputGetDpmsFailNullDpmsArg)
900 {
901         error = tdm_client_output_get_dpms(cl_output, nullptr);
902         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
903 }
904
905 TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankSuccessful)
906 {
907         tdm_client_vblank* cl_vblank;
908
909         cl_vblank = tdm_client_output_create_vblank(cl_output, nullptr);
910         ASSERT_TRUE(nullptr != cl_vblank);
911
912         tdm_client_vblank_destroy(cl_vblank);
913 }
914
915 TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankSuccessfulCheckError)
916 {
917         tdm_client_vblank* cl_vblank;
918
919         cl_vblank = tdm_client_output_create_vblank(cl_output, &error);
920         ASSERT_TRUE(TDM_ERROR_NONE == error);
921
922         tdm_client_vblank_destroy(cl_vblank);
923 }
924
925 TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankFailNullOutput)
926 {
927         tdm_client_vblank* cl_vblank;
928
929         cl_vblank = tdm_client_output_create_vblank(nullptr, nullptr);
930         ASSERT_TRUE(nullptr == cl_vblank);
931 }
932
933 TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankFailNullOutputCheckError)
934 {
935         tdm_client_output_create_vblank(nullptr, &error);
936         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
937 }
938
939 TEST_F(TDMClientTestClientOutputDeathTest, TdmClientDestroyVblankSuccessful)
940 {
941         ASSERT_EXIT(
942         {
943                 tdm_client_vblank *cl_vblank = tdm_client_output_create_vblank(cl_output, nullptr);
944
945                 tdm_client_vblank_destroy(cl_vblank);
946                 exit(EXIT_SUCCESS);
947         },
948         ::testing::ExitedWithCode(EXIT_SUCCESS), "");
949 }
950
951 TEST_F(TDMClientTestClientOutputDeathTest, TdmClientDestroyVblankFailNoClientVblankArg)
952 {
953         ASSERT_EXIT(
954         {
955                 tdm_client_vblank_destroy(nullptr);
956                 exit(EXIT_SUCCESS);
957         },
958         ::testing::ExitedWithCode(EXIT_SUCCESS), "");
959 }
960
961 TEST_F(TDMClientTestVblank, TdmClientVblankSetNameSuccessful)
962 {
963         error = tdm_client_vblank_set_name(cl_vblank, "wassup");
964         ASSERT_TRUE(TDM_ERROR_NONE == error);
965 }
966
967 TEST_F(TDMClientTestVblank, TdmClientVblankSetNameSuccessfulNoExplicitName)
968 {
969         error = tdm_client_vblank_set_name(cl_vblank, nullptr);
970         ASSERT_TRUE(TDM_ERROR_NONE == error);
971 }
972
973 TEST_F(TDMClientTestVblank, TdmClientVblankSetNameFailNullClientVblank)
974 {
975         error = tdm_client_vblank_set_name(nullptr, "wassup");
976         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
977 }
978
979 TEST_F(TDMClientTestVblank, TdmClientVblankSetSyncSuccessful)
980 {
981         error = tdm_client_vblank_set_sync(cl_vblank, 0);
982         ASSERT_TRUE(TDM_ERROR_NONE == error);
983 }
984
985 TEST_F(TDMClientTestVblank, TdmClientVblankSetSyncFailNullClientVblank)
986 {
987         error = tdm_client_vblank_set_sync(nullptr, 0);
988         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
989 }
990
991 TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsSuccessful)
992 {
993         error = tdm_client_vblank_set_fps(cl_vblank, 60);
994         ASSERT_TRUE(TDM_ERROR_NONE == error);
995 }
996
997 TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsSuccessfulSetTwice)
998 {
999         tdm_client_vblank_set_fps(cl_vblank, 60);
1000         error = tdm_client_vblank_set_fps(cl_vblank, 60);
1001         ASSERT_TRUE(TDM_ERROR_NONE == error);
1002 }
1003
1004 TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsFailNullClientVblank)
1005 {
1006         error = tdm_client_vblank_set_fps(nullptr, 60);
1007         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1008 }
1009
1010 TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsFailInvalidFpsArg)
1011 {
1012         error = tdm_client_vblank_set_fps(cl_vblank, 0);
1013         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1014 }
1015
1016 TEST_F(TDMClientTestVblank, TdmClientVblankSetOffsetSuccessful)
1017 {
1018         error = tdm_client_vblank_set_offset(cl_vblank, 10);
1019         ASSERT_TRUE(TDM_ERROR_NONE == error);
1020 }
1021
1022 TEST_F(TDMClientTestVblank, TdmClientVblankSetOffsetSuccessfulSetTwice)
1023 {
1024         tdm_client_vblank_set_offset(cl_vblank, 10);
1025         error = tdm_client_vblank_set_offset(cl_vblank, 10);
1026         ASSERT_TRUE(TDM_ERROR_NONE == error);
1027 }
1028
1029 TEST_F(TDMClientTestVblank, TdmClientVblankSetOffsetFailNullClientVblank)
1030 {
1031         error = tdm_client_vblank_set_offset(nullptr, 10);
1032         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1033 }
1034
1035 TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeSuccessfulEnableFake)
1036 {
1037         error = tdm_client_vblank_set_enable_fake(cl_vblank, 1);
1038         ASSERT_TRUE(TDM_ERROR_NONE == error);
1039 }
1040
1041 TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeSuccessfulDisableFake)
1042 {
1043         error = tdm_client_vblank_set_enable_fake(cl_vblank, 0);
1044         ASSERT_TRUE(TDM_ERROR_NONE == error);
1045 }
1046
1047 TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeSuccessfulSetTwice)
1048 {
1049         tdm_client_vblank_set_enable_fake(cl_vblank, 0);
1050         error = tdm_client_vblank_set_enable_fake(cl_vblank, 0);
1051         ASSERT_TRUE(TDM_ERROR_NONE == error);
1052 }
1053
1054 TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeFailNullClientVblank)
1055 {
1056         error = tdm_client_vblank_set_enable_fake(nullptr, 0);
1057         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1058 }
1059
1060 TEST_F(TDMClientTestVblank, TdmClientVblankWaitSuccessful)
1061 {
1062         auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
1063                          unsigned int tv_sec, unsigned int tv_usec,  void *user_data) {};
1064
1065         tdm_client_vblank_set_sync(cl_vblank, 0);
1066         tdm_client_vblank_set_enable_fake(cl_vblank, 1);
1067
1068         error = tdm_client_vblank_wait(cl_vblank, 1, func, nullptr);
1069         ASSERT_TRUE(TDM_ERROR_NONE == error);
1070 }
1071
1072 TEST_F(TDMClientTestVblank, TdmClientVblankWaitFailNullClientVblank)
1073 {
1074         auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
1075                          unsigned int tv_sec, unsigned int tv_usec,  void *user_data) {};
1076
1077         error = tdm_client_vblank_wait(nullptr, 1, func, nullptr);
1078         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1079 }
1080
1081 TEST_F(TDMClientTestVblank, TdmClientVblankWaitFailNullHandler)
1082 {
1083         error = tdm_client_vblank_wait(cl_vblank, 1, nullptr, nullptr);
1084         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1085 }
1086
1087 TEST_F(TDMClientTestVblank, TdmClientVblankWaitFailInvalidInterval)
1088 {
1089         auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
1090                          unsigned int tv_sec, unsigned int tv_usec,  void *user_data) {};
1091
1092         error = tdm_client_vblank_wait(cl_vblank, 0, func, nullptr);
1093         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1094 }
1095
1096 TEST_F(TDMClientTestVblank, TdmClientVblankWaitSequencySuccessful)
1097 {
1098         auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
1099                          unsigned int tv_sec, unsigned int tv_usec,  void *user_data) {};
1100
1101         tdm_client_vblank_set_sync(cl_vblank, 0);
1102         tdm_client_vblank_set_enable_fake(cl_vblank, 1);
1103
1104         error = tdm_client_vblank_wait_seq(cl_vblank, 100, func, nullptr);
1105         ASSERT_TRUE(TDM_ERROR_NONE == error);
1106 }
1107
1108 TEST_F(TDMClientTestVblank, TdmClientVblankWaitSequencyFailNullClientVblank)
1109 {
1110         auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence,
1111                          unsigned int tv_sec, unsigned int tv_usec,  void *user_data) {};
1112
1113         error = tdm_client_vblank_wait_seq(nullptr, 1, func, nullptr);
1114         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1115 }
1116
1117 TEST_F(TDMClientTestVblank, TdmClientVblankWaitSequencyFailNullHandler)
1118 {
1119         error = tdm_client_vblank_wait_seq(cl_vblank, 1, nullptr, nullptr);
1120         ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error);
1121 }
1122