| Roger Meier | c101092 | 2010-11-26 10:17:48 +0000 | [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 |  | 
| Roger Meier | 213a664 | 2010-10-27 12:30:11 +0000 | [diff] [blame] | 20 | #include <assert.h> | 
|  | 21 | #include <netdb.h> | 
|  | 22 |  | 
| Roger Meier | e3da768 | 2013-01-11 11:41:53 +0100 | [diff] [blame^] | 23 | #include <thrift/c_glib/transport/thrift_transport.h> | 
|  | 24 | #include <thrift/c_glib/transport/thrift_server_transport.h> | 
|  | 25 | #include <thrift/c_glib/transport/thrift_server_socket.h> | 
| Roger Meier | 213a664 | 2010-10-27 12:30:11 +0000 | [diff] [blame] | 26 |  | 
|  | 27 | #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } | 
|  | 28 |  | 
|  | 29 | /* substituted functions to test failures of system and library calls */ | 
|  | 30 | static int socket_error = 0; | 
|  | 31 | int | 
|  | 32 | my_socket(int domain, int type, int protocol) | 
|  | 33 | { | 
|  | 34 | if (socket_error == 0) | 
|  | 35 | { | 
|  | 36 | return socket (domain, type, protocol); | 
|  | 37 | } | 
|  | 38 | return -1; | 
|  | 39 | } | 
|  | 40 |  | 
|  | 41 | static int recv_error = 0; | 
|  | 42 | ssize_t | 
|  | 43 | my_recv(int socket, void *buffer, size_t length, int flags) | 
|  | 44 | { | 
|  | 45 | if (recv_error == 0) | 
|  | 46 | { | 
|  | 47 | return recv (socket, buffer, length, flags); | 
|  | 48 | } | 
|  | 49 | return -1; | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | static int send_error = 0; | 
|  | 53 | ssize_t | 
|  | 54 | my_send(int socket, const void *buffer, size_t length, int flags) | 
|  | 55 | { | 
|  | 56 | if (send_error == 0) | 
|  | 57 | { | 
|  | 58 | return send (socket, buffer, length, flags); | 
|  | 59 | } | 
|  | 60 | return -1; | 
|  | 61 | } | 
|  | 62 |  | 
|  | 63 | #define socket my_socket | 
|  | 64 | #define recv my_recv | 
|  | 65 | #define send my_send | 
| Roger Meier | e3da768 | 2013-01-11 11:41:53 +0100 | [diff] [blame^] | 66 | #include "../src/thrift/c_glib/transport/thrift_socket.c" | 
| Roger Meier | 213a664 | 2010-10-27 12:30:11 +0000 | [diff] [blame] | 67 | #undef socket | 
|  | 68 | #undef recv | 
|  | 69 | #undef send | 
|  | 70 |  | 
|  | 71 | static const char TEST_ADDRESS[] = "localhost"; | 
|  | 72 | static const short TEST_PORT = 64444; | 
|  | 73 |  | 
|  | 74 | static void thrift_socket_server (const int port); | 
|  | 75 |  | 
|  | 76 | /* test object creation and destruction */ | 
|  | 77 | static void | 
|  | 78 | test_create_and_destroy(void) | 
|  | 79 | { | 
|  | 80 | gchar *hostname = NULL; | 
|  | 81 | guint port = 0; | 
|  | 82 |  | 
|  | 83 | GObject *object = NULL; | 
|  | 84 | object = g_object_new (THRIFT_TYPE_SOCKET, NULL); | 
|  | 85 | assert (object != NULL); | 
|  | 86 | g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, NULL); | 
|  | 87 | g_free (hostname); | 
|  | 88 |  | 
|  | 89 | g_object_unref (object); | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | static void | 
|  | 93 | test_open_and_close(void) | 
|  | 94 | { | 
|  | 95 | ThriftSocket *tsocket = NULL; | 
|  | 96 | ThriftTransport *transport = NULL; | 
|  | 97 | GError *err = NULL; | 
|  | 98 |  | 
|  | 99 | /* open a connection and close it */ | 
|  | 100 | tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", | 
|  | 101 | "port", 51188, NULL); | 
|  | 102 | transport = THRIFT_TRANSPORT (tsocket); | 
|  | 103 | thrift_socket_open (transport, NULL); | 
|  | 104 | assert (thrift_socket_is_open (transport) == TRUE); | 
|  | 105 | thrift_socket_close (transport, NULL); | 
|  | 106 | assert (thrift_socket_is_open (transport) == FALSE); | 
|  | 107 |  | 
|  | 108 | /* test close failure */ | 
|  | 109 | tsocket->sd = -1; | 
|  | 110 | thrift_socket_close (transport, NULL); | 
|  | 111 | g_object_unref (tsocket); | 
|  | 112 |  | 
|  | 113 | /* try a hostname lookup failure */ | 
|  | 114 | tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken", | 
|  | 115 | NULL); | 
|  | 116 | transport = THRIFT_TRANSPORT (tsocket); | 
|  | 117 | assert (thrift_socket_open (transport, &err) == FALSE); | 
|  | 118 | g_object_unref (tsocket); | 
|  | 119 | g_error_free (err); | 
|  | 120 | err = NULL; | 
|  | 121 |  | 
|  | 122 | /* try an error call to socket() */ | 
|  | 123 | tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", NULL); | 
|  | 124 | transport = THRIFT_TRANSPORT (tsocket); | 
|  | 125 | socket_error = 1; | 
|  | 126 | assert (thrift_socket_open (transport, &err) == FALSE); | 
|  | 127 | socket_error = 0; | 
|  | 128 | g_object_unref (tsocket); | 
|  | 129 | g_error_free (err); | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 | static void | 
|  | 133 | test_read_and_write(void) | 
|  | 134 | { | 
|  | 135 | int status; | 
|  | 136 | pid_t pid; | 
|  | 137 | ThriftSocket *tsocket = NULL; | 
|  | 138 | ThriftTransport *transport = NULL; | 
|  | 139 | int port = 51199; | 
|  | 140 | guchar buf[10] = TEST_DATA; /* a buffer */ | 
|  | 141 |  | 
|  | 142 | pid = fork (); | 
|  | 143 | assert ( pid >= 0 ); | 
|  | 144 |  | 
|  | 145 | if ( pid == 0 ) | 
|  | 146 | { | 
|  | 147 | /* child listens */ | 
|  | 148 | thrift_socket_server (port); | 
|  | 149 | exit (0); | 
|  | 150 | } else { | 
|  | 151 | /* parent connects, wait a bit for the socket to be created */ | 
|  | 152 | sleep (1); | 
|  | 153 |  | 
|  | 154 | tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", | 
|  | 155 | "port", port, NULL); | 
|  | 156 | transport = THRIFT_TRANSPORT (tsocket); | 
|  | 157 | assert (thrift_socket_open (transport, NULL) == TRUE); | 
|  | 158 | assert (thrift_socket_is_open (transport)); | 
|  | 159 | thrift_socket_write (transport, buf, 10, NULL); | 
|  | 160 |  | 
|  | 161 | /* write fail */ | 
|  | 162 | send_error = 1; | 
|  | 163 | thrift_socket_write (transport, buf, 1, NULL); | 
|  | 164 | send_error = 0; | 
|  | 165 |  | 
|  | 166 | thrift_socket_write_end (transport, NULL); | 
|  | 167 | thrift_socket_flush (transport, NULL); | 
|  | 168 | thrift_socket_close (transport, NULL); | 
|  | 169 | g_object_unref (tsocket); | 
|  | 170 |  | 
|  | 171 | assert ( wait (&status) == pid ); | 
|  | 172 | assert ( status == 0 ); | 
|  | 173 | } | 
|  | 174 | } | 
|  | 175 |  | 
|  | 176 | static void | 
|  | 177 | thrift_socket_server (const int port) | 
|  | 178 | { | 
|  | 179 | int bytes = 0; | 
|  | 180 | ThriftServerTransport *transport = NULL; | 
|  | 181 | ThriftTransport *client = NULL; | 
|  | 182 | guchar buf[10]; /* a buffer */ | 
|  | 183 | guchar match[10] = TEST_DATA; | 
|  | 184 |  | 
|  | 185 | ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, | 
|  | 186 | "port", port, NULL); | 
|  | 187 |  | 
|  | 188 | transport = THRIFT_SERVER_TRANSPORT (tsocket); | 
|  | 189 | thrift_server_transport_listen (transport, NULL); | 
|  | 190 | client = thrift_server_transport_accept (transport, NULL); | 
|  | 191 | assert (client != NULL); | 
|  | 192 |  | 
|  | 193 | /* read 10 bytes */ | 
|  | 194 | bytes = thrift_socket_read (client, buf, 10, NULL); | 
|  | 195 | assert (bytes == 10); /* make sure we've read 10 bytes */ | 
|  | 196 | assert ( memcmp(buf, match, 10) == 0 ); /* make sure what we got matches */ | 
|  | 197 |  | 
|  | 198 | /* failed read */ | 
|  | 199 | recv_error = 1; | 
|  | 200 | thrift_socket_read (client, buf, 1, NULL); | 
|  | 201 | recv_error = 0; | 
|  | 202 |  | 
|  | 203 | thrift_socket_read_end (client, NULL); | 
|  | 204 | thrift_socket_close (client, NULL); | 
|  | 205 | g_object_unref (tsocket); | 
|  | 206 | g_object_unref (client); | 
|  | 207 | } | 
|  | 208 |  | 
|  | 209 | int | 
| Roger Meier | c101092 | 2010-11-26 10:17:48 +0000 | [diff] [blame] | 210 | main(int argc, char *argv[]) | 
| Roger Meier | 213a664 | 2010-10-27 12:30:11 +0000 | [diff] [blame] | 211 | { | 
|  | 212 | g_type_init(); | 
| Roger Meier | c101092 | 2010-11-26 10:17:48 +0000 | [diff] [blame] | 213 | g_test_init (&argc, &argv, NULL); | 
| Roger Meier | 213a664 | 2010-10-27 12:30:11 +0000 | [diff] [blame] | 214 |  | 
| Roger Meier | c101092 | 2010-11-26 10:17:48 +0000 | [diff] [blame] | 215 | g_test_add_func ("/testtransportsocket/CreateAndDestroy", test_create_and_destroy); | 
|  | 216 | g_test_add_func ("/testtransportsocket/OpenAndClose", test_open_and_close); | 
|  | 217 | g_test_add_func ("/testtransportsocket/ReadAndWrite", test_read_and_write); | 
|  | 218 |  | 
|  | 219 | return g_test_run (); | 
| Roger Meier | 213a664 | 2010-10-27 12:30:11 +0000 | [diff] [blame] | 220 | } | 
|  | 221 |  |