zeshuai007 | c80b8bb | 2020-07-23 09:43:41 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | * or more contributor license agreements. See the NOTICE file |
| 4 | * distributed with this work for additional information |
| 5 | * regarding copyright ownership. The ASF licenses this file |
| 6 | * to you under the Apache License, Version 2.0 (the |
| 7 | * "License"); you may not use this file except in compliance |
| 8 | * with the License. You may obtain a copy of the License at |
| 9 | * |
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | * |
| 12 | * Unless required by applicable law or agreed to in writing, |
| 13 | * software distributed under the License is distributed on an |
| 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | * KIND, either express or implied. See the License for the |
| 16 | * specific language governing permissions and limitations |
| 17 | * under the License. |
| 18 | */ |
| 19 | #ifdef __GLIBC__ |
| 20 | #include <features.h> |
| 21 | #define __NO_STRING_INLINES 1 |
| 22 | #endif |
| 23 | |
| 24 | #include <unistd.h> |
| 25 | #include <stdlib.h> |
| 26 | #include <stdio.h> |
| 27 | #include <netdb.h> |
| 28 | #include <string.h> |
| 29 | #include <sys/wait.h> |
| 30 | |
| 31 | #include <thrift/c_glib/protocol/thrift_protocol.h> |
| 32 | #include <thrift/c_glib/transport/thrift_socket.h> |
| 33 | #include <thrift/c_glib/transport/thrift_server_socket.h> |
| 34 | #include <thrift/c_glib/transport/thrift_framed_transport.h> |
| 35 | |
| 36 | #define TEST_BOOL TRUE |
| 37 | #define TEST_BYTE 123 |
| 38 | #define TEST_I16 12345 |
| 39 | #define TEST_I32 1234567890 |
| 40 | #define TEST_I64 G_GINT64_CONSTANT (123456789012345) |
| 41 | #define TEST_DOUBLE 1234567890.123 |
| 42 | #define TEST_STRING "this is a test string 1234567890!@#$%^&*()" |
| 43 | #define TEST_PORT 51199 |
| 44 | |
| 45 | #define MAX_MESSAGE_SIZE 4 |
| 46 | |
| 47 | static int transport_read_count = 0; |
| 48 | static int transport_read_error = 0; |
| 49 | static int transport_read_error_at = -1; |
| 50 | gint32 |
| 51 | my_thrift_transport_read_all (ThriftTransport *transport, gpointer buf, |
| 52 | guint32 len, GError **error) |
| 53 | { |
| 54 | if (transport_read_count != transport_read_error_at |
| 55 | && transport_read_error == 0) |
| 56 | { |
| 57 | transport_read_count++; |
| 58 | return thrift_transport_read_all (transport, buf, len, error); |
| 59 | } |
| 60 | return -1; |
| 61 | } |
| 62 | |
| 63 | static int transport_write_count = 0; |
| 64 | static int transport_write_error = 0; |
| 65 | static int transport_write_error_at = -1; |
| 66 | gboolean |
| 67 | my_thrift_transport_write (ThriftTransport *transport, const gpointer buf, |
| 68 | const guint32 len, GError **error) |
| 69 | { |
| 70 | if (transport_write_count != transport_write_error_at |
| 71 | && transport_write_error == 0) |
| 72 | { |
| 73 | transport_write_count++; |
| 74 | return thrift_transport_write (transport, buf, len, error); |
| 75 | } |
| 76 | return FALSE; |
| 77 | } |
| 78 | |
| 79 | #define thrift_transport_read_all my_thrift_transport_read_all |
| 80 | #define thrift_transport_write my_thrift_transport_write |
| 81 | #include "../src/thrift/c_glib/protocol/thrift_binary_protocol.c" |
| 82 | #undef thrift_transport_read_all |
| 83 | #undef thrift_transport_write |
| 84 | |
| 85 | static void thrift_server_complex_types (const int port); |
| 86 | |
| 87 | static void |
| 88 | test_create_and_destroy (void) |
| 89 | { |
| 90 | GObject *object = NULL; |
| 91 | |
| 92 | /* create an object and then destroy it */ |
| 93 | object = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, NULL); |
| 94 | g_assert (object !=NULL); |
| 95 | g_object_unref (object); |
| 96 | } |
| 97 | |
| 98 | static void |
| 99 | test_initialize (void) |
| 100 | { |
| 101 | ThriftConfiguration *tconfiguration = NULL; |
| 102 | ThriftSocket *tsocket = NULL; |
| 103 | ThriftBinaryProtocol *bprotocol = NULL; |
| 104 | ThriftSocket *temp = NULL; |
| 105 | ThriftConfiguration *tempconf = NULL; |
| 106 | |
| 107 | glong tempsize = 0; |
| 108 | |
| 109 | /* create a ThriftConfiguration */ |
| 110 | tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE, |
| 111 | "max_frame_size", MAX_MESSAGE_SIZE, NULL); |
| 112 | g_assert (tconfiguration != NULL); |
| 113 | /* create a ThriftTransport */ |
| 114 | tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", |
| 115 | "port", 51188, "path", NULL, |
| 116 | "configuration", tconfiguration, |
| 117 | "remainingmessagesize", tconfiguration->maxMessageSize_, NULL); |
| 118 | g_assert (tsocket != NULL); |
| 119 | /* fetch the properties */ |
| 120 | g_object_get (G_OBJECT (tconfiguration), "max_message_size", &tempsize, NULL); |
| 121 | g_assert (tempsize == MAX_MESSAGE_SIZE); |
| 122 | /* fetch the properties */ |
| 123 | g_object_get (G_OBJECT (tsocket), "remainingmessagesize", &tempsize, NULL); |
| 124 | g_assert (tempsize == MAX_MESSAGE_SIZE); |
| 125 | /* fetch the properties */ |
| 126 | g_object_get (G_OBJECT (tsocket), "configuration", &tempconf, NULL); |
| 127 | g_object_unref (tempconf); |
| 128 | /* create a ThriftBinaryProtocol using Transport */ |
| 129 | bprotocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", tsocket, NULL); |
| 130 | g_assert (bprotocol != NULL); |
| 131 | /* fetch the properties */ |
| 132 | g_object_get (G_OBJECT (bprotocol), "transport", &temp, NULL); |
| 133 | g_object_unref (temp); |
| 134 | |
| 135 | /* clean up memory */ |
| 136 | g_object_unref (bprotocol); |
| 137 | g_object_unref (tsocket); |
| 138 | g_object_unref (tconfiguration); |
| 139 | } |
| 140 | |
| 141 | void |
| 142 | test_read_and_wirte_complex_types (void) |
| 143 | { |
| 144 | int status; |
| 145 | pid_t pid; |
| 146 | ThriftConfiguration *tconfiguration = NULL; |
| 147 | ThriftSocket *tsocket = NULL; |
| 148 | ThriftTransport *transport = NULL; |
| 149 | ThriftBinaryProtocol *tb = NULL; |
| 150 | ThriftProtocol *protocol = NULL; |
| 151 | int port = TEST_PORT; |
| 152 | |
| 153 | /* fork a server from the client */ |
| 154 | pid = fork (); |
| 155 | g_assert (pid >= 0); |
| 156 | |
| 157 | if (pid == 0) |
| 158 | { |
| 159 | /* child listens */ |
| 160 | thrift_server_complex_types (port); |
| 161 | exit (0); |
| 162 | } else { |
| 163 | /* parent. wait a bit for the socket to be created. */ |
| 164 | sleep (1); |
| 165 | |
| 166 | /* create a ThriftConfiguration */ |
| 167 | tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE, |
| 168 | "max_frame_size", MAX_MESSAGE_SIZE, NULL); |
| 169 | g_assert (tconfiguration != NULL); |
| 170 | |
| 171 | /* create a ThriftSocket */ |
| 172 | tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", |
| 173 | "port", port, "path", NULL, |
| 174 | "configuration", tconfiguration, NULL); |
| 175 | transport = THRIFT_TRANSPORT (tsocket); |
zeshuai007 | 997e2d4 | 2020-09-29 14:43:18 +0800 | [diff] [blame] | 176 | THRIFT_TRANSPORT_GET_CLASS (tsocket)->resetConsumedMessageSize(THRIFT_TRANSPORT (tsocket), -1, NULL); |
zeshuai007 | c80b8bb | 2020-07-23 09:43:41 +0800 | [diff] [blame] | 177 | thrift_transport_open (transport, NULL); |
| 178 | g_assert (thrift_transport_is_open (transport)); |
| 179 | |
| 180 | /* create a ThriftBinaryTransport */ |
| 181 | tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", |
| 182 | tsocket, NULL); |
| 183 | protocol = THRIFT_PROTOCOL (tb); |
| 184 | g_assert (protocol != NULL); |
| 185 | |
| 186 | /* test 1st write failure on a map */ |
| 187 | g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_BYTE, |
| 188 | 1, NULL) > 0); |
| 189 | g_assert (thrift_binary_protocol_write_map_end (protocol, NULL) == 0); |
| 190 | |
| 191 | g_assert (thrift_binary_protocol_write_map_begin (protocol, T_I32, T_BYTE, |
| 192 | 1, NULL) > 0); |
| 193 | g_assert (thrift_binary_protocol_write_map_end (protocol, NULL) == 0); |
| 194 | |
| 195 | /* test list operations */ |
| 196 | g_assert (thrift_binary_protocol_write_list_begin (protocol, T_BYTE, |
| 197 | 1, NULL) > 0); |
| 198 | g_assert (thrift_binary_protocol_write_list_end (protocol, NULL) == 0); |
| 199 | |
| 200 | g_assert (thrift_binary_protocol_write_list_begin (protocol, T_I32, |
| 201 | 10, NULL) > 0); |
| 202 | g_assert (thrift_binary_protocol_write_list_end (protocol, NULL) == 0); |
| 203 | |
| 204 | /* clean up */ |
| 205 | thrift_transport_close (transport, NULL); |
| 206 | g_object_unref (tsocket); |
| 207 | g_object_unref (protocol); |
| 208 | g_object_unref (tconfiguration); |
| 209 | g_assert (wait (&status) == pid); |
| 210 | g_assert (status == 0); |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | static void |
| 215 | thrift_server_complex_types (const int port) |
| 216 | { |
| 217 | ThriftServerTransport *transport = NULL; |
| 218 | ThriftTransport *client = NULL; |
| 219 | ThriftBinaryProtocol *tbp = NULL; |
| 220 | ThriftProtocol *protocol = NULL; |
| 221 | ThriftType element_type = T_VOID, |
| 222 | key_type = T_VOID, |
| 223 | value_type = T_VOID; |
zeshuai007 | c80b8bb | 2020-07-23 09:43:41 +0800 | [diff] [blame] | 224 | guint32 size = 0; |
zeshuai007 | c80b8bb | 2020-07-23 09:43:41 +0800 | [diff] [blame] | 225 | |
| 226 | ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, |
| 227 | "max_message_size", MAX_MESSAGE_SIZE, |
| 228 | "max_frame_size", MAX_MESSAGE_SIZE, NULL); |
| 229 | |
| 230 | ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, |
| 231 | "configuration", tconfiguration, NULL); |
| 232 | transport = THRIFT_SERVER_TRANSPORT (tsocket); |
| 233 | THRIFT_SERVER_TRANSPORT_GET_CLASS (tsocket)->resetConsumedMessageSize(transport, -1, NULL); |
| 234 | thrift_server_transport_listen (transport, NULL); |
| 235 | client = thrift_server_transport_accept (transport, NULL); |
| 236 | g_assert (client != NULL); |
| 237 | |
| 238 | tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", |
| 239 | client, NULL); |
| 240 | protocol = THRIFT_PROTOCOL(tbp); |
| 241 | |
| 242 | g_assert (thrift_binary_protocol_read_map_begin (protocol, &key_type, &value_type, |
| 243 | &size, NULL) > 0); |
| 244 | g_assert (thrift_binary_protocol_read_map_end (protocol, NULL) == 0); |
| 245 | |
| 246 | g_assert (thrift_binary_protocol_read_map_begin (protocol, &key_type, &value_type, |
| 247 | &size, NULL) == -1); |
| 248 | g_assert (thrift_binary_protocol_read_map_end (protocol, NULL) == 0); |
| 249 | |
| 250 | /* test read failure */ |
| 251 | g_assert (thrift_binary_protocol_read_list_begin (protocol, &element_type, |
| 252 | &size, NULL) > 0); |
| 253 | g_assert (thrift_binary_protocol_read_list_end(protocol, NULL) == 0); |
| 254 | |
| 255 | g_assert (thrift_binary_protocol_read_list_begin (protocol, &element_type, |
| 256 | &size, NULL) == -1); |
| 257 | g_assert (thrift_binary_protocol_read_list_end(protocol, NULL) == 0); |
| 258 | |
| 259 | g_object_unref (client); |
| 260 | /* TODO: investigate g_object_unref (tbp); */ |
| 261 | g_object_unref (tsocket); |
| 262 | g_object_unref (tconfiguration); |
| 263 | } |
| 264 | |
| 265 | int |
| 266 | main (int argc, char *argv[]) |
| 267 | { |
| 268 | #if (!GLIB_CHECK_VERSION (2, 36, 0)) |
| 269 | g_type_init (); |
| 270 | #endif |
| 271 | |
| 272 | g_test_init (&argc, &argv, NULL); |
| 273 | |
| 274 | g_test_add_func ("/testthriftbinaryreadcheck/CreateAndDestroy", test_create_and_destroy); |
| 275 | g_test_add_func ("/testthriftbinaryreadcheck/Initialize", test_initialize); |
| 276 | g_test_add_func ("/testthriftbinaryreadcheck/test_read_and_write_complex_types", test_read_and_wirte_complex_types); |
| 277 | |
| 278 | return g_test_run (); |
| 279 | } |