1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message-factory.c Generator of valid and invalid message data for test suite
4 * Copyright (C) 2005 Red Hat Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifdef DBUS_BUILD_TESTS
26 #include "dbus-message-factory.h"
27 #include "dbus-message-private.h"
28 #include "dbus-test.h"
31 #define BYTE_ORDER_OFFSET 0
32 #define BODY_LENGTH_OFFSET 4
35 iter_recurse (DBusMessageDataIter *iter)
38 _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING);
42 iter_get_sequence (DBusMessageDataIter *iter)
44 return iter->sequence_nos[iter->depth];
48 iter_set_sequence (DBusMessageDataIter *iter,
51 iter->sequence_nos[iter->depth] = sequence;
55 iter_unrecurse (DBusMessageDataIter *iter)
58 _dbus_assert (iter->depth >= 0);
62 iter_next (DBusMessageDataIter *iter)
64 iter->sequence_nos[iter->depth] += 1;
68 iter_first_in_series (DBusMessageDataIter *iter)
73 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
75 if (iter->sequence_nos[i] != 0)
82 typedef dbus_bool_t (* DBusInnerGeneratorFunc) (DBusMessageDataIter *iter,
83 DBusMessage **message_p);
84 typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter,
86 DBusValidity *expected_validity);
89 set_reply_serial (DBusMessage *message)
92 _dbus_assert_not_reached ("oom");
93 if (!dbus_message_set_reply_serial (message, 100))
94 _dbus_assert_not_reached ("oom");
98 generate_trivial_inner (DBusMessageDataIter *iter,
99 DBusMessage **message_p)
101 DBusMessage *message;
103 switch (iter_get_sequence (iter))
106 message = dbus_message_new_method_call ("org.freedesktop.TextEditor",
108 "org.freedesktop.DocumentFactory",
112 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
113 set_reply_serial (message);
116 message = dbus_message_new_signal ("/foo/bar",
117 "org.freedesktop.DocumentFactory",
121 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
123 if (!dbus_message_set_error_name (message,
124 "org.freedesktop.TestErrorName"))
125 _dbus_assert_not_reached ("oom");
128 DBusMessageIter iter;
129 const char *v_STRING = "This is an error";
131 dbus_message_iter_init_append (message, &iter);
132 if (!dbus_message_iter_append_basic (&iter,
135 _dbus_assert_not_reached ("oom");
138 set_reply_serial (message);
145 _dbus_assert_not_reached ("oom");
147 *message_p = message;
153 generate_many_bodies_inner (DBusMessageDataIter *iter,
154 DBusMessage **message_p)
156 DBusMessage *message;
157 DBusString signature;
160 message = dbus_message_new_method_call ("org.freedesktop.Foo",
162 "org.freedesktop.Blah",
165 _dbus_assert_not_reached ("oom");
167 set_reply_serial (message);
169 if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
170 _dbus_assert_not_reached ("oom");
172 if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
176 const char *v_SIGNATURE;
178 v_SIGNATURE = _dbus_string_get_const_data (&signature);
179 if (!_dbus_header_set_field_basic (&message->header,
180 DBUS_HEADER_FIELD_SIGNATURE,
183 _dbus_assert_not_reached ("oom");
185 if (!_dbus_string_move (&body, 0, &message->body, 0))
186 _dbus_assert_not_reached ("oom");
188 _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET,
189 _dbus_string_get_length (&message->body),
190 message->byte_order);
192 *message_p = message;
196 dbus_message_unref (message);
200 _dbus_string_free (&signature);
201 _dbus_string_free (&body);
203 return *message_p != NULL;
207 generate_outer (DBusMessageDataIter *iter,
209 DBusValidity *expected_validity,
210 DBusInnerGeneratorFunc func)
212 DBusMessage *message;
215 if (!(*func)(iter, &message))
220 _dbus_assert (message != NULL);
222 _dbus_message_set_serial (message, 1);
223 _dbus_message_lock (message);
225 *expected_validity = DBUS_VALID;
227 /* move for efficiency, since we'll nuke the message anyway */
228 if (!_dbus_string_move (&message->header.data, 0,
230 _dbus_assert_not_reached ("oom");
232 if (!_dbus_string_copy (&message->body, 0,
233 data, _dbus_string_get_length (data)))
234 _dbus_assert_not_reached ("oom");
236 dbus_message_unref (message);
242 generate_trivial (DBusMessageDataIter *iter,
244 DBusValidity *expected_validity)
246 return generate_outer (iter, data, expected_validity,
247 generate_trivial_inner);
251 generate_many_bodies (DBusMessageDataIter *iter,
253 DBusValidity *expected_validity)
255 return generate_outer (iter, data, expected_validity,
256 generate_many_bodies_inner);
260 generate_wrong_length (DBusMessageDataIter *iter,
262 DBusValidity *expected_validity)
264 int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
265 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
270 len_seq = iter_get_sequence (iter);
271 if (len_seq == _DBUS_N_ELEMENTS (lengths))
274 _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
277 if (!generate_many_bodies (iter, data, expected_validity))
279 iter_set_sequence (iter, 0); /* reset to first body */
280 iter_unrecurse (iter);
281 iter_next (iter); /* next length adjustment */
284 iter_unrecurse (iter);
286 adjust = lengths[len_seq];
290 if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
291 _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE);
293 _dbus_string_shorten (data, - adjust);
294 *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
298 if (!_dbus_string_lengthen (data, adjust))
299 _dbus_assert_not_reached ("oom");
300 *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
309 _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
311 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
312 old_body_len = _dbus_marshal_read_uint32 (data,
316 _dbus_assert (old_body_len < _dbus_string_get_length (data));
317 new_body_len = old_body_len + adjust;
318 if (new_body_len < 0)
321 /* we just munged the header, and aren't sure how */
322 *expected_validity = DBUS_VALIDITY_UNKNOWN;
325 _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
326 old_body_len, new_body_len, adjust);
328 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
337 generate_byte_changed (DBusMessageDataIter *iter,
339 DBusValidity *expected_validity)
344 /* This is a little convoluted to make the bodies the
345 * outer loop and each byte of each body the inner
350 if (!generate_many_bodies (iter, data, expected_validity))
354 byte_seq = iter_get_sequence (iter);
356 iter_unrecurse (iter);
358 if (byte_seq == _dbus_string_get_length (data))
360 _dbus_string_set_length (data, 0);
361 /* reset byte count */
363 iter_set_sequence (iter, 0);
364 iter_unrecurse (iter);
369 /* Undo the "next" in generate_many_bodies */
370 iter_set_sequence (iter, iter_get_sequence (iter) - 1);
373 _dbus_assert (byte_seq < _dbus_string_get_length (data));
374 v_BYTE = _dbus_string_get_byte (data, byte_seq);
375 v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
376 _dbus_string_set_byte (data, byte_seq, v_BYTE);
377 *expected_validity = DBUS_VALIDITY_UNKNOWN;
385 DBusMessageGeneratorFunc func;
386 } DBusMessageGenerator;
388 static const DBusMessageGenerator generators[] = {
389 { "trivial example of each message type", generate_trivial },
390 { "assorted arguments", generate_many_bodies },
391 { "wrong body lengths", generate_wrong_length },
392 { "each byte modified", generate_byte_changed }
396 _dbus_message_data_free (DBusMessageData *data)
398 _dbus_string_free (&data->data);
402 _dbus_message_data_iter_init (DBusMessageDataIter *iter)
408 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
410 iter->sequence_nos[i] = 0;
416 _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
417 DBusMessageData *data)
419 DBusMessageGeneratorFunc func;
423 generator = iter_get_sequence (iter);
425 if (generator == _DBUS_N_ELEMENTS (generators))
430 if (iter_first_in_series (iter))
431 printf (" testing message loading: %s\n", generators[generator].name);
433 func = generators[generator].func;
435 if (!_dbus_string_init (&data->data))
436 _dbus_assert_not_reached ("oom");
438 if ((*func)(iter, &data->data, &data->expected_validity))
442 iter_set_sequence (iter, 0);
443 iter_unrecurse (iter);
444 iter_next (iter); /* next generator */
445 _dbus_string_free (&data->data);
448 iter_unrecurse (iter);
453 #endif /* DBUS_BUILD_TESTS */