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"
37 #define BYTE_ORDER_OFFSET 0
38 #define BODY_LENGTH_OFFSET 4
41 iter_recurse (DBusMessageDataIter *iter)
44 _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING);
45 _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
49 iter_get_sequence (DBusMessageDataIter *iter)
51 _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
52 return iter->sequence_nos[iter->depth];
56 iter_set_sequence (DBusMessageDataIter *iter,
59 _dbus_assert (sequence >= 0);
60 iter->sequence_nos[iter->depth] = sequence;
64 iter_unrecurse (DBusMessageDataIter *iter)
67 _dbus_assert (iter->depth >= 0);
71 iter_next (DBusMessageDataIter *iter)
73 iter->sequence_nos[iter->depth] += 1;
77 iter_first_in_series (DBusMessageDataIter *iter)
82 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
84 if (iter->sequence_nos[i] != 0)
91 typedef dbus_bool_t (* DBusInnerGeneratorFunc) (DBusMessageDataIter *iter,
92 DBusMessage **message_p);
93 typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter,
95 DBusValidity *expected_validity);
98 set_reply_serial (DBusMessage *message)
101 _dbus_assert_not_reached ("oom");
102 if (!dbus_message_set_reply_serial (message, 100))
103 _dbus_assert_not_reached ("oom");
107 generate_trivial_inner (DBusMessageDataIter *iter,
108 DBusMessage **message_p)
110 DBusMessage *message;
112 switch (iter_get_sequence (iter))
115 message = dbus_message_new_method_call ("org.freedesktop.TextEditor",
117 "org.freedesktop.DocumentFactory",
121 message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
122 set_reply_serial (message);
125 message = dbus_message_new_signal ("/foo/bar",
126 "org.freedesktop.DocumentFactory",
130 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
132 if (!dbus_message_set_error_name (message,
133 "org.freedesktop.TestErrorName"))
134 _dbus_assert_not_reached ("oom");
137 DBusMessageIter iter;
138 const char *v_STRING = "This is an error";
140 dbus_message_iter_init_append (message, &iter);
141 if (!dbus_message_iter_append_basic (&iter,
144 _dbus_assert_not_reached ("oom");
147 set_reply_serial (message);
154 _dbus_assert_not_reached ("oom");
156 *message_p = message;
162 generate_many_bodies_inner (DBusMessageDataIter *iter,
163 DBusMessage **message_p)
165 DBusMessage *message;
166 DBusString signature;
169 message = dbus_message_new_method_call ("org.freedesktop.Foo",
171 "org.freedesktop.Blah",
174 _dbus_assert_not_reached ("oom");
176 set_reply_serial (message);
178 if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
179 _dbus_assert_not_reached ("oom");
181 if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
185 const char *v_SIGNATURE;
187 v_SIGNATURE = _dbus_string_get_const_data (&signature);
188 if (!_dbus_header_set_field_basic (&message->header,
189 DBUS_HEADER_FIELD_SIGNATURE,
192 _dbus_assert_not_reached ("oom");
194 if (!_dbus_string_move (&body, 0, &message->body, 0))
195 _dbus_assert_not_reached ("oom");
197 _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET,
198 _dbus_string_get_length (&message->body),
199 message->byte_order);
201 *message_p = message;
205 dbus_message_unref (message);
209 _dbus_string_free (&signature);
210 _dbus_string_free (&body);
212 return *message_p != NULL;
216 generate_outer (DBusMessageDataIter *iter,
218 DBusValidity *expected_validity,
219 DBusInnerGeneratorFunc func)
221 DBusMessage *message;
224 if (!(*func)(iter, &message))
229 _dbus_assert (message != NULL);
231 _dbus_message_set_serial (message, 1);
232 _dbus_message_lock (message);
234 *expected_validity = DBUS_VALID;
236 /* move for efficiency, since we'll nuke the message anyway */
237 if (!_dbus_string_move (&message->header.data, 0,
239 _dbus_assert_not_reached ("oom");
241 if (!_dbus_string_copy (&message->body, 0,
242 data, _dbus_string_get_length (data)))
243 _dbus_assert_not_reached ("oom");
245 dbus_message_unref (message);
251 generate_trivial (DBusMessageDataIter *iter,
253 DBusValidity *expected_validity)
255 return generate_outer (iter, data, expected_validity,
256 generate_trivial_inner);
260 generate_many_bodies (DBusMessageDataIter *iter,
262 DBusValidity *expected_validity)
264 return generate_outer (iter, data, expected_validity,
265 generate_many_bodies_inner);
269 generate_wrong_length (DBusMessageDataIter *iter,
271 DBusValidity *expected_validity)
273 int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
274 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
279 len_seq = iter_get_sequence (iter);
280 if (len_seq == _DBUS_N_ELEMENTS (lengths))
283 _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
286 if (!generate_many_bodies (iter, data, expected_validity))
288 iter_set_sequence (iter, 0); /* reset to first body */
289 iter_unrecurse (iter);
290 iter_next (iter); /* next length adjustment */
293 iter_unrecurse (iter);
295 adjust = lengths[len_seq];
299 if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
300 _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE);
302 _dbus_string_shorten (data, - adjust);
303 *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
307 if (!_dbus_string_lengthen (data, adjust))
308 _dbus_assert_not_reached ("oom");
309 *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
318 _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
320 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
321 old_body_len = _dbus_marshal_read_uint32 (data,
325 _dbus_assert (old_body_len < _dbus_string_get_length (data));
326 new_body_len = old_body_len + adjust;
327 if (new_body_len < 0)
330 /* we just munged the header, and aren't sure how */
331 *expected_validity = DBUS_VALIDITY_UNKNOWN;
334 _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
335 old_body_len, new_body_len, adjust);
337 _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
346 generate_byte_changed (DBusMessageDataIter *iter,
348 DBusValidity *expected_validity)
353 /* This is a little convoluted to make the bodies the
354 * outer loop and each byte of each body the inner
359 if (!generate_many_bodies (iter, data, expected_validity))
363 byte_seq = iter_get_sequence (iter);
365 iter_unrecurse (iter);
367 if (byte_seq == _dbus_string_get_length (data))
369 _dbus_string_set_length (data, 0);
370 /* reset byte count */
372 iter_set_sequence (iter, 0);
373 iter_unrecurse (iter);
378 /* Undo the "next" in generate_many_bodies */
379 iter_set_sequence (iter, iter_get_sequence (iter) - 1);
382 _dbus_assert (byte_seq < _dbus_string_get_length (data));
383 v_BYTE = _dbus_string_get_byte (data, byte_seq);
384 v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
385 _dbus_string_set_byte (data, byte_seq, v_BYTE);
386 *expected_validity = DBUS_VALIDITY_UNKNOWN;
394 dbus_uint32_t value; /* cast to signed for adjusts */
397 static const UIntChange uint32_changes[] = {
398 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 },
399 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 },
400 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 },
401 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 },
402 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 },
403 { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 },
404 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX },
405 { CHANGE_TYPE_ABSOLUTE, 0 },
406 { CHANGE_TYPE_ABSOLUTE, 1 },
407 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 },
408 { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 }
412 generate_uint32_changed (DBusMessageDataIter *iter,
414 DBusValidity *expected_validity)
419 dbus_uint32_t v_UINT32;
421 const UIntChange *change;
424 /* Outer loop is each body, next loop is each change,
425 * inner loop is each change location
428 base_depth = iter->depth;
431 _dbus_assert (iter->depth == (base_depth + 0));
432 _dbus_string_set_length (data, 0);
433 body_seq = iter_get_sequence (iter);
435 if (!generate_many_bodies (iter, data, expected_validity))
438 _dbus_assert (iter->depth == (base_depth + 0));
440 iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */
443 _dbus_assert (iter->depth == (base_depth + 1));
444 change_seq = iter_get_sequence (iter);
446 if (change_seq == _DBUS_N_ELEMENTS (uint32_changes))
448 /* Reset change count */
449 iter_set_sequence (iter, 0);
450 iter_unrecurse (iter);
455 _dbus_assert (iter->depth == (base_depth + 1));
458 _dbus_assert (iter->depth == (base_depth + 2));
459 byte_seq = iter_get_sequence (iter);
460 /* skip 4 bytes at a time */
465 iter_unrecurse (iter);
467 _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq);
468 if (byte_seq >= (_dbus_string_get_length (data) - 4))
470 /* reset byte count */
471 _dbus_assert (iter->depth == (base_depth + 1));
473 _dbus_assert (iter->depth == (base_depth + 2));
474 iter_set_sequence (iter, 0);
475 iter_unrecurse (iter);
476 _dbus_assert (iter->depth == (base_depth + 1));
481 _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4));
483 byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
485 v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL);
487 change = &uint32_changes[change_seq];
489 if (change->type == CHANGE_TYPE_ADJUST)
491 v_UINT32 += (int) change->value;
495 v_UINT32 = change->value;
499 printf ("body %d change %d pos %d ",
500 body_seq, change_seq, byte_seq);
502 if (change->type == CHANGE_TYPE_ADJUST)
503 printf ("adjust by %d", (int) change->value);
505 printf ("set to %u", change->value);
507 printf (" \t%u -> %u\n",
508 _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL),
512 _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order);
513 *expected_validity = DBUS_VALIDITY_UNKNOWN;
515 _dbus_assert (iter->depth == (base_depth + 1));
516 iter_unrecurse (iter);
517 _dbus_assert (iter->depth == (base_depth + 0));
525 DBusMessageGeneratorFunc func;
526 } DBusMessageGenerator;
528 static const DBusMessageGenerator generators[] = {
529 { "trivial example of each message type", generate_trivial },
530 { "assorted arguments", generate_many_bodies },
531 { "each uint32 modified", generate_uint32_changed },
532 { "wrong body lengths", generate_wrong_length },
533 { "each byte modified", generate_byte_changed }
537 _dbus_message_data_free (DBusMessageData *data)
539 _dbus_string_free (&data->data);
543 _dbus_message_data_iter_init (DBusMessageDataIter *iter)
549 while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
551 iter->sequence_nos[i] = 0;
558 _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
559 DBusMessageData *data)
561 DBusMessageGeneratorFunc func;
565 generator = iter_get_sequence (iter);
567 if (generator == _DBUS_N_ELEMENTS (generators))
572 if (iter_first_in_series (iter))
574 printf (" testing message loading: %s ", generators[generator].name);
578 func = generators[generator].func;
580 if (!_dbus_string_init (&data->data))
581 _dbus_assert_not_reached ("oom");
583 if ((*func)(iter, &data->data, &data->expected_validity))
587 iter_set_sequence (iter, 0);
588 iter_unrecurse (iter);
589 iter_next (iter); /* next generator */
590 _dbus_string_free (&data->data);
591 printf ("%d test loads cumulative\n", iter->count);
594 iter_unrecurse (iter);
600 #endif /* DBUS_BUILD_TESTS */