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