}
static void
-test_datagram_get_available (void)
+test_get_available (gconstpointer user_data)
{
+ GSocketType socket_type = GPOINTER_TO_UINT (user_data);
GError *err = NULL;
- GSocket *server, *client;
+ GSocket *listener, *server, *client;
GInetAddress *addr;
GSocketAddress *saddr;
gchar data[] = "0123456789abcdef";
gchar buf[34];
gssize nread;
- server = g_socket_new (G_SOCKET_FAMILY_IPV4,
- G_SOCKET_TYPE_DATAGRAM,
- G_SOCKET_PROTOCOL_DEFAULT,
- &err);
+ listener = g_socket_new (G_SOCKET_FAMILY_IPV4,
+ socket_type,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &err);
g_assert_no_error (err);
- g_assert (G_IS_SOCKET (server));
+ g_assert (G_IS_SOCKET (listener));
client = g_socket_new (G_SOCKET_FAMILY_IPV4,
- G_SOCKET_TYPE_DATAGRAM,
- G_SOCKET_PROTOCOL_DEFAULT,
- &err);
+ socket_type,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ &err);
g_assert_no_error (err);
g_assert (G_IS_SOCKET (client));
+ if (socket_type == G_SOCKET_TYPE_STREAM)
+ {
+ g_socket_set_option (client, IPPROTO_TCP, TCP_NODELAY, TRUE, &err);
+ g_assert_no_error (err);
+ }
+
addr = g_inet_address_new_any (G_SOCKET_FAMILY_IPV4);
saddr = g_inet_socket_address_new (addr, 0);
- g_socket_bind (server, saddr, TRUE, &err);
+ g_socket_bind (listener, saddr, TRUE, &err);
g_assert_no_error (err);
g_object_unref (saddr);
g_object_unref (addr);
- saddr = g_socket_get_local_address (server, &err);
+ saddr = g_socket_get_local_address (listener, &err);
g_assert_no_error (err);
+ if (socket_type == G_SOCKET_TYPE_STREAM)
+ {
+ g_socket_listen (listener, &err);
+ g_assert_no_error (err);
+ g_socket_connect (client, saddr, NULL, &err);
+ g_assert_no_error (err);
+
+ server = g_socket_accept (listener, NULL, &err);
+ g_assert_no_error (err);
+ g_socket_set_blocking (server, FALSE);
+ g_object_unref (listener);
+ }
+ else
+ server = listener;
+
g_socket_send_to (client, saddr, data, sizeof (data), NULL, &err);
g_assert_no_error (err);
g_socket_send_to (client, saddr, data, sizeof (data), NULL, &err);
g_assert_no_error (err);
- /* g_socket_condition_wait() won't help here since the socket is
- * definitely already readable. So there's a race condition here, but
- * at least the failure mode is passes-when-it-shouldn't, not
- * fails-when-it-shouldn't.
+ /* We need to wait until the data has actually been copied into the
+ * server socket's buffers, but g_socket_condition_wait() won't help
+ * here since the socket is definitely already readable. So there's
+ * a race condition in checking its available bytes. In the TCP
+ * case, we poll for a bit until the new data shows up. In the UDP
+ * case, there's not much we can do, but at least the failure mode
+ * is passes-when-it-shouldn't, not fails-when-it-shouldn't.
*/
- g_usleep (100000);
- g_assert_cmpint (g_socket_get_available_bytes (server), ==, sizeof (data));
+ if (socket_type == G_SOCKET_TYPE_STREAM)
+ {
+ int tries;
+
+ for (tries = 0; tries < 100; tries++)
+ {
+ if (g_socket_get_available_bytes (server) > sizeof (data))
+ break;
+ g_usleep (100000);
+ }
+
+ g_assert_cmpint (g_socket_get_available_bytes (server), ==, 2 * sizeof (data));
+ }
+ else
+ {
+ g_usleep (100000);
+ g_assert_cmpint (g_socket_get_available_bytes (server), ==, sizeof (data));
+ }
g_assert_cmpint (sizeof (buf), >=, 2 * sizeof (data));
nread = g_socket_receive (server, buf, sizeof (buf), NULL, &err);
- g_assert_cmpint (nread, ==, sizeof (data));
g_assert_no_error (err);
- g_assert_cmpint (g_socket_get_available_bytes (server), ==, sizeof (data));
+ if (socket_type == G_SOCKET_TYPE_STREAM)
+ {
+ g_assert_cmpint (nread, ==, 2 * sizeof (data));
+ g_assert_cmpint (g_socket_get_available_bytes (server), ==, 0);
+ }
+ else
+ {
+ g_assert_cmpint (nread, ==, sizeof (data));
+ g_assert_cmpint (g_socket_get_available_bytes (server), ==, sizeof (data));
+ }
nread = g_socket_receive (server, buf, sizeof (buf), NULL, &err);
- g_assert_cmpint (nread, ==, sizeof (data));
- g_assert_no_error (err);
+ if (socket_type == G_SOCKET_TYPE_STREAM)
+ {
+ g_assert_cmpint (nread, ==, -1);
+ g_assert_error (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_clear_error (&err);
+ }
+ else
+ {
+ g_assert_cmpint (nread, ==, sizeof (data));
+ g_assert_no_error (err);
+ }
g_assert_cmpint (g_socket_get_available_bytes (server), ==, 0);
#endif
g_test_add_func ("/socket/reuse/tcp", test_reuse_tcp);
g_test_add_func ("/socket/reuse/udp", test_reuse_udp);
- g_test_add_func ("/socket/datagram_get_available", test_datagram_get_available);
+ g_test_add_data_func ("/socket/get_available/datagram", GUINT_TO_POINTER (G_SOCKET_TYPE_DATAGRAM),
+ test_get_available);
+ g_test_add_data_func ("/socket/get_available/stream", GUINT_TO_POINTER (G_SOCKET_TYPE_STREAM),
+ test_get_available);
return g_test_run();
}