| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <assert.h> |
| #include <err.h> |
| #include <lib/trusty/event.h> |
| #include <lib/trusty/handle_set.h> |
| #include <lib/trusty/ipc_msg.h> |
| #include <lib/trusty/uuid.h> |
| #include <lib/unittest/unittest.h> |
| |
| #include <trace.h> |
| |
| #define EXPECTED_TO_FAIL_TIMEOUT_MSEC 1000 |
| #define NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC (30000) |
| |
| #define MAX_EVT_CNT 100 |
| #define TEST_EVS_NAME1 "com.android.trusty.test-uevent-source1" |
| #define TEST_EVS_NAME2 "com.android.trusty.test-uevent-source2" |
| #define TEST_EVT_NAME1 "com.android.trusty.test-uevent-client1" |
| #define TEST_EVT_NAME2 "com.android.trusty.test-uevent-client2" |
| |
| typedef struct uirq { |
| struct handle* hset; |
| struct handle* hevts; |
| struct handle* hevt1; |
| struct handle* hevt2; |
| struct handle_ref hevts_ref; |
| struct handle_ref hevt1_ref; |
| struct handle_ref hevt2_ref; |
| } uirq_t; |
| |
| TEST_F_SETUP(uirq) { |
| memset(_state, 0, sizeof(*_state)); |
| } |
| |
| TEST_F_TEARDOWN(uirq) { |
| if (_state->hevts_ref.handle) { |
| handle_set_detach_ref(&_state->hevts_ref); |
| } |
| |
| if (_state->hevt1_ref.handle) { |
| handle_set_detach_ref(&_state->hevt1_ref); |
| } |
| |
| if (_state->hevt2_ref.handle) { |
| handle_set_detach_ref(&_state->hevt2_ref); |
| } |
| |
| if (_state->hevts) { |
| handle_close(_state->hevts); |
| } |
| |
| if (_state->hevt1) { |
| handle_close(_state->hevt1); |
| } |
| |
| if (_state->hevt2) { |
| handle_close(_state->hevt2); |
| } |
| |
| if (_state->hset) { |
| handle_close(_state->hset); |
| } |
| } |
| |
| TEST_F(uirq, event_source_create_invalid) { |
| int rc; |
| |
| rc = event_source_create(NULL, NULL, NULL, NULL, 0, 0, &_state->hevts); |
| ASSERT_EQ(ERR_INVALID_ARGS, rc); |
| |
| rc = event_source_create("", NULL, NULL, NULL, 0, 0, &_state->hevts); |
| ASSERT_EQ(ERR_INVALID_ARGS, rc); |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_source_create_close) { |
| int rc; |
| uint32_t cnt; |
| |
| /* create/close named event 10000 times */ |
| for (cnt = 0; cnt < 10000; cnt++) { |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* then close it */ |
| handle_close(_state->hevts); |
| _state->hevts = NULL; |
| } |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_source_create_existing) { |
| int rc; |
| struct handle* h = NULL; |
| |
| /* create named event */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* then publish it */ |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* try to create event with the same name again */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, &h); |
| ASSERT_EQ(0, rc); |
| |
| /* then publish it */ |
| rc = event_source_publish(h); |
| EXPECT_EQ(ERR_ALREADY_EXISTS, rc); |
| |
| if (h) { |
| handle_close(h); |
| } |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_source_wait_no_clients) { |
| int rc; |
| uint32_t uevt; |
| |
| /* create named event */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = handle_wait(_state->hevts, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on created event"); |
| |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "signal event"); |
| |
| /* event without clients becomes ready */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on signaled event"); |
| |
| /* do it again: it should time out */ |
| rc = handle_wait(_state->hevts, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on created event"); |
| |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "signal event"); |
| |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on created event"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_open_invalid) { |
| int rc; |
| struct uuid cid = zero_uuid; |
| |
| /* open named event with NULL name */ |
| rc = event_source_open(&cid, NULL, 0, 0, &_state->hevt1); |
| ASSERT_EQ(ERR_INVALID_ARGS, rc); |
| |
| /* open named event with empty name */ |
| rc = event_source_open(&cid, "", 1, 0, &_state->hevt1); |
| ASSERT_EQ(ERR_INVALID_ARGS, rc); |
| |
| /* open non-existing named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(ERR_NOT_FOUND, rc); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_open_close) { |
| int rc; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open/close the same named event 10000 times */ |
| for (int i = 0; i < 10000; i++) { |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, |
| 0, &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| handle_close(_state->hevt1); |
| _state->hevt1 = NULL; |
| } |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_wait_single) { |
| int rc; |
| uint32_t uevt; |
| struct handle_ref ref; |
| struct uuid cid = zero_uuid; |
| |
| /* create handle set */ |
| _state->hset = handle_set_create(); |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the same named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* wait on unsignaled event: should timeout */ |
| rc = handle_wait(_state->hevt1, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on client"); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on signaled event: should return as it is signaled */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client"); |
| |
| /* wait on event source: should timeout as we have not notified */ |
| rc = handle_wait(_state->hevts, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on source"); |
| |
| /* notify that event is handled to put source into handled state */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source again: should return as event is handled */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| /* Check handle sets: add both events to handle set */ |
| memset(&_state->hevts_ref, 0, sizeof(_state->hevts_ref)); |
| _state->hevts_ref.handle = _state->hevts; |
| _state->hevts_ref.emask = ~0U; |
| _state->hevts_ref.cookie = NULL; |
| rc = handle_set_attach(_state->hset, &_state->hevts_ref); |
| ASSERT_EQ(0, rc); |
| |
| memset(&_state->hevt1_ref, 0, sizeof(_state->hevt1_ref)); |
| _state->hevt1_ref.handle = _state->hevt1; |
| _state->hevt1_ref.emask = ~0U; |
| _state->hevt1_ref.cookie = NULL; |
| rc = handle_set_attach(_state->hset, &_state->hevt1_ref); |
| ASSERT_EQ(0, rc); |
| |
| /* trigger and handle event MAX_EVT_CNT times */ |
| uint32_t cnt = MAX_EVT_CNT; |
| rc = event_source_signal(_state->hevts); |
| ASSERT_EQ(0, rc, "notify event signaled"); |
| while (cnt) { |
| rc = handle_set_wait(_state->hset, &ref, |
| NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| ASSERT_EQ(0, rc, "wait any"); |
| |
| if (ref.handle) { |
| /* dec ref obtained by handle_set_wait */ |
| handle_decref(ref.handle); |
| } |
| |
| if (ref.handle == _state->hevt1) { |
| cnt--; |
| rc = event_client_notify_handled(_state->hevt1); |
| ASSERT_EQ(0, rc, "notify event handled"); |
| } else if (ref.handle == _state->hevts) { |
| rc = event_source_signal(_state->hevts); |
| ASSERT_EQ(0, rc, "notify event signaled"); |
| } else { |
| break; |
| } |
| } |
| EXPECT_EQ(0, cnt, "event counter"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_wait_multiple) { |
| int rc; |
| struct handle_ref ref; |
| struct uuid cid = zero_uuid; |
| |
| /* create handle set */ |
| _state->hset = handle_set_create(); |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* open the same named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt2); |
| ASSERT_EQ(0, rc); |
| |
| /* Add all handles to handle set */ |
| memset(&_state->hevts_ref, 0, sizeof(_state->hevts_ref)); |
| _state->hevts_ref.handle = _state->hevts; |
| _state->hevts_ref.emask = ~0U; |
| _state->hevts_ref.cookie = NULL; |
| rc = handle_set_attach(_state->hset, &_state->hevts_ref); |
| ASSERT_EQ(0, rc); |
| |
| memset(&_state->hevt1_ref, 0, sizeof(_state->hevt1_ref)); |
| _state->hevt1_ref.handle = _state->hevt1; |
| _state->hevt1_ref.emask = ~0U; |
| _state->hevt1_ref.cookie = NULL; |
| rc = handle_set_attach(_state->hset, &_state->hevt1_ref); |
| ASSERT_EQ(0, rc); |
| |
| memset(&_state->hevt2_ref, 0, sizeof(_state->hevt2_ref)); |
| _state->hevt2_ref.handle = _state->hevt2; |
| _state->hevt2_ref.emask = ~0U; |
| _state->hevt2_ref.cookie = NULL; |
| rc = handle_set_attach(_state->hset, &_state->hevt2_ref); |
| ASSERT_EQ(0, rc); |
| |
| /* trigger and handle event MAX_EVT_CNT times */ |
| uint32_t evts_cnt = 0; |
| uint32_t evt1_cnt = 0; |
| uint32_t evt2_cnt = 0; |
| |
| rc = event_source_signal(_state->hevts); |
| ASSERT_EQ(0, rc, "notify event signaled"); |
| evts_cnt++; |
| for (;;) { |
| rc = handle_set_wait(_state->hset, &ref, |
| NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| ASSERT_EQ(0, rc, "wait any"); |
| |
| if (ref.handle) { |
| /* dec ref obtained by handle_set_wait */ |
| handle_decref(ref.handle); |
| } |
| |
| if (ref.handle == _state->hevts) { |
| if (evts_cnt == MAX_EVT_CNT) |
| break; |
| rc = event_source_signal(_state->hevts); |
| ASSERT_EQ(0, rc, "notify event signaled"); |
| evts_cnt++; |
| } else if (ref.handle == _state->hevt1) { |
| evt1_cnt++; |
| rc = event_client_notify_handled(_state->hevt1); |
| ASSERT_EQ(0, rc, "notify event handled"); |
| } else if (ref.handle == _state->hevt2) { |
| evt2_cnt++; |
| rc = event_client_notify_handled(_state->hevt2); |
| ASSERT_EQ(0, rc, "notify event handled"); |
| } else { |
| break; |
| } |
| } |
| EXPECT_EQ(MAX_EVT_CNT, evts_cnt, "evts count"); |
| EXPECT_EQ(MAX_EVT_CNT, evt1_cnt, "evt1 count"); |
| EXPECT_EQ(MAX_EVT_CNT, evt2_cnt, "evt2 count"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_open_signaled) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* open named event again */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt2); |
| ASSERT_EQ(0, rc); |
| |
| /* wait on client 1: should be signaled */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* wait on client 2: should timeout as it should not be signaled */ |
| rc = handle_wait(_state->hevt2, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on source"); |
| |
| /* wait on event source: should timeout: event is not handled */ |
| rc = handle_wait(_state->hevts, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on source"); |
| |
| /* notify that event1 is handled: to put it in unsignaled state */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source again: should return as event is handled */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| /* signal event again: now both events must ack */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: should be signaled */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* wait on client 2: should be signaled */ |
| rc = handle_wait(_state->hevt2, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client2"); |
| |
| /* notify that event1 is handled */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* notify that event2 is handled */ |
| rc = event_client_notify_handled(_state->hevt2); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source again: should be handled */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_source_resignal_signaled) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* open named event again */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt2); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* signal event again */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: should be signaled */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* wait on client 2: should be signaled */ |
| rc = handle_wait(_state->hevt2, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client2"); |
| |
| /* notify that event1 is handled */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* notify that event2 is handled */ |
| rc = event_client_notify_handled(_state->hevt2); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source: should be handled */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_source_resignal_notified) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* open named event again */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt2); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: to put it into notifieed state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* signal event again */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* notify that event1 is handled: it should enter signaled state */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on client 2: should be signaled */ |
| rc = handle_wait(_state->hevt2, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client2"); |
| |
| /* notify that event2 is handled to put it into unsignaled state */ |
| rc = event_client_notify_handled(_state->hevt2); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source: should timeout as event1 stil signaled */ |
| rc = handle_wait(_state->hevts, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on source"); |
| |
| /* wait on client 1: should be signaled */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* notify that event1 is handled to put it into unsignaled state */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source: should be handled */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_source_resignal_handled) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* open named event again */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt2); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: to put it into notified state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* notify that event1 is handled to put it into unsignaled state */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* signal event again to put event 1 into signaled state */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 2: should be in signaled state */ |
| rc = handle_wait(_state->hevt2, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client2"); |
| |
| /* notify that event2 is handled to put it into unsignaled state */ |
| rc = event_client_notify_handled(_state->hevt2); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source: should timeout as event1 still signaled */ |
| rc = handle_wait(_state->hevts, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on source"); |
| |
| /* wait on client 1: to put it into notified state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* notify that event1 is handled to put it into unsignaled state */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source: should be in handled */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_source_close) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* close sevent source */ |
| handle_close(_state->hevts); |
| _state->hevts = NULL; |
| |
| /* wait on closed client: should return HUP event */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| EXPECT_EQ(1, !!(uevt & IPC_HANDLE_POLL_HUP)); |
| |
| /* Invoke notify on client with closed source */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(ERR_CHANNEL_CLOSED, rc, "notify event handled"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_close_signaled) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* close signaled event */ |
| handle_close(_state->hevt1); |
| _state->hevt1 = NULL; |
| |
| /* wait on event source: should not block */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_close_notified) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: to put it into notified state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* close client */ |
| handle_close(_state->hevt1); |
| _state->hevt1 = NULL; |
| |
| /* wait on event source: should not block */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_close_notified_signaled) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: to put it into notified state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* signal event to put it intonotified signaled state */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* close client */ |
| handle_close(_state->hevt1); |
| _state->hevt1 = NULL; |
| |
| /* wait on event source: should not block */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_ack_unread) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* |
| * Notify that event1 is handled: should error because we need to wait on |
| * event first |
| */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(ERR_BAD_STATE, rc, "notify event handled"); |
| |
| /* wait on client 1: to put it into notifird state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* notify that event1 is handled: should be OK */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| test_abort:; |
| } |
| |
| TEST_F(uirq, event_client_wait_on_notified_signaled) { |
| int rc; |
| uint32_t uevt; |
| struct uuid cid = zero_uuid; |
| |
| /* create named event source */ |
| rc = event_source_create(TEST_EVS_NAME1, NULL, NULL, NULL, 0, 0, |
| &_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| rc = event_source_publish(_state->hevts); |
| ASSERT_EQ(0, rc); |
| |
| /* open the named event */ |
| rc = event_source_open(&cid, TEST_EVS_NAME1, strlen(TEST_EVS_NAME1) + 1, 0, |
| &_state->hevt1); |
| ASSERT_EQ(0, rc); |
| |
| /* signal event */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: should be signaled: enters notified state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* signal event again to put is into notified signaled state */ |
| rc = event_source_signal(_state->hevts); |
| EXPECT_EQ(0, rc, "notify event signaled"); |
| |
| /* wait on client 1: should timeout as it is in notified signaled state */ |
| rc = handle_wait(_state->hevt1, &uevt, EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(ERR_TIMED_OUT, rc, "wait on client1"); |
| |
| /* |
| * notify that event1 is handled: shoudl be OK: puts event into signaled |
| * state |
| */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on client 1: should be signaled as it is in signaled state */ |
| rc = handle_wait(_state->hevt1, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on client1"); |
| |
| /* notify that event1 is handled to put source into handled state */ |
| rc = event_client_notify_handled(_state->hevt1); |
| EXPECT_EQ(0, rc, "notify event handled"); |
| |
| /* wait on event source: should be in handled state */ |
| rc = handle_wait(_state->hevts, &uevt, NOT_EXPECTED_TO_FAIL_TIMEOUT_MSEC); |
| EXPECT_EQ(0, rc, "wait on source"); |
| |
| test_abort:; |
| } |
| |
| PORT_TEST(uirq, "com.android.kernel.uirq-unittest"); |