test-engine-stuff.c

Go to the documentation of this file.
00001 /*
00002  *  This program is free software; you can redistribute it and/or modify
00003  *  it under the terms of the GNU General Public License as published by
00004  *  the Free Software Foundation; either version 2 of the License, or
00005  *  (at your option) any later version.
00006  *
00007  *  This program is distributed in the hope that it will be useful,
00008  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010  *  GNU General Public License for more details.
00011  *
00012  *  You should have received a copy of the GNU General Public License
00013  *  along with this program; if not, write to the Free Software
00014  *  Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA  02110-1301,  USA
00015  */
00016 
00025 #include <sys/types.h>
00026 #include <dirent.h>
00027 #include <fcntl.h>
00028 #include <glib.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <sys/stat.h>
00033 #include <unistd.h>
00034 #include "config.h"
00035 #include "qof.h"
00036 #include "test-engine-stuff.h"
00037 #include "test-stuff.h"
00038 
00039 static gboolean glist_strings_only = FALSE;
00040 
00041 static GHashTable *exclude_kvp_types = NULL;
00042 static gint kvp_max_depth = 5;
00043 static gint kvp_frame_max_elements = 10;
00044 
00045 gboolean gnc_engine_debug_random = FALSE;
00046 
00047 /* ========================================================== */
00048 /* Set control parameters governing the run. */
00049 
00050 void
00051 set_max_kvp_depth (gint max_kvp_depth)
00052 {
00053     kvp_max_depth = MAX (max_kvp_depth, 1);
00054 }
00055 
00056 void
00057 set_max_kvp_frame_elements (gint max_kvp_frame_elements)
00058 {
00059     kvp_frame_max_elements = MAX (max_kvp_frame_elements, 1);
00060 }
00061 
00062 void
00063 kvp_exclude_type (KvpValueType kvp_type)
00064 {
00065     gint *key;
00066 
00067     if (!exclude_kvp_types)
00068         exclude_kvp_types = g_hash_table_new (g_int_hash, g_int_equal);
00069 
00070     key = g_new (gint, 1);
00071     *key = kvp_type;
00072 
00073     g_hash_table_insert (exclude_kvp_types, key, exclude_kvp_types);
00074 }
00075 
00076 static gboolean
00077 kvp_type_excluded (KvpValueType kvp_type)
00078 {
00079     gint key = kvp_type;
00080 
00081     if (!exclude_kvp_types)
00082         return FALSE;
00083 
00084     if (g_hash_table_lookup (exclude_kvp_types, &key))
00085         return TRUE;
00086 
00087     return FALSE;
00088 }
00089 
00090 void
00091 random_glist_strings_only (gboolean strings_only)
00092 {
00093     glist_strings_only = strings_only;
00094 }
00095 
00096 
00097 #ifndef QOF_DISABLE_DEPRECATED
00098 static gboolean zero_nsec = FALSE;
00099 
00100 void
00101 random_timespec_zero_nsec (gboolean zero_nsec_in)
00102 {
00103     zero_nsec = zero_nsec_in;
00104 }
00105 
00106 static gboolean usec_resolution = FALSE;
00107 
00108 void
00109 random_timespec_usec_resolution (gboolean usec_resolution_in)
00110 {
00111     usec_resolution = usec_resolution_in;
00112 }
00113 #endif
00114 /* ========================================================== */
00115 
00116 static gint borked = 80;
00117 
00118 static inline gboolean
00119 do_bork (void)
00120 {
00121     if (1 == get_random_int_in_range (0, borked))
00122     {
00123         return TRUE;
00124     }
00125     return FALSE;
00126 }
00127 
00128 /* ========================================================== */
00129 /* GList stuff */
00130 /*
00131 static gpointer
00132 get_random_list_element (GList *list)
00133 {
00134   g_return_val_if_fail (list, NULL);
00135 
00136   return g_list_nth_data (list,
00137                           get_random_int_in_range (0,
00138                                                    g_list_length (list) - 1));
00139 }
00140 */
00141 static KvpValue *get_random_kvp_value_depth (int type, gint depth);
00142 
00143 static GList *
00144 get_random_glist_depth (gint depth)
00145 {
00146     GList *ret = NULL;
00147     int count = get_random_int_in_range (1, 5);
00148     int i;
00149 
00150     if (depth >= kvp_max_depth)
00151         return NULL;
00152 
00153     for (i = 0; i < count; i++)
00154     {
00155         KvpValueType kvpt;
00156         KvpValue *value;
00157 
00158         kvpt = glist_strings_only ? KVP_TYPE_STRING : -2;
00159 
00160         do
00161         {
00162             value = get_random_kvp_value_depth (kvpt, depth + 1);
00163         }
00164         while (!value);
00165 
00166         ret = g_list_prepend (ret, value);
00167     }
00168 
00169     return ret;
00170 }
00171 
00172 GList *
00173 get_random_glist (void)
00174 {
00175     return get_random_glist_depth (0);
00176 }
00177 
00178 /* ========================================================== */
00179 /* Time/Date, GUID, binary data stuff */
00180 #ifndef QOF_DISABLE_DEPRECATED
00181 Timespec *
00182 get_random_timespec (void)
00183 {
00184     Timespec *ret;
00185 
00186     ret = g_new0 (Timespec, 1);
00187 
00188     while (ret->tv_sec <= 0)
00189         ret->tv_sec = rand ();
00190 
00191     if (zero_nsec)
00192         ret->tv_nsec = 0;
00193     else
00194     {
00195         ret->tv_nsec = rand ();
00196 
00197         if (usec_resolution)
00198         {
00199             ret->tv_nsec = MIN (ret->tv_nsec, 999999999);
00200             ret->tv_nsec /= 1000;
00201             ret->tv_nsec *= 1000;
00202         }
00203     }
00204 
00205     return ret;
00206 }
00207 #endif
00208 
00209 GUID *
00210 get_random_guid (void)
00211 {
00212     GUID *ret;
00213 
00214     ret = g_new (GUID, 1);
00215     guid_new (ret);
00216 
00217     return ret;
00218 }
00219 
00220 bin_data *
00221 get_random_binary_data (void)
00222 {
00223     int len;
00224     bin_data *ret;
00225 
00226     len = get_random_int_in_range (20, 100);
00227     ret = g_new (bin_data, 1);
00228     ret->data = g_new (guchar, len);
00229     ret->len = len;
00230 
00231     for (len--; len >= 0; len--)
00232     {
00233         ret->data[len] = (guchar) get_random_int_in_range (0, 255);
00234     }
00235 
00236     return ret;
00237 }
00238 
00239 /* ========================================================== */
00240 /* KVP stuff */
00241 
00242 static KvpFrame *get_random_kvp_frame_depth (gint depth);
00243 
00244 static KvpValue *
00245 get_random_kvp_value_depth (int type, gint depth)
00246 {
00247     int datype = type;
00248     KvpValue *ret;
00249 
00250     if (datype == -1)
00251     {
00252         datype = get_random_int_in_range (KVP_TYPE_GINT64, KVP_TYPE_FRAME);
00253     }
00254 
00255     if (datype == -2)
00256     {
00257         datype =
00258             get_random_int_in_range (KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1);
00259     }
00260 
00261     if (datype == KVP_TYPE_FRAME && depth >= kvp_max_depth)
00262         return NULL;
00263 
00264     if (datype == KVP_TYPE_GLIST && depth >= kvp_max_depth)
00265         return NULL;
00266 
00267     if (kvp_type_excluded (datype))
00268         return NULL;
00269 
00270     switch (datype)
00271     {
00272     case KVP_TYPE_GINT64:
00273         ret = kvp_value_new_gint64 (get_random_gint64 ());
00274         break;
00275 
00276     case KVP_TYPE_DOUBLE:
00277         ret = NULL;
00278         break;
00279 
00280     case KVP_TYPE_NUMERIC:
00281         ret = kvp_value_new_numeric (get_random_qof_numeric ());
00282         break;
00283 
00284     case KVP_TYPE_STRING:
00285         {
00286             gchar *tmp_str;
00287             tmp_str = get_random_string ();
00288             if (!tmp_str)
00289                 return NULL;
00290 
00291             ret = kvp_value_new_string (tmp_str);
00292             g_free (tmp_str);
00293         }
00294         break;
00295 
00296     case KVP_TYPE_GUID:
00297         {
00298             GUID *tmp_guid;
00299             tmp_guid = get_random_guid ();
00300             ret = kvp_value_new_guid (tmp_guid);
00301             g_free (tmp_guid);
00302         }
00303         break;
00304 #ifndef QOF_DISABLE_DEPRECATED
00305     case KVP_TYPE_TIMESPEC:
00306         {
00307             Timespec *ts = get_random_timespec ();
00308             ret = kvp_value_new_timespec (*ts);
00309             g_free (ts);
00310         }
00311         break;
00312 #endif
00313     case KVP_TYPE_BINARY:
00314         {
00315             bin_data *tmp_data;
00316             tmp_data = get_random_binary_data ();
00317             ret = kvp_value_new_binary (tmp_data->data, tmp_data->len);
00318             g_free (tmp_data->data);
00319             g_free (tmp_data);
00320         }
00321         break;
00322 
00323     case KVP_TYPE_GLIST:
00324         ret = kvp_value_new_glist_nc (get_random_glist_depth (depth + 1));
00325         break;
00326 
00327     case KVP_TYPE_FRAME:
00328         {
00329             KvpFrame *tmp_frame;
00330             tmp_frame = get_random_kvp_frame_depth (depth + 1);
00331             ret = kvp_value_new_frame (tmp_frame);
00332             kvp_frame_delete (tmp_frame);
00333         }
00334         break;
00335 
00336     default:
00337         ret = NULL;
00338         break;
00339     }
00340     return ret;
00341 }
00342 
00343 static KvpFrame *
00344 get_random_kvp_frame_depth (gint depth)
00345 {
00346     KvpFrame *ret;
00347     int vals_to_add;
00348     gboolean val_added;
00349 
00350     if (depth >= kvp_max_depth)
00351         return NULL;
00352 
00353     ret = kvp_frame_new ();
00354 
00355     vals_to_add = get_random_int_in_range (1, kvp_frame_max_elements);
00356     val_added = FALSE;
00357 
00358     for (; vals_to_add > 0; vals_to_add--)
00359     {
00360         gchar *key;
00361         KvpValue *val;
00362 
00363         key = NULL;
00364         while (key == NULL)
00365         {
00366             key = get_random_string_without ("/");
00367             if (*key == '\0')
00368             {
00369                 g_free (key);
00370                 key = NULL;
00371             }
00372         }
00373 
00374         val = get_random_kvp_value_depth (-1, depth + 1);
00375         if (!val)
00376         {
00377             g_free (key);
00378             if (!val_added)
00379                 vals_to_add++;
00380             continue;
00381         }
00382 
00383         val_added = TRUE;
00384 
00385         kvp_frame_set_slot_nc (ret, key, val);
00386 
00387         g_free (key);
00388     }
00389 
00390     return ret;
00391 }
00392 
00393 KvpFrame *
00394 get_random_kvp_frame (void)
00395 {
00396     return get_random_kvp_frame_depth (0);
00397 }
00398 
00399 KvpValue *
00400 get_random_kvp_value (int type)
00401 {
00402     return get_random_kvp_value_depth (type, 0);
00403 }
00404 
00405 /* ================================================================= */
00406 /* Numeric stuff */
00407 
00408 #define RAND_IN_RANGE(X) (((X)*((gint64) (rand()+1)))/RAND_MAX)
00409 
00410 QofNumeric
00411 get_random_qof_numeric (void)
00412 {
00413     gint64 numer;
00414     gint64 deno;
00415 
00416     if (RAND_MAX / 8 > rand ())
00417     {
00418         /* Random number between 1 and 6000 */
00419         deno = RAND_IN_RANGE (6000ULL);
00420     }
00421     else
00422     {
00423         gint64 norm = RAND_IN_RANGE (10ULL);
00424 
00425         /* multiple of 10, between 1 and 10 000 million */
00426         deno = 1;
00427         while (norm)
00428         {
00429             deno *= 10;
00430             norm--;
00431         }
00432     }
00433 
00434     /* Arbitrary random numbers can cause pointless overflow
00435      * during calculations.  Limit dynamic range in hopes
00436      * of avoiding overflow. */
00437     numer = get_random_gint64 () / 100000;
00438     if (0 == numer)
00439         numer = 1;
00440     return qof_numeric_create (numer, deno);
00441 }
00442 
00443 /*
00444 static GList *
00445 get_random_guids(int max)
00446 {
00447   GList *guids = NULL;
00448   int num_guids;
00449 
00450   if (max < 1) return NULL;
00451 
00452   num_guids = get_random_int_in_range (1, max);
00453 
00454   while (num_guids-- > 0)
00455     g_list_prepend (guids, get_random_guid ());
00456 
00457   return guids;
00458   }
00459 *//*
00460      static void
00461      free_random_guids(GList *guids)
00462      {
00463      GList *node;
00464 
00465      for (node = guids; node; node = node->next)
00466      g_free (node->data);
00467 
00468      g_list_free (guids);
00469      }
00470    *//*
00471      static QofQueryOp
00472      get_random_queryop(void)
00473      {
00474      QofQueryOp op = get_random_int_in_range (1, QOF_QUERY_XOR);
00475      if (gnc_engine_debug_random) printf ("op = %d, ", op);
00476      return op;
00477      }
00478    *//*
00479      static GSList *
00480      get_random_kvp_path (void)
00481      {
00482      GSList *path;
00483      gint len;
00484 
00485      path = NULL;
00486      len = get_random_int_in_range (1, kvp_max_depth);
00487 
00488      while (len--)
00489      path = g_slist_prepend (path, get_random_string ());
00490 
00491      return g_slist_reverse (path);
00492      }
00493    *//*
00494      static void
00495      free_random_kvp_path (GSList *path)
00496      {
00497      GSList *node;
00498 
00499      for (node = path; node; node = node->next)
00500      g_free (node->data);
00501 
00502      g_slist_free (path);
00503      }
00504    */
00505 typedef enum
00506 {
00507     BY_STANDARD = 1,
00508     BY_DATE,
00509     BY_DATE_ENTERED,
00510     BY_DATE_RECONCILED,
00511     BY_NUM,
00512     BY_AMOUNT,
00513     BY_MEMO,
00514     BY_DESC,
00515     BY_NONE
00516 } sort_type_t;
00517 
00518 typedef struct
00519 {
00520     QofIdType where;
00521     GSList *path;
00522     QofQuery *q;
00523 } KVPQueryData;
00524 
00525 TestQueryTypes
00526 get_random_query_type (void)
00527 {
00528     switch (get_random_int_in_range (0, 4))
00529     {
00530     case 0:
00531         return SIMPLE_QT;
00532     case 4:
00533         return GUID_QT;
00534     default:
00535         return SIMPLE_QT;
00536     }
00537 }

Generated on Thu Jan 31 22:50:26 2008 for QOF by  doxygen 1.5.4