• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stddef.h>
18 #include <stdio.h>
19 #include <uapi/err.h>
20 
21 #include <lib/uirq/uirq.h>
22 #include <trusty_ipc.h>
23 #include <trusty_uio.h>
24 
25 #define TLOG_TAG "uirq-unittest"
26 #include <trusty_unittest.h>
27 
28 #define MAX_UIRQ_CNT 100
29 #define TEST_UIRQ_10MS "test-uirq-10ms"
30 #define TEST_UIRQ_NO_ACCESS "test-uirq-no-access"
31 #define TEST_UIRQ_PORT "test-uirq-port"
32 
33 #define FAIL_TIMEOUT 5000
34 
35 typedef struct uirq {
36     handle_t hset;
37     handle_t hevts;
38     handle_t hevt1;
39     handle_t hevt2;
40 } uirq_t;
41 
TEST_F_SETUP(uirq)42 TEST_F_SETUP(uirq) {
43     _state->hset = INVALID_IPC_HANDLE;
44     _state->hevts = INVALID_IPC_HANDLE;
45     _state->hevt1 = INVALID_IPC_HANDLE;
46     _state->hevt2 = INVALID_IPC_HANDLE;
47 }
48 
TEST_F_TEARDOWN(uirq)49 TEST_F_TEARDOWN(uirq) {
50     (void)close(_state->hset);
51     (void)close(_state->hevts);
52     (void)close(_state->hevt1);
53     (void)close(_state->hevt2);
54 }
55 
TEST_F(uirq,uirq_test_open_no_access)56 TEST_F(uirq, uirq_test_open_no_access) {
57     /* open unaccessible uirq event */
58     _state->hevt1 = uirq_open(TEST_UIRQ_NO_ACCESS, 0);
59     EXPECT_EQ(ERR_NOT_FOUND, _state->hevt1, "open no-access uirq event");
60 
61 test_abort:;
62 }
63 
TEST_F(uirq,uirq_test_handle_single)64 TEST_F(uirq, uirq_test_handle_single) {
65     int rc;
66     uevent_t uevt;
67     uint32_t evt_cnt = 0;
68 
69     /* open uirq */
70     _state->hevt1 = uirq_open(TEST_UIRQ_10MS, 0);
71     ASSERT_GE(_state->hevt1, 0, "open uirq");
72 
73     /* handle test uirq event MAX_UIRQ_CNT times */
74     while (evt_cnt < MAX_UIRQ_CNT) {
75         rc = wait(_state->hevt1, &uevt, FAIL_TIMEOUT);
76         ASSERT_EQ(0, rc, "wait for uirq");
77         ASSERT_EQ(uevt.handle, _state->hevt1);
78 
79         evt_cnt++;
80         rc = uirq_ack_handled(_state->hevt1);
81         ASSERT_EQ(0, rc, "ack uirq");
82     }
83     EXPECT_EQ(MAX_UIRQ_CNT, evt_cnt, "evt1  count");
84 
85 test_abort:;
86 }
87 
TEST_F(uirq,uirq_test_handle_multiple)88 TEST_F(uirq, uirq_test_handle_multiple) {
89     int rc;
90     uevent_t uevt;
91     uint32_t ttl_cnt = 0;
92     uint32_t evt1_cnt = 0;
93     uint32_t evt2_cnt = 0;
94 
95     /* create handle set */
96     _state->hset = handle_set_create();
97     ASSERT_GE(_state->hset, 0, "create handle set");
98 
99     /* open uirq event */
100     _state->hevt1 = uirq_open(TEST_UIRQ_10MS, 0);
101     ASSERT_GE(_state->hevt1, 0, "open uirq");
102 
103     /* open the same uirq event */
104     _state->hevt2 = uirq_open(TEST_UIRQ_10MS, 0);
105     ASSERT_GE(_state->hevt2, 0, "open uirq");
106 
107     /* Add all uirq events to handle set */
108     uevt.handle = _state->hevt1;
109     uevt.event = ~0U;
110     uevt.cookie = NULL;
111     rc = handle_set_ctrl(_state->hset, HSET_ADD, &uevt);
112     ASSERT_EQ(0, rc);
113 
114     uevt.handle = _state->hevt2;
115     uevt.event = ~0U;
116     uevt.cookie = NULL;
117     rc = handle_set_ctrl(_state->hset, HSET_ADD, &uevt);
118     ASSERT_EQ(0, rc);
119 
120     /* trigger and handle uirq event MAX_UIRQ_CNT times */
121     while (ttl_cnt < MAX_UIRQ_CNT * 2) {
122         rc = wait(_state->hset, &uevt, FAIL_TIMEOUT);
123         ASSERT_EQ(0, rc, "wait for uirq");
124 
125         if (uevt.handle == _state->hevt1) {
126             evt1_cnt++;
127             rc = uirq_ack_handled(_state->hevt1);
128             ASSERT_EQ(0, rc, "ack uirq");
129 
130         } else if (uevt.handle == _state->hevt2) {
131             evt2_cnt++;
132             rc = uirq_ack_handled(_state->hevt2);
133             ASSERT_EQ(0, rc, "ack uirq");
134         } else {
135             break;
136         }
137         ttl_cnt++;
138     }
139     EXPECT_EQ(MAX_UIRQ_CNT * 2, ttl_cnt, "total count");
140     EXPECT_EQ(MAX_UIRQ_CNT, evt1_cnt, "evt1  count");
141     EXPECT_EQ(MAX_UIRQ_CNT, evt2_cnt, "evt2  count");
142 
143 test_abort:;
144 }
145 
TEST(uirq,invalid_ack_handled)146 TEST(uirq, invalid_ack_handled) {
147     int rc;
148     uint32_t cmd;
149     handle_t port;
150 
151     /* Create port to use it as target for this test */
152     rc = port_create(TEST_UIRQ_PORT, 1, 1, IPC_PORT_ALLOW_TA_CONNECT);
153     ASSERT_GE(rc, 0);
154     port = (handle_t)rc;
155 
156     /* ack existing but invalid handle: should return ERR_NOT_SUPPORTED */
157     rc = uirq_ack_handled(port);
158     EXPECT_EQ(ERR_NOT_SUPPORTED, rc);
159 
160     /* use direct write to invalid handle: should return ERR_NOT_SUPPORTED */
161     cmd = 1;
162     rc = trusty_write(port, &cmd, sizeof(cmd));
163     EXPECT_EQ(ERR_NOT_SUPPORTED, rc);
164 
165     /* use direct read from invalid handle: should return ERR_NOT_SUPPORTED */
166     rc = trusty_read(port, &cmd, sizeof(cmd));
167     EXPECT_EQ(ERR_NOT_SUPPORTED, rc);
168 
169     close(port);
170 test_abort:;
171 }
172 
173 PORT_TEST(uirq, "com.android.uirq-unittest");
174