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 
20 
21 #include <string.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <unistd.h>
25 
26 #include <glib.h>
27 #include <glib/gstdio.h>
28 
29 #include <thrift/c_glib/transport/thrift_transport.h>
30 #include <thrift/c_glib/transport/thrift_fd_transport.h>
31 
32 #define MAX_MESSAGE_SIZE 2
33 
34 static const gchar TEST_DATA[12] = "abcde01234!";
35 
36 static void
test_open_and_close(void)37 test_open_and_close (void)
38 {
39   ThriftConfiguration *configuration;
40   ThriftTransport *transport;
41   ThriftTransportClass *klass;
42   GError *error;
43   gint fd;
44   gchar *filename;
45 
46   error = NULL;
47   filename = NULL;
48 
49   fd = g_file_open_tmp (NULL, &filename, &error);
50   g_assert (fd >= 0);
51 
52   configuration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
53                                 "max_frame_size", MAX_MESSAGE_SIZE, NULL);
54 
55   transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
56                                               "configuration", configuration, "fd", fd,
57                                               NULL));
58   klass = THRIFT_TRANSPORT_GET_CLASS (transport);
59 
60   /* open is no-op */
61   g_assert (klass->is_open (transport));
62   g_assert (klass->peek (transport, &error));
63   g_assert (klass->open (transport, &error));
64   g_assert (klass->is_open (transport));
65   g_assert (klass->peek (transport, &error));
66 
67   g_assert (klass->close (transport, &error));
68   g_assert (! klass->open (transport, &error));
69   g_assert (! klass->is_open (transport));
70   g_assert (! klass->peek (transport, &error));
71 
72   /* already closed */
73   g_assert (close (fd) != 0);
74   g_assert (errno == EBADF);
75 
76   g_object_unref (transport);
77   g_object_unref (configuration);
78 
79   g_remove (filename);
80   g_free (filename);
81 
82   /* test bad fd */
83   transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
84                                               "fd", -1,
85                                               NULL));
86   klass = THRIFT_TRANSPORT_GET_CLASS (transport);
87 
88   g_assert (! klass->is_open (transport));
89   error = NULL;
90   g_assert (! klass->peek (transport, &error));
91   error = NULL;
92   g_assert (! klass->open (transport, &error));
93   error = NULL;
94   g_assert (! klass->close (transport, &error));
95 
96   g_object_unref (transport);
97 }
98 
99 static void
test_read_and_write(void)100 test_read_and_write (void)
101 {
102   gchar out_buf[8];
103   gchar *b;
104   gint want, got;
105   ThriftConfiguration *configuration;
106   ThriftTransport *transport;
107   ThriftTransportClass *klass;
108   GError *error;
109   gint fd;
110   gchar *filename;
111 
112   error = NULL;
113   filename = NULL;
114 
115   fd = g_file_open_tmp (NULL, &filename, &error);
116   g_assert (fd >= 0);
117 
118   configuration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
119                                 "max_frame_size", MAX_MESSAGE_SIZE, NULL);
120   /* write */
121   transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
122                                              "configuration", configuration, "fd", fd,
123                                               NULL));
124   klass = THRIFT_TRANSPORT_GET_CLASS (transport);
125   g_assert (klass->is_open (transport));
126   g_assert (klass->write (transport, (gpointer) TEST_DATA, 11, &error));
127   g_assert (klass->flush (transport, &error));
128   g_assert (klass->close (transport, &error));
129   g_object_unref (transport);
130 
131   /* read */
132   fd = open(filename, O_RDONLY, S_IRUSR | S_IWUSR);
133   g_assert (fd >= 0);
134 
135   transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT,
136                                               "configuration", configuration,
137                                               "remainingmessagesize", MAX_MESSAGE_SIZE,
138                                               "fd", fd,
139                                               NULL));
140   klass = THRIFT_TRANSPORT_GET_CLASS (transport);
141 
142   memset(out_buf, 0, 8);
143   b = out_buf;
144   want = 2;
145   while (want > 0) {
146     got = klass->read (transport, (gpointer) b, want, &error);
147     g_assert (got > 0 && got <= want);
148     b += got;
149     want -= got;
150   }
151   g_assert (memcmp (out_buf, TEST_DATA, 2) == 0);
152 
153   memset(out_buf, 0, 8);
154   b = out_buf;
155   want = 4;
156   got = klass->read (transport, (gpointer) b, want, &error);
157   g_assert (got < 0);
158 
159   g_assert (klass->close (transport, &error));
160   g_object_unref (transport);
161   g_object_unref (configuration);
162 
163   /* clean up */
164 
165   g_remove (filename);
166   g_free (filename);
167 }
168 
169 int
main(int argc,char * argv[])170 main (int argc, char *argv[])
171 {
172 #if (!GLIB_CHECK_VERSION (2, 36, 0))
173   g_type_init ();
174 #endif
175 
176   g_test_init (&argc, &argv, NULL);
177 
178   g_test_add_func ("/testfdtransport/OpenAndClose", test_open_and_close);
179   g_test_add_func ("/testfdtransport/ReadAndWrite", test_read_and_write);
180 
181   return g_test_run ();
182 }
183