D-Bus 1.6.12

dbus-message-factory.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-message-factory.c Generator of valid and invalid message data for test suite
00003  *
00004  * Copyright (C) 2005 Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 #include <config.h>
00024 
00025 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00026 
00027 #ifdef DBUS_BUILD_TESTS
00028 #include "dbus-message-factory.h"
00029 #include "dbus-message-private.h"
00030 #include "dbus-signature.h"
00031 #include "dbus-test.h"
00032 #include <stdio.h>
00033 
00034 typedef enum
00035   {
00036     CHANGE_TYPE_ADJUST,
00037     CHANGE_TYPE_ABSOLUTE
00038   } ChangeType;
00039 
00040 #define BYTE_ORDER_OFFSET  0
00041 #define TYPE_OFFSET        1
00042 #define BODY_LENGTH_OFFSET 4
00043 #define FIELDS_ARRAY_LENGTH_OFFSET 12
00044 
00045 static void
00046 iter_recurse (DBusMessageDataIter *iter)
00047 {
00048   iter->depth += 1;
00049   _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING);
00050   _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
00051 }
00052 
00053 static int
00054 iter_get_sequence (DBusMessageDataIter *iter)
00055 {
00056   _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
00057   return iter->sequence_nos[iter->depth];
00058 }
00059 
00060 static void
00061 iter_set_sequence (DBusMessageDataIter *iter,
00062                    int                  sequence)
00063 {
00064   _dbus_assert (sequence >= 0);
00065   iter->sequence_nos[iter->depth] = sequence;
00066 }
00067 
00068 static void
00069 iter_unrecurse (DBusMessageDataIter *iter)
00070 {
00071   iter->depth -= 1;
00072   _dbus_assert (iter->depth >= 0);
00073 }
00074 
00075 static void
00076 iter_next (DBusMessageDataIter *iter)
00077 {
00078   iter->sequence_nos[iter->depth] += 1;
00079 }
00080 
00081 static dbus_bool_t
00082 iter_first_in_series (DBusMessageDataIter *iter)
00083 {
00084   int i;
00085 
00086   i = iter->depth;
00087   while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
00088     {
00089       if (iter->sequence_nos[i] != 0)
00090         return FALSE;
00091       ++i;
00092     }
00093   return TRUE;
00094 }
00095 
00096 typedef dbus_bool_t (* DBusInnerGeneratorFunc)   (DBusMessageDataIter *iter,
00097                                                   DBusMessage        **message_p);
00098 typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter,
00099                                                   DBusString          *data,
00100                                                   DBusValidity        *expected_validity);
00101 
00102 static void
00103 set_reply_serial (DBusMessage *message)
00104 {
00105   if (message == NULL)
00106     _dbus_assert_not_reached ("oom");
00107   if (!dbus_message_set_reply_serial (message, 100))
00108     _dbus_assert_not_reached ("oom");
00109 }
00110 
00111 static dbus_bool_t
00112 generate_trivial_inner (DBusMessageDataIter *iter,
00113                         DBusMessage        **message_p)
00114 {
00115   DBusMessage *message;
00116 
00117   switch (iter_get_sequence (iter))
00118     {
00119     case 0:
00120       message = dbus_message_new_method_call ("org.freedesktop.TextEditor",
00121                                               "/foo/bar",
00122                                               "org.freedesktop.DocumentFactory",
00123                                               "Create");
00124       break;
00125     case 1:
00126       message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
00127       set_reply_serial (message);
00128       break;
00129     case 2:
00130       message = dbus_message_new_signal ("/foo/bar",
00131                                          "org.freedesktop.DocumentFactory",
00132                                          "Created");
00133       break;
00134     case 3:
00135       message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
00136 
00137       if (!dbus_message_set_error_name (message,
00138                                         "org.freedesktop.TestErrorName"))
00139         _dbus_assert_not_reached ("oom");
00140       
00141       {
00142         DBusMessageIter iter;
00143         const char *v_STRING = "This is an error";
00144         
00145         dbus_message_iter_init_append (message, &iter);
00146         if (!dbus_message_iter_append_basic (&iter,
00147                                              DBUS_TYPE_STRING,
00148                                              &v_STRING))
00149           _dbus_assert_not_reached ("oom");
00150       }
00151       
00152       set_reply_serial (message);
00153       break;
00154     default:
00155       return FALSE;
00156     }
00157   
00158   if (message == NULL)
00159     _dbus_assert_not_reached ("oom");
00160 
00161   *message_p = message;
00162   
00163   return TRUE;
00164 }
00165 
00166 static dbus_bool_t
00167 generate_many_bodies_inner (DBusMessageDataIter *iter,
00168                             DBusMessage        **message_p)
00169 {
00170   DBusMessage *message;
00171   DBusString signature;
00172   DBusString body;
00173   char byte_order;
00174 
00175   /* Keeping this small makes things go faster */
00176   message = dbus_message_new_method_call ("o.z.F",
00177                                           "/",
00178                                           "o.z.B",
00179                                           "Nah");
00180   if (message == NULL)
00181     _dbus_assert_not_reached ("oom");
00182 
00183   byte_order = _dbus_header_get_byte_order (&message->header);
00184 
00185   set_reply_serial (message);
00186 
00187   if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
00188     _dbus_assert_not_reached ("oom");
00189   
00190   if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
00191                                                 byte_order,
00192                                                 &signature, &body))
00193     {
00194       const char *v_SIGNATURE;
00195 
00196       v_SIGNATURE = _dbus_string_get_const_data (&signature);
00197       if (!_dbus_header_set_field_basic (&message->header,
00198                                          DBUS_HEADER_FIELD_SIGNATURE,
00199                                          DBUS_TYPE_SIGNATURE,
00200                                          &v_SIGNATURE))
00201         _dbus_assert_not_reached ("oom");
00202 
00203       if (!_dbus_string_move (&body, 0, &message->body, 0))
00204         _dbus_assert_not_reached ("oom");
00205 
00206       _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET,
00207                                 _dbus_string_get_length (&message->body),
00208                                 byte_order);
00209       
00210       *message_p = message;
00211     }
00212   else
00213     {
00214       dbus_message_unref (message);
00215       *message_p = NULL;
00216     }
00217   
00218   _dbus_string_free (&signature);
00219   _dbus_string_free (&body);
00220 
00221   return *message_p != NULL;
00222 }
00223 
00224 static void
00225 generate_from_message (DBusString            *data,
00226                        DBusValidity          *expected_validity,
00227                        DBusMessage           *message)
00228 {
00229   dbus_message_set_serial (message, 1);
00230   dbus_message_lock (message);
00231 
00232   *expected_validity = DBUS_VALID;
00233   
00234   /* move for efficiency, since we'll nuke the message anyway */
00235   if (!_dbus_string_move (&message->header.data, 0,
00236                           data, 0))
00237     _dbus_assert_not_reached ("oom");
00238 
00239   if (!_dbus_string_copy (&message->body, 0,
00240                           data, _dbus_string_get_length (data)))
00241     _dbus_assert_not_reached ("oom");
00242 }
00243 
00244 static dbus_bool_t
00245 generate_outer (DBusMessageDataIter   *iter,
00246                 DBusString            *data,
00247                 DBusValidity          *expected_validity,
00248                 DBusInnerGeneratorFunc func)
00249 {
00250   DBusMessage *message;
00251 
00252   message = NULL;
00253   if (!(*func)(iter, &message))
00254     return FALSE;
00255 
00256   iter_next (iter);
00257   
00258   _dbus_assert (message != NULL);
00259 
00260   generate_from_message (data, expected_validity, message);
00261 
00262   dbus_message_unref (message);
00263 
00264   return TRUE;
00265 }
00266 
00267 static dbus_bool_t
00268 generate_trivial (DBusMessageDataIter   *iter,
00269                   DBusString            *data,
00270                   DBusValidity          *expected_validity)
00271 {
00272   return generate_outer (iter, data, expected_validity,
00273                          generate_trivial_inner);
00274 }
00275 
00276 static dbus_bool_t
00277 generate_many_bodies (DBusMessageDataIter   *iter,
00278                       DBusString            *data,
00279                       DBusValidity          *expected_validity)
00280 {
00281   return generate_outer (iter, data, expected_validity,
00282                          generate_many_bodies_inner);
00283 }
00284 
00285 static DBusMessage*
00286 simple_method_call (void)
00287 {
00288   DBusMessage *message;
00289   /* Keeping this small makes stuff go faster */
00290   message = dbus_message_new_method_call ("o.b.Q",
00291                                           "/f/b",
00292                                           "o.b.Z",
00293                                           "Fro");
00294   if (message == NULL)
00295     _dbus_assert_not_reached ("oom");
00296   return message;
00297 }
00298 
00299 static DBusMessage*
00300 simple_signal (void)
00301 {
00302   DBusMessage *message;
00303   message = dbus_message_new_signal ("/f/b",
00304                                      "o.b.Z",
00305                                      "Fro");
00306   if (message == NULL)
00307     _dbus_assert_not_reached ("oom");
00308   return message;
00309 }
00310 
00311 static DBusMessage*
00312 simple_method_return (void)
00313 {
00314   DBusMessage *message;
00315   message =  dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
00316   if (message == NULL)
00317     _dbus_assert_not_reached ("oom");
00318 
00319   set_reply_serial (message);
00320   
00321   return message;
00322 }
00323 
00324 static DBusMessage*
00325 simple_error (void)
00326 {
00327   DBusMessage *message;
00328   message =  dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
00329   if (message == NULL)
00330     _dbus_assert_not_reached ("oom");
00331 
00332   if (!dbus_message_set_error_name (message, "foo.bar"))
00333     _dbus_assert_not_reached ("oom");
00334   
00335   set_reply_serial (message);
00336   
00337   return message;
00338 }
00339 
00340 static DBusMessage*
00341 message_with_nesting_levels (int levels)
00342 {
00343   DBusMessage *message;
00344   dbus_int32_t v_INT32;
00345   DBusMessageIter *parents;
00346   DBusMessageIter *children;
00347   int i;
00348 
00349   /* If levels is higher it breaks sig_refcount in DBusMessageRealIter
00350    * in dbus-message.c, this assert is just to help you know you need
00351    * to fix that if you hit it
00352    */
00353   _dbus_assert (levels < 256);
00354 
00355   parents = dbus_new(DBusMessageIter, levels + 1);
00356   children = dbus_new(DBusMessageIter, levels + 1);
00357 
00358   v_INT32 = 42;
00359   message = simple_method_call ();
00360 
00361   i = 0;
00362   dbus_message_iter_init_append (message, &parents[i]);
00363   while (i < levels)
00364     {
00365       dbus_message_iter_open_container (&parents[i], DBUS_TYPE_VARIANT,
00366                                         i == (levels - 1) ?
00367                                         DBUS_TYPE_INT32_AS_STRING :
00368                                         DBUS_TYPE_VARIANT_AS_STRING,
00369                                         &children[i]);
00370       ++i;
00371       parents[i] = children[i-1];
00372     }
00373   --i;
00374   dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32);
00375   while (i >= 0)
00376     {
00377       dbus_message_iter_close_container (&parents[i], &children[i]);
00378       --i;
00379     }
00380 
00381   dbus_free(parents);
00382   dbus_free(children);
00383 
00384   return message;
00385 }
00386 
00387 static dbus_bool_t
00388 generate_special (DBusMessageDataIter   *iter,
00389                   DBusString            *data,
00390                   DBusValidity          *expected_validity)
00391 {
00392   int item_seq;
00393   DBusMessage *message;
00394   int pos;
00395   dbus_int32_t v_INT32;
00396 
00397   _dbus_assert (_dbus_string_get_length (data) == 0);
00398   
00399   message = NULL;
00400   pos = -1;
00401   v_INT32 = 42;
00402   item_seq = iter_get_sequence (iter);
00403 
00404   if (item_seq == 0)
00405     {
00406       message = simple_method_call ();
00407       if (!dbus_message_append_args (message,
00408                                      DBUS_TYPE_INT32, &v_INT32,
00409                                      DBUS_TYPE_INT32, &v_INT32,
00410                                      DBUS_TYPE_INT32, &v_INT32,
00411                                      DBUS_TYPE_INVALID))
00412         _dbus_assert_not_reached ("oom");
00413                                      
00414       _dbus_header_get_field_raw (&message->header,
00415                                   DBUS_HEADER_FIELD_SIGNATURE,
00416                                   NULL, &pos);
00417       generate_from_message (data, expected_validity, message);
00418       
00419       /* set an invalid typecode */
00420       _dbus_string_set_byte (data, pos + 1, '$');
00421 
00422       *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE;
00423     }
00424   else if (item_seq == 1)
00425     {
00426       char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2];
00427       const char *v_STRING;
00428       int i;
00429       
00430       message = simple_method_call ();
00431       if (!dbus_message_append_args (message,
00432                                      DBUS_TYPE_INT32, &v_INT32,
00433                                      DBUS_TYPE_INT32, &v_INT32,
00434                                      DBUS_TYPE_INT32, &v_INT32,
00435                                      DBUS_TYPE_INVALID))
00436         _dbus_assert_not_reached ("oom");
00437 
00438       i = 0;
00439       while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
00440         {
00441           long_sig[i] = DBUS_TYPE_ARRAY;
00442           ++i;
00443         }
00444       long_sig[i] = DBUS_TYPE_INVALID;
00445 
00446       v_STRING = long_sig;
00447       if (!_dbus_header_set_field_basic (&message->header,
00448                                          DBUS_HEADER_FIELD_SIGNATURE,
00449                                          DBUS_TYPE_SIGNATURE,
00450                                          &v_STRING))
00451         _dbus_assert_not_reached ("oom");
00452       
00453       _dbus_header_get_field_raw (&message->header,
00454                                   DBUS_HEADER_FIELD_SIGNATURE,
00455                                   NULL, &pos);
00456       generate_from_message (data, expected_validity, message);
00457       
00458       *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
00459     }
00460   else if (item_seq == 2)
00461     {
00462       char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4];
00463       const char *v_STRING;
00464       int i;
00465       
00466       message = simple_method_call ();
00467       if (!dbus_message_append_args (message,
00468                                      DBUS_TYPE_INT32, &v_INT32,
00469                                      DBUS_TYPE_INT32, &v_INT32,
00470                                      DBUS_TYPE_INT32, &v_INT32,
00471                                      DBUS_TYPE_INVALID))
00472         _dbus_assert_not_reached ("oom");
00473 
00474       i = 0;
00475       while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
00476         {
00477           long_sig[i] = DBUS_STRUCT_BEGIN_CHAR;
00478           ++i;
00479         }
00480 
00481       long_sig[i] = DBUS_TYPE_INT32;
00482       ++i;
00483 
00484       while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3))
00485         {
00486           long_sig[i] = DBUS_STRUCT_END_CHAR;
00487           ++i;
00488         }
00489       long_sig[i] = DBUS_TYPE_INVALID;
00490       
00491       v_STRING = long_sig;
00492       if (!_dbus_header_set_field_basic (&message->header,
00493                                          DBUS_HEADER_FIELD_SIGNATURE,
00494                                          DBUS_TYPE_SIGNATURE,
00495                                          &v_STRING))
00496         _dbus_assert_not_reached ("oom");
00497       
00498       _dbus_header_get_field_raw (&message->header,
00499                                   DBUS_HEADER_FIELD_SIGNATURE,
00500                                   NULL, &pos);
00501       generate_from_message (data, expected_validity, message);
00502       
00503       *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
00504     }
00505   else if (item_seq == 3)
00506     {
00507       message = simple_method_call ();
00508       if (!dbus_message_append_args (message,
00509                                      DBUS_TYPE_INT32, &v_INT32,
00510                                      DBUS_TYPE_INT32, &v_INT32,
00511                                      DBUS_TYPE_INT32, &v_INT32,
00512                                      DBUS_TYPE_INVALID))
00513         _dbus_assert_not_reached ("oom");
00514                                      
00515       _dbus_header_get_field_raw (&message->header,
00516                                   DBUS_HEADER_FIELD_SIGNATURE,
00517                                   NULL, &pos);
00518       generate_from_message (data, expected_validity, message);
00519       
00520       _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
00521       
00522       *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
00523     }
00524   else if (item_seq == 4)
00525     {
00526       message = simple_method_call ();
00527       if (!dbus_message_append_args (message,
00528                                      DBUS_TYPE_INT32, &v_INT32,
00529                                      DBUS_TYPE_INT32, &v_INT32,
00530                                      DBUS_TYPE_INT32, &v_INT32,
00531                                      DBUS_TYPE_INVALID))
00532         _dbus_assert_not_reached ("oom");
00533                                      
00534       _dbus_header_get_field_raw (&message->header,
00535                                   DBUS_HEADER_FIELD_SIGNATURE,
00536                                   NULL, &pos);
00537       generate_from_message (data, expected_validity, message);
00538       
00539       _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR);
00540       
00541       *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
00542     }
00543   else if (item_seq == 5)
00544     {
00545       message = simple_method_call ();
00546       if (!dbus_message_append_args (message,
00547                                      DBUS_TYPE_INT32, &v_INT32,
00548                                      DBUS_TYPE_INT32, &v_INT32,
00549                                      DBUS_TYPE_INT32, &v_INT32,
00550                                      DBUS_TYPE_INVALID))
00551         _dbus_assert_not_reached ("oom");
00552                                      
00553       _dbus_header_get_field_raw (&message->header,
00554                                   DBUS_HEADER_FIELD_SIGNATURE,
00555                                   NULL, &pos);
00556       generate_from_message (data, expected_validity, message);
00557       
00558       _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
00559       _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR);
00560       
00561       *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
00562     }
00563   else if (item_seq == 6)
00564     {
00565       message = simple_method_call ();
00566       generate_from_message (data, expected_validity, message);
00567       
00568       _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID);
00569       
00570       *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
00571     }
00572   else if (item_seq == 7)
00573     {
00574       /* Messages of unknown type are considered valid */
00575       message = simple_method_call ();
00576       generate_from_message (data, expected_validity, message);
00577       
00578       _dbus_string_set_byte (data, TYPE_OFFSET, 100);
00579       
00580       *expected_validity = DBUS_VALID;
00581     }
00582   else if (item_seq == 8)
00583     {
00584       char byte_order;
00585 
00586       message = simple_method_call ();
00587       byte_order = _dbus_header_get_byte_order (&message->header);
00588       generate_from_message (data, expected_validity, message);
00589       
00590       _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
00591                                 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
00592                                 byte_order);
00593       _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET,
00594                                 DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
00595                                 byte_order);
00596       *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG;
00597     }
00598   else if (item_seq == 9)
00599     {
00600       const char *v_STRING = "not a valid bus name";
00601       message = simple_method_call ();
00602 
00603       if (!_dbus_header_set_field_basic (&message->header,
00604                                          DBUS_HEADER_FIELD_SENDER,
00605                                          DBUS_TYPE_STRING, &v_STRING))
00606         _dbus_assert_not_reached ("oom");
00607       
00608       generate_from_message (data, expected_validity, message);
00609 
00610       *expected_validity = DBUS_INVALID_BAD_SENDER;
00611     }
00612   else if (item_seq == 10)
00613     {
00614       message = simple_method_call ();
00615 
00616       if (!dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL))
00617         _dbus_assert_not_reached ("oom");
00618       
00619       generate_from_message (data, expected_validity, message);
00620 
00621       *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE;
00622     }
00623   else if (item_seq == 11)
00624     {
00625       message = simple_method_call ();
00626 
00627       if (!dbus_message_set_path (message, DBUS_PATH_LOCAL))
00628         _dbus_assert_not_reached ("oom");
00629       
00630       generate_from_message (data, expected_validity, message);
00631 
00632       *expected_validity = DBUS_INVALID_USES_LOCAL_PATH;
00633     }
00634   else if (item_seq == 12)
00635     {
00636       /* Method calls don't have to have interface */
00637       message = simple_method_call ();
00638 
00639       if (!dbus_message_set_interface (message, NULL))
00640         _dbus_assert_not_reached ("oom");
00641       
00642       generate_from_message (data, expected_validity, message);
00643       
00644       *expected_validity = DBUS_VALID;
00645     }
00646   else if (item_seq == 13)
00647     {
00648       /* Signals require an interface */
00649       message = simple_signal ();
00650 
00651       if (!dbus_message_set_interface (message, NULL))
00652         _dbus_assert_not_reached ("oom");
00653       
00654       generate_from_message (data, expected_validity, message);
00655       
00656       *expected_validity = DBUS_INVALID_MISSING_INTERFACE;
00657     }
00658   else if (item_seq == 14)
00659     {
00660       message = simple_method_return ();
00661 
00662       if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL))
00663         _dbus_assert_not_reached ("oom");
00664       
00665       generate_from_message (data, expected_validity, message);
00666       
00667       *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL;
00668     }
00669   else if (item_seq == 15)
00670     {
00671       message = simple_error ();
00672 
00673       if (!dbus_message_set_error_name (message, NULL))
00674         _dbus_assert_not_reached ("oom");
00675       
00676       generate_from_message (data, expected_validity, message);
00677       
00678       *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME;
00679     }
00680   else if (item_seq == 16)
00681     {
00682       char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10];
00683       const char *v_STRING;
00684       int i;
00685       int n_begins;
00686       
00687       message = simple_method_call ();
00688       if (!dbus_message_append_args (message,
00689                                      DBUS_TYPE_INT32, &v_INT32,
00690                                      DBUS_TYPE_INT32, &v_INT32,
00691                                      DBUS_TYPE_INT32, &v_INT32,
00692                                      DBUS_TYPE_INVALID))
00693         _dbus_assert_not_reached ("oom");
00694 
00695       i = 0;
00696       while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3))
00697         {
00698           long_sig[i] = DBUS_TYPE_ARRAY;
00699           ++i;
00700           long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR;
00701           ++i;
00702           long_sig[i] = DBUS_TYPE_INT32;
00703           ++i;
00704         }
00705       n_begins = i / 3;
00706 
00707       long_sig[i] = DBUS_TYPE_INT32;
00708       ++i;
00709       
00710       while (n_begins > 0)
00711         {
00712           long_sig[i] = DBUS_DICT_ENTRY_END_CHAR;
00713           ++i;
00714           n_begins -= 1;
00715         }
00716       long_sig[i] = DBUS_TYPE_INVALID;
00717       
00718       v_STRING = long_sig;
00719       if (!_dbus_header_set_field_basic (&message->header,
00720                                          DBUS_HEADER_FIELD_SIGNATURE,
00721                                          DBUS_TYPE_SIGNATURE,
00722                                          &v_STRING))
00723         _dbus_assert_not_reached ("oom");
00724       
00725       _dbus_header_get_field_raw (&message->header,
00726                                   DBUS_HEADER_FIELD_SIGNATURE,
00727                                   NULL, &pos);
00728       generate_from_message (data, expected_validity, message);
00729       
00730       *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
00731     }
00732   else if (item_seq == 17)
00733     {
00734       message = simple_method_call ();
00735       if (!dbus_message_append_args (message,
00736                                      DBUS_TYPE_INT32, &v_INT32,
00737                                      DBUS_TYPE_INT32, &v_INT32,
00738                                      DBUS_TYPE_INT32, &v_INT32,
00739                                      DBUS_TYPE_INVALID))
00740         _dbus_assert_not_reached ("oom");
00741                                      
00742       _dbus_header_get_field_raw (&message->header,
00743                                   DBUS_HEADER_FIELD_SIGNATURE,
00744                                   NULL, &pos);
00745       generate_from_message (data, expected_validity, message);
00746 
00747       _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
00748       _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
00749       
00750       *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
00751     }
00752   else if (item_seq == 18)
00753     {
00754       message = simple_method_call ();
00755       if (!dbus_message_append_args (message,
00756                                      DBUS_TYPE_INT32, &v_INT32,
00757                                      DBUS_TYPE_INT32, &v_INT32,
00758                                      DBUS_TYPE_INT32, &v_INT32,
00759                                      DBUS_TYPE_INVALID))
00760         _dbus_assert_not_reached ("oom");
00761                                      
00762       _dbus_header_get_field_raw (&message->header,
00763                                   DBUS_HEADER_FIELD_SIGNATURE,
00764                                   NULL, &pos);
00765       generate_from_message (data, expected_validity, message);
00766       
00767       _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR);
00768       
00769       *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
00770     }
00771   else if (item_seq == 19)
00772     {
00773       message = simple_method_call ();
00774       if (!dbus_message_append_args (message,
00775                                      DBUS_TYPE_INT32, &v_INT32,
00776                                      DBUS_TYPE_INT32, &v_INT32,
00777                                      DBUS_TYPE_INT32, &v_INT32,
00778                                      DBUS_TYPE_INVALID))
00779         _dbus_assert_not_reached ("oom");
00780                                      
00781       _dbus_header_get_field_raw (&message->header,
00782                                   DBUS_HEADER_FIELD_SIGNATURE,
00783                                   NULL, &pos);
00784       generate_from_message (data, expected_validity, message);
00785 
00786       _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
00787       _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
00788       _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR);
00789       
00790       *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
00791     }
00792   else if (item_seq == 20)
00793     {
00794       /* 64 levels of nesting is OK */
00795       message = message_with_nesting_levels(64);
00796 
00797       generate_from_message (data, expected_validity, message);
00798 
00799       *expected_validity = DBUS_VALID;
00800     }
00801   else if (item_seq == 21)
00802     {
00803       /* 65 levels of nesting is not OK */
00804       message = message_with_nesting_levels(65);
00805 
00806       generate_from_message (data, expected_validity, message);
00807 
00808       *expected_validity = DBUS_INVALID_NESTED_TOO_DEEPLY;
00809     }
00810   else
00811     {
00812       return FALSE;
00813     }
00814 
00815   if (message)
00816     dbus_message_unref (message);
00817 
00818   iter_next (iter);
00819   return TRUE;
00820 }
00821 
00822 static dbus_bool_t
00823 generate_wrong_length (DBusMessageDataIter *iter,
00824                        DBusString          *data,
00825                        DBusValidity        *expected_validity)
00826 {
00827   int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
00828                     1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
00829   int adjust;
00830   int len_seq;
00831 
00832  restart:
00833   len_seq = iter_get_sequence (iter);
00834   if (len_seq == _DBUS_N_ELEMENTS (lengths))
00835     return FALSE;
00836 
00837   _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
00838   
00839   iter_recurse (iter);
00840   if (!generate_many_bodies (iter, data, expected_validity))
00841     {
00842       iter_set_sequence (iter, 0); /* reset to first body */
00843       iter_unrecurse (iter);
00844       iter_next (iter);            /* next length adjustment */
00845       goto restart;
00846     }
00847   iter_unrecurse (iter);
00848 
00849   adjust = lengths[len_seq];
00850 
00851   if (adjust < 0)
00852     {
00853       if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
00854         _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE);
00855       else
00856         _dbus_string_shorten (data, - adjust);
00857       *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
00858     }
00859   else
00860     {      
00861       if (!_dbus_string_lengthen (data, adjust))
00862         _dbus_assert_not_reached ("oom");
00863       *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
00864     }
00865 
00866   /* Fixup lengths */
00867   {
00868     int old_body_len;
00869     int new_body_len;
00870     int byte_order;
00871     
00872     _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
00873     
00874     byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
00875     old_body_len = _dbus_marshal_read_uint32 (data,
00876                                               BODY_LENGTH_OFFSET,
00877                                               byte_order,
00878                                               NULL);
00879     _dbus_assert (old_body_len < _dbus_string_get_length (data));
00880     new_body_len = old_body_len + adjust;
00881     if (new_body_len < 0)
00882       {
00883         new_body_len = 0;
00884         /* we just munged the header, and aren't sure how */
00885         *expected_validity = DBUS_VALIDITY_UNKNOWN;
00886       }
00887 
00888     _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
00889                    old_body_len, new_body_len, adjust);
00890     
00891     _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
00892                               new_body_len,
00893                               byte_order);
00894   }
00895 
00896   return TRUE;
00897 }
00898 
00899 static dbus_bool_t
00900 generate_byte_changed (DBusMessageDataIter *iter,
00901                        DBusString          *data,
00902                        DBusValidity        *expected_validity)
00903 {
00904   int byte_seq;
00905   int v_BYTE;
00906 
00907   /* This is a little convoluted to make the bodies the
00908    * outer loop and each byte of each body the inner
00909    * loop
00910    */
00911 
00912  restart:
00913   if (!generate_many_bodies (iter, data, expected_validity))
00914     return FALSE;
00915 
00916   iter_recurse (iter);
00917   byte_seq = iter_get_sequence (iter);
00918   iter_next (iter);
00919   iter_unrecurse (iter);
00920   
00921   if (byte_seq == _dbus_string_get_length (data))
00922     {
00923       _dbus_string_set_length (data, 0);
00924       /* reset byte count */
00925       iter_recurse (iter);
00926       iter_set_sequence (iter, 0);
00927       iter_unrecurse (iter);
00928       goto restart;
00929     }
00930   else
00931     {
00932       /* Undo the "next" in generate_many_bodies */
00933       iter_set_sequence (iter, iter_get_sequence (iter) - 1);
00934     }
00935 
00936   _dbus_assert (byte_seq < _dbus_string_get_length (data));
00937   v_BYTE = _dbus_string_get_byte (data, byte_seq);
00938   v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
00939   _dbus_string_set_byte (data, byte_seq, v_BYTE);
00940   *expected_validity = DBUS_VALIDITY_UNKNOWN;
00941 
00942   return TRUE;
00943 }
00944 
00945 #if 0
00946 /* This is really expensive and doesn't add too much coverage */
00947 
00948 static dbus_bool_t
00949 find_next_typecode (DBusMessageDataIter *iter,
00950                     DBusString          *data,
00951                     DBusValidity        *expected_validity)
00952 {
00953   int body_seq;
00954   int byte_seq;
00955   int base_depth;
00956 
00957   base_depth = iter->depth;
00958 
00959  restart:
00960   _dbus_assert (iter->depth == (base_depth + 0));
00961   _dbus_string_set_length (data, 0);
00962 
00963   body_seq = iter_get_sequence (iter);
00964   
00965   if (!generate_many_bodies (iter, data, expected_validity))
00966     return FALSE;
00967   /* Undo the "next" in generate_many_bodies */
00968   iter_set_sequence (iter, body_seq);
00969   
00970   iter_recurse (iter);
00971   while (TRUE)
00972     {
00973       _dbus_assert (iter->depth == (base_depth + 1));
00974       
00975       byte_seq = iter_get_sequence (iter);
00976 
00977       _dbus_assert (byte_seq <= _dbus_string_get_length (data));
00978       
00979       if (byte_seq == _dbus_string_get_length (data))
00980         {
00981           /* reset byte count */
00982           iter_set_sequence (iter, 0);
00983           iter_unrecurse (iter);
00984           _dbus_assert (iter->depth == (base_depth + 0));
00985           iter_next (iter); /* go to the next body */
00986           goto restart;
00987         }
00988 
00989       _dbus_assert (byte_seq < _dbus_string_get_length (data));
00990 
00991       if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
00992         break;
00993       else
00994         iter_next (iter);
00995     }
00996 
00997   _dbus_assert (byte_seq == iter_get_sequence (iter));
00998   _dbus_assert (byte_seq < _dbus_string_get_length (data));
00999 
01000   iter_unrecurse (iter);
01001 
01002   _dbus_assert (iter->depth == (base_depth + 0));
01003   
01004   return TRUE;
01005 }
01006 
01007 static const int typecodes[] = {
01008   DBUS_TYPE_INVALID,
01009   DBUS_TYPE_BYTE,
01010   DBUS_TYPE_BOOLEAN,
01011   DBUS_TYPE_INT16,
01012   DBUS_TYPE_UINT16,
01013   DBUS_TYPE_INT32,
01014   DBUS_TYPE_UINT32,
01015   DBUS_TYPE_INT64,
01016   DBUS_TYPE_UINT64,
01017   DBUS_TYPE_DOUBLE,
01018   DBUS_TYPE_STRING,
01019   DBUS_TYPE_OBJECT_PATH,
01020   DBUS_TYPE_SIGNATURE,
01021   DBUS_TYPE_ARRAY,
01022   DBUS_TYPE_VARIANT,
01023   DBUS_STRUCT_BEGIN_CHAR,
01024   DBUS_STRUCT_END_CHAR,
01025   DBUS_DICT_ENTRY_BEGIN_CHAR,
01026   DBUS_DICT_ENTRY_END_CHAR,
01027   DBUS_TYPE_UNIX_FD,
01028   255 /* random invalid typecode */
01029 };
01030 
01031 static dbus_bool_t
01032 generate_typecode_changed (DBusMessageDataIter *iter,
01033                            DBusString          *data,
01034                            DBusValidity        *expected_validity)
01035 {
01036   int byte_seq;
01037   int typecode_seq;
01038   int base_depth;
01039 
01040   base_depth = iter->depth;
01041 
01042  restart:
01043   _dbus_assert (iter->depth == (base_depth + 0));
01044   _dbus_string_set_length (data, 0);
01045   
01046   if (!find_next_typecode (iter, data, expected_validity))
01047     return FALSE;
01048 
01049   iter_recurse (iter);
01050   byte_seq = iter_get_sequence (iter);
01051 
01052   _dbus_assert (byte_seq < _dbus_string_get_length (data));
01053   
01054   iter_recurse (iter);
01055   typecode_seq = iter_get_sequence (iter);
01056   iter_next (iter);
01057 
01058   _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes));
01059   
01060   if (typecode_seq == _DBUS_N_ELEMENTS (typecodes))
01061     {
01062       _dbus_assert (iter->depth == (base_depth + 2));
01063       iter_set_sequence (iter, 0); /* reset typecode sequence */
01064       iter_unrecurse (iter);
01065       _dbus_assert (iter->depth == (base_depth + 1));
01066       iter_next (iter); /* go to the next byte_seq */
01067       iter_unrecurse (iter);
01068       _dbus_assert (iter->depth == (base_depth + 0));
01069       goto restart;
01070     }
01071 
01072   _dbus_assert (iter->depth == (base_depth + 2));
01073   iter_unrecurse (iter);
01074   _dbus_assert (iter->depth == (base_depth + 1));
01075   iter_unrecurse (iter);
01076   _dbus_assert (iter->depth == (base_depth + 0));
01077 
01078 #if 0
01079   printf ("Changing byte %d in message %d to %c\n",
01080           byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]);
01081 #endif
01082   
01083   _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]);
01084   *expected_validity = DBUS_VALIDITY_UNKNOWN;
01085   return TRUE;
01086 }
01087 #endif
01088 
01089 typedef struct
01090 {
01091   ChangeType type;
01092   dbus_uint32_t value; /* cast to signed for adjusts */
01093 } UIntChange;
01094 
01095 static const UIntChange uint32_changes[] = {
01096   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 },
01097   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 },
01098   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 },
01099   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 },
01100   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 },
01101   { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 },
01102   { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX },
01103   { CHANGE_TYPE_ABSOLUTE, 0 },
01104   { CHANGE_TYPE_ABSOLUTE, 1 },
01105   { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 },
01106   { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 }
01107 };
01108 
01109 static dbus_bool_t
01110 generate_uint32_changed (DBusMessageDataIter *iter,
01111                          DBusString          *data,
01112                          DBusValidity        *expected_validity)
01113 {
01114   int body_seq;
01115   int byte_seq;
01116   int change_seq;
01117   dbus_uint32_t v_UINT32;
01118   int byte_order;
01119   const UIntChange *change;
01120   int base_depth;
01121 
01122   /* Outer loop is each body, next loop is each change,
01123    * inner loop is each change location
01124    */
01125 
01126   base_depth = iter->depth;
01127   
01128  next_body:
01129   _dbus_assert (iter->depth == (base_depth + 0));
01130   _dbus_string_set_length (data, 0);
01131   body_seq = iter_get_sequence (iter);
01132   
01133   if (!generate_many_bodies (iter, data, expected_validity))
01134     return FALSE;
01135 
01136   _dbus_assert (iter->depth == (base_depth + 0));
01137 
01138   iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */
01139   iter_recurse (iter);
01140  next_change:
01141   _dbus_assert (iter->depth == (base_depth + 1));
01142   change_seq = iter_get_sequence (iter);
01143   
01144   if (change_seq == _DBUS_N_ELEMENTS (uint32_changes))
01145     {
01146       /* Reset change count */
01147       iter_set_sequence (iter, 0);
01148       iter_unrecurse (iter);
01149       iter_next (iter);
01150       goto next_body;
01151     }
01152 
01153   _dbus_assert (iter->depth == (base_depth + 1));
01154   
01155   iter_recurse (iter);
01156   _dbus_assert (iter->depth == (base_depth + 2));
01157   byte_seq = iter_get_sequence (iter);
01158   /* skip 4 bytes at a time */
01159   iter_next (iter);
01160   iter_next (iter);
01161   iter_next (iter);
01162   iter_next (iter);
01163   iter_unrecurse (iter);
01164 
01165   _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq);
01166   if (byte_seq >= (_dbus_string_get_length (data) - 4))
01167     {
01168       /* reset byte count */
01169       _dbus_assert (iter->depth == (base_depth + 1));
01170       iter_recurse (iter);
01171       _dbus_assert (iter->depth == (base_depth + 2));
01172       iter_set_sequence (iter, 0);
01173       iter_unrecurse (iter);
01174       _dbus_assert (iter->depth == (base_depth + 1));
01175       iter_next (iter);
01176       goto next_change;
01177     }
01178   
01179   _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4));
01180 
01181   byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
01182   
01183   v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL);
01184 
01185   change = &uint32_changes[change_seq];
01186 
01187   if (change->type == CHANGE_TYPE_ADJUST)
01188     {
01189       v_UINT32 += (int) change->value;
01190     }
01191   else
01192     {
01193       v_UINT32 = change->value;
01194     }
01195 
01196 #if 0
01197   printf ("body %d change %d pos %d ",
01198           body_seq, change_seq, byte_seq);
01199 
01200   if (change->type == CHANGE_TYPE_ADJUST)
01201     printf ("adjust by %d", (int) change->value);
01202   else
01203     printf ("set to %u", change->value);
01204   
01205   printf (" \t%u -> %u\n",
01206           _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL),
01207           v_UINT32);
01208 #endif
01209   
01210   _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order);
01211   *expected_validity = DBUS_VALIDITY_UNKNOWN;
01212 
01213   _dbus_assert (iter->depth == (base_depth + 1));
01214   iter_unrecurse (iter);
01215   _dbus_assert (iter->depth == (base_depth + 0));
01216           
01217   return TRUE;
01218 }
01219 
01220 typedef struct
01221 {
01222   const char *name;
01223   DBusMessageGeneratorFunc func;  
01224 } DBusMessageGenerator;
01225 
01226 static const DBusMessageGenerator generators[] = {
01227   { "trivial example of each message type", generate_trivial },
01228   { "assorted arguments", generate_many_bodies },
01229   { "assorted special cases", generate_special },
01230   { "each uint32 modified", generate_uint32_changed },
01231   { "wrong body lengths", generate_wrong_length },
01232   { "each byte modified", generate_byte_changed },
01233 #if 0
01234   /* This is really expensive and doesn't add too much coverage */
01235   { "change each typecode", generate_typecode_changed }
01236 #endif
01237 };
01238 
01239 void
01240 _dbus_message_data_free (DBusMessageData *data)
01241 {
01242   _dbus_string_free (&data->data);
01243 }
01244 
01245 void
01246 _dbus_message_data_iter_init (DBusMessageDataIter *iter)
01247 {
01248   int i;
01249   
01250   iter->depth = 0;
01251   i = 0;
01252   while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
01253     {
01254       iter->sequence_nos[i] = 0;
01255       ++i;
01256     }
01257   iter->count = 0;
01258 }
01259 
01260 dbus_bool_t
01261 _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
01262                                       DBusMessageData     *data)
01263 {
01264   DBusMessageGeneratorFunc func;
01265   int generator;
01266 
01267  restart:
01268   generator = iter_get_sequence (iter);
01269   
01270   if (generator == _DBUS_N_ELEMENTS (generators))
01271     return FALSE;
01272 
01273   iter_recurse (iter);
01274   
01275   if (iter_first_in_series (iter))
01276     {
01277       printf (" testing message loading: %s ", generators[generator].name);
01278       fflush (stdout);
01279     }
01280   
01281   func = generators[generator].func;
01282 
01283   if (!_dbus_string_init (&data->data))
01284     _dbus_assert_not_reached ("oom");
01285   
01286   if ((*func)(iter, &data->data, &data->expected_validity))
01287     ;
01288   else
01289     {
01290       iter_set_sequence (iter, 0);
01291       iter_unrecurse (iter);
01292       iter_next (iter); /* next generator */
01293       _dbus_string_free (&data->data);
01294       printf ("%d test loads cumulative\n", iter->count);
01295       goto restart;
01296     }
01297   iter_unrecurse (iter);
01298 
01299   iter->count += 1;
01300   return TRUE;
01301 }
01302 
01303 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
01304 
01305 #endif /* DBUS_BUILD_TESTS */