1// Copyright 2016 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <lib/sync/completion.h>
6
7#include <zircon/syscalls.h>
8#include <unittest/unittest.h>
9#include <stddef.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <threads.h>
14
15static sync_completion_t completion;
16
17#define ITERATIONS 64
18
19static int sync_completion_thread_wait(void* arg) {
20    for (int iteration = 0u; iteration < ITERATIONS; iteration++) {
21        zx_status_t status = sync_completion_wait(&completion, ZX_TIME_INFINITE);
22        ASSERT_EQ(status, ZX_OK, "completion wait failed!");
23    }
24
25    return 0;
26}
27
28static int sync_completion_thread_signal(void* arg) {
29    for (int iteration = 0u; iteration < ITERATIONS; iteration++) {
30        sync_completion_reset(&completion);
31        zx_nanosleep(zx_deadline_after(ZX_USEC(10)));
32        sync_completion_signal(&completion);
33    }
34
35    return 0;
36}
37
38static bool test_initializer(void) {
39    BEGIN_TEST;
40    // Let's not accidentally break .bss'd completions
41    static sync_completion_t static_completion;
42    sync_completion_t completion;
43    int status = memcmp(&static_completion, &completion, sizeof(sync_completion_t));
44    EXPECT_EQ(status, 0, "completion's initializer is not all zeroes");
45    END_TEST;
46}
47
48#define NUM_THREADS 16
49
50static bool test_completions(void) {
51    BEGIN_TEST;
52    thrd_t signal_thread;
53    thrd_t wait_thread[NUM_THREADS];
54
55    for (int idx = 0; idx < NUM_THREADS; idx++)
56        thrd_create_with_name(wait_thread + idx, sync_completion_thread_wait, NULL, "completion wait");
57    thrd_create_with_name(&signal_thread, sync_completion_thread_signal, NULL, "completion signal");
58
59    for (int idx = 0; idx < NUM_THREADS; idx++)
60        thrd_join(wait_thread[idx], NULL);
61    thrd_join(signal_thread, NULL);
62
63    END_TEST;
64}
65
66static bool test_timeout(void) {
67    BEGIN_TEST;
68    zx_time_t timeout = 0u;
69    sync_completion_t completion;
70    for (int iteration = 0; iteration < 1000; iteration++) {
71        timeout += 2000u;
72        zx_status_t status = sync_completion_wait(&completion, timeout);
73        ASSERT_EQ(status, ZX_ERR_TIMED_OUT, "wait returned spuriously!");
74    }
75    END_TEST;
76}
77
78BEGIN_TEST_CASE(sync_completion_tests)
79RUN_TEST(test_initializer)
80RUN_TEST(test_completions)
81RUN_TEST(test_timeout)
82END_TEST_CASE(sync_completion_tests)
83