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