Add a targeted test for OOM during _dbus_server_new_for_tcp_socket()
[platform/upstream/dbus.git] / test / internals / server-oom.c
1 /* Targeted unit tests for OOM paths in DBusServer
2  *
3  * Copyright © 2017 Collabora Ltd.
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include <config.h>
27
28 #include <string.h>
29
30 #include <glib.h>
31
32 #include <dbus/dbus.h>
33 #include "dbus/dbus-internals.h"
34 #include "dbus/dbus-pipe.h"
35 #include "dbus/dbus-server-socket.h"
36 #include "test-utils-glib.h"
37
38 /* Return TRUE if the right thing happens, but the right thing might include
39  * OOM. */
40 static dbus_bool_t
41 test_new_tcp (void *user_data)
42 {
43   DBusError error = DBUS_ERROR_INIT;
44   DBusServer *server = NULL;
45   dbus_bool_t use_nonce = FALSE;
46   const char *bind = "localhost";
47   const char *family = NULL;
48   dbus_bool_t result = FALSE;
49
50   if (user_data != NULL)
51     {
52       if (strcmp (user_data, "nonce") == 0)
53         use_nonce = TRUE;
54
55       if (strcmp (user_data, "star") == 0)
56         bind = "*";
57
58       if (strcmp (user_data, "v4") == 0)
59         family = "ipv4";
60     }
61
62   server = _dbus_server_new_for_tcp_socket ("localhost", bind,
63                                             "0", family, &error,
64                                             use_nonce);
65
66   if (server == NULL)
67     goto out;
68
69   result = TRUE;
70
71 out:
72   if (result)
73     {
74       test_assert_no_error (&error);
75     }
76   else
77     {
78       g_assert_cmpstr (error.name, ==, DBUS_ERROR_NO_MEMORY);
79       result = TRUE;
80     }
81
82   if (server != NULL)
83     dbus_server_disconnect (server);
84
85   dbus_clear_server (&server);
86   dbus_error_free (&error);
87
88   return result;
89 }
90
91 typedef struct
92 {
93   const gchar *name;
94   DBusTestMemoryFunction function;
95   const void *data;
96 } OOMTestCase;
97
98 static void
99 test_oom_wrapper (gconstpointer data)
100 {
101   const OOMTestCase *test = data;
102
103   if (!_dbus_test_oom_handling (test->name, test->function,
104                                 (void *) test->data))
105     {
106       g_test_message ("OOM test failed");
107       g_test_fail ();
108     }
109 }
110
111 static GQueue *test_cases_to_free = NULL;
112
113 static void
114 add_oom_test (const gchar *name,
115               DBusTestMemoryFunction function,
116               const void *data)
117 {
118   /* By using GLib memory allocation here, we avoid being affected by
119    * dbus_shutdown() or contributing to
120    * _dbus_get_malloc_blocks_outstanding() */
121   OOMTestCase *test_case = g_new0 (OOMTestCase, 1);
122
123   test_case->name = name;
124   test_case->function = function;
125   test_case->data = data;
126   g_test_add_data_func (name, test_case, test_oom_wrapper);
127   g_queue_push_tail (test_cases_to_free, test_case);
128 }
129
130 int
131 main (int argc,
132       char **argv)
133 {
134   int ret;
135
136   test_init (&argc, &argv);
137
138   test_cases_to_free = g_queue_new ();
139   add_oom_test ("/server/new-tcp", test_new_tcp, NULL);
140   add_oom_test ("/server/new-nonce-tcp", test_new_tcp, "nonce");
141   add_oom_test ("/server/new-tcp-star", test_new_tcp, "star");
142   add_oom_test ("/server/new-tcp-v4", test_new_tcp, "v4");
143
144   ret = g_test_run ();
145
146   g_queue_free_full (test_cases_to_free, g_free);
147   return ret;
148 }