1 /*
2 * librest - RESTful web services access
3 * Copyright (c) 2009 Intel Corporation.
4 *
5 * Authors: Rob Bradford <rob@linux.intel.com>
6 * Ross Burton <ross@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU Lesser General Public License,
10 * version 2.1, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23 /*
24 * TODO:
25 * - port to gtest
26 * - decide if status 3xx is success or failure
27 * - test query params
28 * - test request headers
29 * - test response headers
30 */
31
32 #include <config.h>
33
34 #include <string.h>
35 #include <stdlib.h>
36 #include <libsoup/soup.h>
37 #include <rest/rest-proxy.h>
38
39 #if SOUP_CHECK_VERSION (2, 28, 0)
40 /* Avoid deprecation warning with newer libsoup */
41 #define soup_message_headers_get soup_message_headers_get_one
42 #endif
43
44 static int errors = 0;
45
46 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * client,gpointer user_data)47 server_callback (SoupServer *server, SoupMessage *msg,
48 const char *path, GHashTable *query,
49 SoupClientContext *client, gpointer user_data)
50 {
51 if (g_str_equal (path, "/ping")) {
52 soup_message_set_status (msg, SOUP_STATUS_OK);
53 }
54 else if (g_str_equal (path, "/echo")) {
55 const char *value;
56
57 value = g_hash_table_lookup (query, "value");
58 soup_message_set_response (msg, "text/plain", SOUP_MEMORY_COPY,
59 value, strlen (value));
60 soup_message_set_status (msg, SOUP_STATUS_OK);
61 }
62 else if (g_str_equal (path, "/reverse")) {
63 char *value;
64
65 value = g_strdup (g_hash_table_lookup (query, "value"));
66 g_strreverse (value);
67
68 soup_message_set_response (msg, "text/plain", SOUP_MEMORY_TAKE,
69 value, strlen (value));
70 soup_message_set_status (msg, SOUP_STATUS_OK);
71 }
72 else if (g_str_equal (path, "/status")) {
73 const char *value;
74 int status;
75
76 value = g_hash_table_lookup (query, "status");
77 if (value) {
78 status = atoi (value);
79 soup_message_set_status (msg, status ?: SOUP_STATUS_INTERNAL_SERVER_ERROR);
80 } else {
81 soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR);
82 }
83 }
84 else if (g_str_equal (path, "/useragent/none")) {
85 if (soup_message_headers_get (msg->request_headers, "User-Agent") == NULL) {
86 soup_message_set_status (msg, SOUP_STATUS_OK);
87 } else {
88 soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED);
89 }
90 }
91 else if (g_str_equal (path, "/useragent/testsuite")) {
92 const char *value;
93 value = soup_message_headers_get (msg->request_headers, "User-Agent");
94 if (g_strcmp0 (value, "TestSuite-1.0") == 0) {
95 soup_message_set_status (msg, SOUP_STATUS_OK);
96 } else {
97 soup_message_set_status (msg, SOUP_STATUS_EXPECTATION_FAILED);
98 }
99 }
100 }
101
102 static void
ping_test(RestProxy * proxy)103 ping_test (RestProxy *proxy)
104 {
105 RestProxyCall *call;
106 GError *error = NULL;
107
108 call = rest_proxy_new_call (proxy);
109 rest_proxy_call_set_function (call, "ping");
110
111 if (!rest_proxy_call_run (call, NULL, &error)) {
112 g_printerr ("Call failed: %s\n", error->message);
113 g_error_free (error);
114 errors++;
115 g_object_unref (call);
116 return;
117 }
118 g_assert(error == NULL);
119
120 if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
121 g_printerr ("wrong response code\n");
122 errors++;
123 return;
124 }
125
126 if (rest_proxy_call_get_payload_length (call) != 0) {
127 g_printerr ("wrong length returned\n");
128 errors++;
129 return;
130 }
131
132 g_object_unref (call);
133 }
134
135 static void
echo_test(RestProxy * proxy)136 echo_test (RestProxy *proxy)
137 {
138 RestProxyCall *call;
139 GError *error = NULL;
140
141 call = rest_proxy_new_call (proxy);
142 rest_proxy_call_set_function (call, "echo");
143 rest_proxy_call_add_param (call, "value", "echome");
144
145 if (!rest_proxy_call_run (call, NULL, &error)) {
146 g_printerr ("Call failed: %s\n", error->message);
147 g_error_free (error);
148 errors++;
149 g_object_unref (call);
150 return;
151 }
152 g_assert(error == NULL);
153
154 if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
155 g_printerr ("wrong response code\n");
156 errors++;
157 g_object_unref (call);
158 return;
159 }
160 if (rest_proxy_call_get_payload_length (call) != 6) {
161 g_printerr ("wrong length returned\n");
162 errors++;
163 g_object_unref (call);
164 return;
165 }
166 if (g_strcmp0 ("echome", rest_proxy_call_get_payload (call)) != 0) {
167 g_printerr ("wrong string returned\n");
168 errors++;
169 g_object_unref (call);
170 return;
171 }
172 g_object_unref (call);
173 }
174
175 static void
reverse_test(RestProxy * proxy)176 reverse_test (RestProxy *proxy)
177 {
178 RestProxyCall *call;
179 GError *error = NULL;
180
181 call = rest_proxy_new_call (proxy);
182 rest_proxy_call_set_function (call, "reverse");
183 rest_proxy_call_add_param (call, "value", "reverseme");
184
185 if (!rest_proxy_call_run (call, NULL, &error)) {
186 g_printerr ("Call failed: %s\n", error->message);
187 g_error_free (error);
188 errors++;
189 g_object_unref (call);
190 return;
191 }
192 g_assert(error == NULL);
193
194 if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
195 g_printerr ("wrong response code\n");
196 errors++;
197 g_object_unref (call);
198 return;
199 }
200 if (rest_proxy_call_get_payload_length (call) != 9) {
201 g_printerr ("wrong length returned\n");
202 errors++;
203 g_object_unref (call);
204 return;
205 }
206 if (g_strcmp0 ("emesrever", rest_proxy_call_get_payload (call)) != 0) {
207 g_printerr ("wrong string returned\n");
208 errors++;
209 g_object_unref (call);
210 return;
211 }
212 g_object_unref (call);
213 }
214
215 static void
status_ok_test(RestProxy * proxy,int status)216 status_ok_test (RestProxy *proxy, int status)
217 {
218 RestProxyCall *call;
219 GError *error = NULL;
220 char *status_str;
221
222 call = rest_proxy_new_call (proxy);
223 rest_proxy_call_set_function (call, "status");
224 status_str = g_strdup_printf ("%d", status);
225 rest_proxy_call_add_param (call, "status", status_str);
226 g_free (status_str);
227
228 if (!rest_proxy_call_run (call, NULL, &error)) {
229 g_printerr ("Call failed: %s\n", error->message);
230 g_error_free (error);
231 errors++;
232 g_object_unref (call);
233 return;
234 }
235 g_assert(error == NULL);
236
237 if (rest_proxy_call_get_status_code (call) != status) {
238 g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
239 errors++;
240 return;
241 }
242
243 g_object_unref (call);
244 }
245
246 static void
status_error_test(RestProxy * proxy,int status)247 status_error_test (RestProxy *proxy, int status)
248 {
249 RestProxyCall *call;
250 GError *error = NULL;
251 char *status_str;
252
253 call = rest_proxy_new_call (proxy);
254 rest_proxy_call_set_function (call, "status");
255 status_str = g_strdup_printf ("%d", status);
256 rest_proxy_call_add_param (call, "status", status_str);
257 g_free (status_str);
258
259 if (rest_proxy_call_run (call, NULL, &error)) {
260 g_printerr ("Call succeeded should have failed");
261 errors++;
262 g_object_unref (call);
263 return;
264 }
265 g_error_free (error);
266
267 if (rest_proxy_call_get_status_code (call) != status) {
268 g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
269 errors++;
270 return;
271 }
272
273 g_object_unref (call);
274 }
275
276 static void
test_status_ok(RestProxy * proxy,const char * function)277 test_status_ok (RestProxy *proxy, const char *function)
278 {
279 RestProxyCall *call;
280 GError *error = NULL;
281
282 call = rest_proxy_new_call (proxy);
283 rest_proxy_call_set_function (call, function);
284
285 if (!rest_proxy_call_run (call, NULL, &error)) {
286 g_printerr ("%s call failed: %s\n", function, error->message);
287 g_error_free (error);
288 errors++;
289 g_object_unref (call);
290 return;
291 }
292 g_assert(error == NULL);
293
294 if (rest_proxy_call_get_status_code (call) != SOUP_STATUS_OK) {
295 g_printerr ("wrong response code, got %d\n", rest_proxy_call_get_status_code (call));
296 errors++;
297 return;
298 }
299
300 g_object_unref (call);
301 }
302
303 int
main(int argc,char ** argv)304 main (int argc, char **argv)
305 {
306 SoupServer *server;
307 char *url;
308 RestProxy *proxy;
309
310 #if !GLIB_CHECK_VERSION (2, 36, 0)
311 g_type_init ();
312 #endif
313
314 server = soup_server_new (NULL);
315 soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
316 soup_server_run_async (server);
317
318 url = g_strdup_printf ("http://127.0.0.1:%d/", soup_server_get_port (server));
319 proxy = rest_proxy_new (url, FALSE);
320 g_free (url);
321
322 ping_test (proxy);
323 echo_test (proxy);
324 reverse_test (proxy);
325 status_ok_test (proxy, SOUP_STATUS_OK);
326 status_ok_test (proxy, SOUP_STATUS_NO_CONTENT);
327 /* status_ok_test (proxy, SOUP_STATUS_MULTIPLE_CHOICES); */
328 status_error_test (proxy, SOUP_STATUS_BAD_REQUEST);
329 status_error_test (proxy, SOUP_STATUS_NOT_IMPLEMENTED);
330
331 test_status_ok (proxy, "useragent/none");
332 rest_proxy_set_user_agent (proxy, "TestSuite-1.0");
333 test_status_ok (proxy, "useragent/testsuite");
334
335 return errors != 0;
336 }
337