Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : SSSD tests: SBUS internals
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include <popt.h>
24 : #include <dbus/dbus.h>
25 :
26 : #include "util/util.h"
27 : #include "responder/common/responder.h"
28 : #include "tests/cmocka/common_mock.h"
29 : #include "sbus/sssd_dbus_private.h"
30 :
31 : struct sbus_get_id_ctx {
32 : struct sss_test_ctx *stc;
33 : struct sbus_connection *conn;
34 :
35 : DBusPendingCallNotifyFunction reply_handler;
36 : void *reply_pvt;
37 : int last_hash_lookup;
38 :
39 : int64_t expected;
40 : };
41 :
42 : struct sbus_get_id_ctx *global_test_ctx;
43 :
44 : DBusConnection *
45 1 : __wrap_dbus_bus_get(DBusBusType type,
46 : DBusError *error)
47 : {
48 : /* just don't return NULL */
49 1 : return (DBusConnection *) 0x42;
50 : }
51 :
52 : void
53 1 : __wrap_dbus_connection_set_exit_on_disconnect(DBusConnection *connection,
54 : dbus_bool_t exit_on_disconnect)
55 : {
56 1 : return;
57 : }
58 :
59 1 : void __wrap_dbus_pending_call_unref(DBusPendingCall *pending)
60 : {
61 1 : return;
62 : }
63 :
64 2 : void __wrap_dbus_message_unref(DBusMessage *message)
65 : {
66 2 : return;
67 : }
68 :
69 1 : void __wrap_dbus_connection_unref(DBusConnection *connection)
70 : {
71 1 : return;
72 : }
73 :
74 : DBusMessage*
75 1 : __wrap_dbus_pending_call_steal_reply(DBusPendingCall *pending)
76 : {
77 1 : return sss_mock_ptr_type(DBusMessage *);
78 : }
79 :
80 : int __real_hash_lookup(hash_table_t *table, hash_key_t *key, hash_value_t *value);
81 :
82 2 : int __wrap_hash_lookup(hash_table_t *table, hash_key_t *key, hash_value_t *value)
83 : {
84 2 : global_test_ctx->last_hash_lookup = __real_hash_lookup(table, key, value);
85 2 : return global_test_ctx->last_hash_lookup;
86 : }
87 :
88 1 : static void fake_sbus_msg_done(struct tevent_context *ev,
89 : struct tevent_immediate *imm,
90 : void *pvt)
91 : {
92 1 : struct sbus_get_id_ctx *test_ctx = talloc_get_type(pvt,
93 : struct sbus_get_id_ctx);
94 1 : talloc_free(imm);
95 1 : test_ctx->reply_handler(NULL, test_ctx->reply_pvt);
96 1 : }
97 :
98 1 : int sss_dbus_conn_send(DBusConnection *dbus_conn,
99 : DBusMessage *msg,
100 : int timeout_ms,
101 : DBusPendingCallNotifyFunction reply_handler,
102 : void *pvt,
103 : DBusPendingCall **pending)
104 : {
105 : struct tevent_immediate *imm;
106 :
107 1 : global_test_ctx->reply_pvt = pvt;
108 1 : global_test_ctx->reply_handler = reply_handler;
109 :
110 1 : imm = tevent_create_immediate(global_test_ctx->stc->ev);
111 1 : assert_non_null(imm);
112 1 : tevent_schedule_immediate(imm, global_test_ctx->stc->ev, fake_sbus_msg_done, global_test_ctx);
113 :
114 1 : return EOK;
115 : }
116 :
117 2 : int sbus_get_id_test_setup(void **state)
118 : {
119 : struct sbus_get_id_ctx *test_ctx;
120 : int ret;
121 :
122 2 : test_ctx = talloc(global_talloc_context, struct sbus_get_id_ctx);
123 2 : assert_non_null(test_ctx);
124 :
125 2 : test_ctx->conn = talloc(test_ctx, struct sbus_connection);
126 2 : assert_non_null(test_ctx->conn);
127 2 : test_ctx->conn->connection_type = SBUS_CONN_TYPE_SYSBUS;
128 2 : ret = sss_hash_create(test_ctx->conn, 32, &test_ctx->conn->clients);
129 2 : assert_int_equal(ret, EOK);
130 :
131 2 : test_ctx->stc = create_ev_test_ctx(test_ctx);
132 2 : assert_non_null(test_ctx->stc);
133 :
134 2 : *state = test_ctx;
135 2 : global_test_ctx = test_ctx;
136 2 : return 0;
137 : }
138 :
139 1 : void sbus_int_test_get_uid_done(struct tevent_req *req)
140 : {
141 : errno_t ret;
142 : int64_t uid;
143 1 : struct sbus_get_id_ctx *test_ctx = tevent_req_callback_data(req,
144 : struct sbus_get_id_ctx);
145 :
146 1 : ret = sbus_get_sender_id_recv(req, &uid);
147 1 : talloc_free(req);
148 1 : assert_int_equal(ret, EOK);
149 :
150 1 : test_ctx->stc->done = true;
151 1 : assert_int_equal(uid, test_ctx->expected);
152 1 : }
153 :
154 1 : void sbus_int_test_get_uid(void **state)
155 : {
156 : errno_t ret;
157 : struct tevent_req *req;
158 : DBusMessage *reply;
159 1 : struct sbus_get_id_ctx *test_ctx = talloc_get_type(*state,
160 : struct sbus_get_id_ctx);
161 :
162 : uint32_t uid;
163 :
164 1 : test_ctx->expected = 42;
165 1 : uid = test_ctx->expected;
166 :
167 1 : reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
168 1 : assert_non_null(reply);
169 1 : dbus_message_append_args(reply,
170 : DBUS_TYPE_UINT32, &uid,
171 : DBUS_TYPE_INVALID);
172 1 : will_return(__wrap_dbus_pending_call_steal_reply, reply);
173 :
174 1 : req = sbus_get_sender_id_send(test_ctx, test_ctx->stc->ev,
175 : test_ctx->conn, __FILE__);
176 1 : tevent_req_set_callback(req, sbus_int_test_get_uid_done, test_ctx);
177 :
178 1 : ret = test_ev_loop(test_ctx->stc);
179 1 : assert_int_equal(ret, EOK);
180 1 : assert_int_equal(test_ctx->last_hash_lookup, HASH_ERROR_KEY_NOT_FOUND);
181 :
182 : /* Now do the same lookup again, just make sure the result was cached */
183 1 : req = sbus_get_sender_id_send(test_ctx, test_ctx->stc->ev,
184 : test_ctx->conn, __FILE__);
185 1 : tevent_req_set_callback(req, sbus_int_test_get_uid_done, test_ctx);
186 :
187 1 : ret = test_ev_loop(test_ctx->stc);
188 1 : assert_int_equal(ret, EOK);
189 1 : assert_int_equal(test_ctx->last_hash_lookup, HASH_SUCCESS);
190 1 : }
191 :
192 1 : void sbus_int_test_get_uid_no_sender_done(struct tevent_req *req)
193 : {
194 : errno_t ret;
195 : int64_t uid;
196 1 : struct sbus_get_id_ctx *test_ctx = tevent_req_callback_data(req,
197 : struct sbus_get_id_ctx);
198 :
199 1 : ret = sbus_get_sender_id_recv(req, &uid);
200 1 : talloc_free(req);
201 1 : assert_int_equal(ret, ERR_SBUS_NO_SENDER);
202 1 : test_ctx->stc->done = true;
203 1 : }
204 :
205 1 : void sbus_int_test_get_uid_no_sender(void **state)
206 : {
207 : errno_t ret;
208 : struct tevent_req *req;
209 1 : struct sbus_get_id_ctx *test_ctx = talloc_get_type(*state,
210 : struct sbus_get_id_ctx);
211 :
212 1 : test_ctx->expected = -1;
213 :
214 1 : req = sbus_get_sender_id_send(test_ctx, test_ctx->stc->ev,
215 : test_ctx->conn, NULL);
216 1 : tevent_req_set_callback(req, sbus_int_test_get_uid_no_sender_done, test_ctx);
217 :
218 1 : ret = test_ev_loop(test_ctx->stc);
219 1 : assert_int_equal(ret, EOK);
220 1 : }
221 :
222 2 : int sbus_get_id_test_teardown(void **state)
223 : {
224 2 : struct sbus_get_id_ctx *test_ctx = talloc_get_type(*state,
225 : struct sbus_get_id_ctx);
226 2 : talloc_free(test_ctx);
227 2 : return 0;
228 : }
229 :
230 1 : int main(int argc, const char *argv[])
231 : {
232 : poptContext pc;
233 : int opt;
234 6 : struct poptOption long_options[] = {
235 : POPT_AUTOHELP
236 5 : SSSD_DEBUG_OPTS
237 : POPT_TABLEEND
238 : };
239 :
240 1 : const struct CMUnitTest tests[] = {
241 : cmocka_unit_test_setup_teardown(sbus_int_test_get_uid,
242 : sbus_get_id_test_setup,
243 : sbus_get_id_test_teardown),
244 : cmocka_unit_test_setup_teardown(sbus_int_test_get_uid_no_sender,
245 : sbus_get_id_test_setup,
246 : sbus_get_id_test_teardown),
247 : };
248 :
249 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
250 1 : debug_level = SSSDBG_INVALID;
251 :
252 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
253 1 : while((opt = poptGetNextOpt(pc)) != -1) {
254 : switch(opt) {
255 : default:
256 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
257 : poptBadOption(pc, 0), poptStrerror(opt));
258 0 : poptPrintUsage(pc, stderr, 0);
259 0 : return 1;
260 : }
261 : }
262 1 : poptFreeContext(pc);
263 :
264 1 : DEBUG_CLI_INIT(debug_level);
265 1 : tests_set_cwd();
266 1 : return cmocka_run_group_tests(tests, NULL, NULL);
267 : }
|