File: s2n_init_test.c

package info (click to toggle)
aws-crt-python 0.24.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 75,932 kB
  • sloc: ansic: 418,984; python: 23,626; makefile: 6,035; sh: 4,075; ruby: 208; java: 82; perl: 73; cpp: 25; xml: 11
file content (132 lines) | stat: -rw-r--r-- 4,657 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 <pthread.h>

#include "api/unstable/cleanup.h"
#include "s2n_test.h"

bool s2n_is_initialized(void);

static void *s2n_init_fail_cb(void *_unused_arg)
{
    (void) _unused_arg;

    EXPECT_FAILURE_WITH_ERRNO(s2n_init(), S2N_ERR_INITIALIZED);
    return NULL;
}

static void *s2n_init_success_cb(void *_unused_arg)
{
    (void) _unused_arg;

    EXPECT_SUCCESS(s2n_init());
    return NULL;
}

static void *s2n_cleanup_thread_cb(void *_unused_arg)
{
    (void) _unused_arg;

    EXPECT_SUCCESS(s2n_cleanup_thread());
    return NULL;
}

int main(int argc, char **argv)
{
    BEGIN_TEST_NO_INIT();

    /* Calling s2n_init twice in a row will cause an error */
    EXPECT_SUCCESS(s2n_init());
    EXPECT_FAILURE_WITH_ERRNO(s2n_init(), S2N_ERR_INITIALIZED);
    EXPECT_SUCCESS(s2n_cleanup_final());

    /* Second call to s2n_cleanup_final will fail, since the full cleanup is not idempotent. */
    EXPECT_FAILURE_WITH_ERRNO(s2n_cleanup_final(), S2N_ERR_NOT_INITIALIZED);

    /* Clean up and init multiple times */
    for (size_t i = 0; i < 10; i++) {
        EXPECT_SUCCESS(s2n_init());
        EXPECT_SUCCESS(s2n_cleanup_final());
    }

    /* Calling s2n_init again after creating a process will cause an error */
    EXPECT_SUCCESS(s2n_init());
    int pid = fork();
    if (pid == 0) {
        /* Child process */
        EXPECT_FAILURE_WITH_ERRNO(s2n_init(), S2N_ERR_INITIALIZED);
        EXPECT_SUCCESS(s2n_cleanup());
        return 0;
    }
    EXPECT_SUCCESS(s2n_cleanup_final());

    /* Calling s2n_init again after creating a thread will cause an error */
    EXPECT_SUCCESS(s2n_init());
    pthread_t init_thread = { 0 };
    EXPECT_EQUAL(pthread_create(&init_thread, NULL, s2n_init_fail_cb, NULL), 0);
    EXPECT_EQUAL(pthread_join(init_thread, NULL), 0);
    EXPECT_SUCCESS(s2n_cleanup_final());

    /* Calling s2n_init/s2n_cleanup_final in a different thread than s2n_cleanup_thread is called cleans up properly */
    {
        EXPECT_SUCCESS(s2n_init());
        EXPECT_TRUE(s2n_is_initialized());
        pthread_t s2n_cleanup_th = { 0 };
        EXPECT_EQUAL(pthread_create(&s2n_cleanup_th, NULL, s2n_cleanup_thread_cb, NULL), 0);
        EXPECT_EQUAL(pthread_join(s2n_cleanup_th, NULL), 0);
        EXPECT_TRUE(s2n_is_initialized());
        /* Calling s2n_cleanup_thread in the main thread leaves s2n initialized. */
        EXPECT_SUCCESS(s2n_cleanup_thread());
        EXPECT_TRUE(s2n_is_initialized());
        EXPECT_SUCCESS(s2n_cleanup_final());
        EXPECT_FALSE(s2n_is_initialized());
        /* Second call to s2n_cleanup_final will fail, since the full cleanup is not idempotent. */
        EXPECT_FAILURE_WITH_ERRNO(s2n_cleanup_final(), S2N_ERR_NOT_INITIALIZED);
    }

    /* s2n_cleanup_final */
    {
        /* s2n_cleanup_final fully de-initializes the library */
        EXPECT_SUCCESS(s2n_init());
        EXPECT_TRUE(s2n_is_initialized());
        EXPECT_SUCCESS(s2n_cleanup_final());
        EXPECT_FALSE(s2n_is_initialized());

        /* s2n_cleanup only cleans up thread-local storage.
         * Therefore, calling s2n_cleanup_final after s2n_cleanup will succeed */
        EXPECT_SUCCESS(s2n_init());
        EXPECT_SUCCESS(s2n_cleanup());
        EXPECT_SUCCESS(s2n_cleanup_final());

        /* s2n_cleanup_thread only cleans up thread-local storage.
         * Therefore calling s2n_cleanup_final after s2n_cleanup_thread will succeed  */
        EXPECT_SUCCESS(s2n_init());
        EXPECT_SUCCESS(s2n_cleanup_thread());
        EXPECT_SUCCESS(s2n_cleanup_final());
    }

    /* The following test requires atexit to be enabled. */
    EXPECT_SUCCESS(s2n_enable_atexit());

    /* Initializing s2n on a child thread without calling s2n_cleanup on that
     * thread will not result in a memory leak. This is because we register
     * thread-local memory to be cleaned up at thread-exit. */
    pthread_t init_success_thread = { 0 };
    EXPECT_EQUAL(pthread_create(&init_success_thread, NULL, s2n_init_success_cb, NULL), 0);
    EXPECT_EQUAL(pthread_join(init_success_thread, NULL), 0);

    END_TEST_NO_INIT();
}