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

Generated on Tue Jul 7 15:13:59 2009 for D-BUS by  doxygen 1.4.6