1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2017, Intel Corporation
4  * All rights reserved.
5  */
6 #include <glib.h>
7 
8 #include <errno.h>
9 #include <gio/gunixinputstream.h>
10 #include <gio/gunixoutputstream.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 
17 #include <setjmp.h>
18 #include <cmocka.h>
19 
20 #include "connection.h"
21 #include "util.h"
22 
23 typedef struct connection_test_data {
24     Connection *connection;
25     GIOStream  *client_iostream;
26 } connection_test_data_t;
27 /*
28  * Data goes in the iostream_in, and out the iostream_out.
29  */
30 static int
write_read(GIOStream * iostream_in,GIOStream * iostream_out,const char * buf,ssize_t length)31 write_read (GIOStream  *iostream_in,
32             GIOStream  *iostream_out,
33             const char *buf,
34             ssize_t      length)
35 {
36     char out_buf[256] = { 0 };
37     ssize_t ret;
38     GInputStream *istream;
39     GOutputStream *ostream;
40 
41     ostream = g_io_stream_get_output_stream (iostream_in);
42     ret = g_output_stream_write (ostream, buf, length, NULL, NULL);
43     if (ret != length)
44         g_error ("error writing to fds[1]: %s", strerror (errno));
45     istream = g_io_stream_get_input_stream (iostream_out);
46     ret = g_input_stream_read (istream, out_buf, length, NULL, NULL);
47     if (ret != length)
48         g_error ("error reading from fds[0]: %s", strerror (errno));
49 
50     return ret;
51 }
52 
53 static void
connection_allocate_test(void ** state)54 connection_allocate_test (void **state)
55 {
56     HandleMap   *handle_map = NULL;
57     Connection *connection = NULL;
58     gint client_fd;
59     GIOStream *iostream;
60     UNUSED_PARAM(state);
61 
62     handle_map = handle_map_new (TPM2_HT_TRANSIENT, MAX_ENTRIES_DEFAULT);
63     iostream = create_connection_iostream (&client_fd);
64     connection = connection_new (iostream, 0, handle_map);
65     g_object_unref (handle_map);
66     g_object_unref (iostream);
67     assert_non_null (connection);
68     assert_true (client_fd >= 0);
69     g_object_unref (connection);
70 }
71 
72 static int
connection_setup(void ** state)73 connection_setup (void **state)
74 {
75     connection_test_data_t *data = NULL;
76     HandleMap *handle_map = NULL;
77     int client_fd;
78     GIOStream *iostream;
79     GSocket *socket;
80 
81     data = calloc (1, sizeof (connection_test_data_t));
82     assert_non_null (data);
83     handle_map = handle_map_new (TPM2_HT_TRANSIENT, MAX_ENTRIES_DEFAULT);
84     iostream = create_connection_iostream (&client_fd);
85     data->connection = connection_new (iostream, 0, handle_map);
86     g_object_unref (iostream);
87     socket = g_socket_new_from_fd (client_fd, NULL);
88     data->client_iostream =
89         G_IO_STREAM (g_socket_connection_factory_create_connection (socket));
90     g_object_unref (socket);
91     assert_non_null (data->connection);
92     g_object_unref (handle_map);
93     *state = data;
94     return 0;
95 }
96 
97 static int
connection_teardown(void ** state)98 connection_teardown (void **state)
99 {
100     connection_test_data_t *data = (connection_test_data_t*)*state;
101 
102     g_object_unref (data->connection);
103     g_object_unref (data->client_iostream);
104     free (data);
105     return 0;
106 }
107 
108 static void
connection_key_socket_test(void ** state)109 connection_key_socket_test (void **state)
110 {
111     connection_test_data_t *data = (connection_test_data_t*)*state;
112     Connection *connection = CONNECTION (data->connection);
113     gpointer *key = NULL;
114 
115     key = connection_key_istream (connection);
116     assert_ptr_equal (g_io_stream_get_input_stream (connection->iostream),
117                                                     key);
118 }
119 
120 static void
connection_key_id_test(void ** state)121 connection_key_id_test (void **state)
122 {
123     connection_test_data_t *data = (connection_test_data_t*)*state;
124     Connection *connection = CONNECTION (data->connection);
125     guint64 *key = NULL;
126 
127     key = (guint64*)connection_key_id (connection);
128     assert_int_equal (connection->id, *key);
129 }
130 
131 /* connection_client_to_server_test begin
132  * This test creates a connection and communicates with it as though the pipes
133  * that are created as part of connection setup.
134  */
135 static void
connection_client_to_server_test(void ** state)136 connection_client_to_server_test (void ** state)
137 {
138     connection_test_data_t *data = (connection_test_data_t*)*state;
139     gint ret = 0;
140 
141     ret = write_read (data->connection->iostream, data->client_iostream, "test", strlen ("test"));
142     if (ret == -1)
143         g_print ("write_read failed: %d\n", ret);
144     assert_int_equal (ret, strlen ("test"));
145 }
146 /* connection_client_to_server_test end */
147 /* connection_server_to_client_test begin
148  * Do the same in the reverse direction.
149  */
150 static void
connection_server_to_client_test(void ** state)151 connection_server_to_client_test (void **state)
152 {
153     connection_test_data_t *data = (connection_test_data_t*)*state;
154     gint ret = 0;
155 
156     ret = write_read (data->client_iostream,
157                       data->connection->iostream,
158                       "test",
159                       strlen ("test"));
160     if (ret == -1)
161         g_print ("write_read failed: %d\n", ret);
162     assert_int_equal (ret, strlen ("test"));
163 }
164 /* connection_server_to_client_test end */
165 
166 int
main(void)167 main(void)
168 {
169     const struct CMUnitTest tests[] = {
170         cmocka_unit_test (connection_allocate_test),
171         cmocka_unit_test_setup_teardown (connection_key_socket_test,
172                                          connection_setup,
173                                          connection_teardown),
174         cmocka_unit_test_setup_teardown (connection_key_id_test,
175                                          connection_setup,
176                                          connection_teardown),
177         cmocka_unit_test_setup_teardown (connection_client_to_server_test,
178                                          connection_setup,
179                                          connection_teardown),
180         cmocka_unit_test_setup_teardown (connection_server_to_client_test,
181                                          connection_setup,
182                                          connection_teardown),
183     };
184     return cmocka_run_group_tests(tests, NULL, NULL);
185 }
186