dbus-message-factory.c

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

Generated on Fri Sep 21 18:12:12 2007 for D-Bus by  doxygen 1.5.1