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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 
00035 #include "gnc-date.h"
00036 #include "qofquerycore.h"
00037 
00038 #include "test-engine-stuff.h"
00039 #include "test-stuff.h"
00040 
00041 static gboolean glist_strings_only = FALSE;
00042 
00043 static GHashTable *exclude_kvp_types = NULL;
00044 static gint kvp_max_depth = 5;
00045 static gint kvp_frame_max_elements = 10;
00046 
00047 gboolean gnc_engine_debug_random = FALSE;
00048 
00049 /* ========================================================== */
00050 /* Set control parameters governing the run. */
00051 
00052 void
00053 set_max_kvp_depth (gint max_kvp_depth)
00054 {
00055   kvp_max_depth = MAX (max_kvp_depth, 1);
00056 }
00057 
00058 void
00059 set_max_kvp_frame_elements (gint max_kvp_frame_elements)
00060 {
00061   kvp_frame_max_elements = MAX (max_kvp_frame_elements, 1);
00062 }
00063 
00064 void
00065 kvp_exclude_type (KvpValueType kvp_type)
00066 {
00067   gint *key;
00068 
00069   if (!exclude_kvp_types)
00070     exclude_kvp_types = g_hash_table_new (g_int_hash, g_int_equal);
00071 
00072   key = g_new (gint, 1);
00073   *key = kvp_type;
00074 
00075   g_hash_table_insert (exclude_kvp_types, key, exclude_kvp_types);
00076 }
00077 
00078 static gboolean
00079 kvp_type_excluded (KvpValueType kvp_type)
00080 {
00081   gint key = kvp_type;
00082 
00083   if (!exclude_kvp_types)
00084     return FALSE;
00085 
00086   if (g_hash_table_lookup (exclude_kvp_types, &key))
00087     return TRUE;
00088 
00089   return FALSE;
00090 }
00091 
00092 void
00093 random_glist_strings_only (gboolean strings_only)
00094 {
00095   glist_strings_only = strings_only;
00096 }
00097 
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 
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 kvp_value* 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 
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 
00208 GUID*
00209 get_random_guid(void)
00210 {
00211     GUID *ret;
00212 
00213     ret = g_new(GUID, 1);
00214     guid_new(ret);
00215 
00216     return ret;
00217 }
00218 
00219 bin_data*
00220 get_random_binary_data(void)
00221 {
00222     int len;
00223     bin_data *ret;
00224 
00225     len = get_random_int_in_range(20,100);
00226     ret = g_new(bin_data, 1);
00227     ret->data = g_new(guchar, len);
00228     ret->len = len;
00229 
00230     for(len--; len >= 0; len--)
00231     {
00232         ret->data[len] = (guchar)get_random_int_in_range(0,255);
00233     }
00234 
00235     return ret;
00236 }
00237 
00238 /* ========================================================== */
00239 /* KVP stuff */
00240 
00241 static KvpFrame* get_random_kvp_frame_depth (gint depth);
00242 
00243 static KvpValue*
00244 get_random_kvp_value_depth (int type, gint depth)
00245 {
00246     int datype = type;
00247     KvpValue *ret;
00248 
00249     if (datype == -1)
00250     {
00251         datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME);
00252     }
00253 
00254     if (datype == -2)
00255     {
00256         datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1);
00257     }
00258 
00259     if (datype == KVP_TYPE_FRAME && depth >= kvp_max_depth)
00260       return NULL;
00261 
00262     if (datype == KVP_TYPE_GLIST && depth >= kvp_max_depth)
00263       return NULL;
00264 
00265     if (kvp_type_excluded (datype))
00266       return NULL;
00267 
00268     switch(datype)
00269     {
00270     case KVP_TYPE_GINT64:
00271         ret = kvp_value_new_gint64(get_random_gint64());
00272         break;
00273 
00274     case KVP_TYPE_DOUBLE:
00275         ret = NULL;
00276         break;
00277 
00278     case KVP_TYPE_NUMERIC:
00279         ret = kvp_value_new_gnc_numeric(get_random_gnc_numeric());
00280         break;
00281 
00282     case KVP_TYPE_STRING:
00283     {
00284         gchar *tmp_str;
00285         tmp_str = get_random_string();
00286         if(!tmp_str)
00287           return NULL;
00288 
00289         ret = kvp_value_new_string(tmp_str);
00290         g_free(tmp_str);
00291     }
00292         break;
00293 
00294     case KVP_TYPE_GUID:
00295     {
00296         GUID *tmp_guid;
00297         tmp_guid = get_random_guid();
00298         ret = kvp_value_new_guid(tmp_guid);
00299         g_free(tmp_guid);
00300     }
00301         break;
00302 
00303     case KVP_TYPE_TIMESPEC:
00304     {
00305         Timespec *ts = get_random_timespec();
00306         ret = kvp_value_new_timespec (*ts);
00307         g_free(ts);
00308     }
00309         break;
00310 
00311     case KVP_TYPE_BINARY:
00312     {
00313         bin_data *tmp_data;
00314         tmp_data = get_random_binary_data();
00315         ret = kvp_value_new_binary(tmp_data->data, tmp_data->len);
00316         g_free(tmp_data->data);
00317         g_free(tmp_data);
00318     }
00319         break;
00320 
00321     case KVP_TYPE_GLIST:
00322         ret = kvp_value_new_glist_nc(get_random_glist_depth (depth + 1));
00323         break;
00324 
00325     case KVP_TYPE_FRAME:
00326     {
00327         KvpFrame *tmp_frame;
00328         tmp_frame = get_random_kvp_frame_depth(depth + 1);
00329         ret = kvp_value_new_frame(tmp_frame);
00330         kvp_frame_delete(tmp_frame);
00331     }
00332         break;
00333 
00334     default:
00335         ret = NULL;
00336         break;
00337     }
00338     return ret;
00339 }
00340 
00341 static KvpFrame*
00342 get_random_kvp_frame_depth (gint depth)
00343 {
00344     KvpFrame *ret;
00345     int vals_to_add;
00346     gboolean val_added;
00347 
00348     if (depth >= kvp_max_depth)
00349       return NULL;
00350 
00351     ret = kvp_frame_new();
00352 
00353     vals_to_add = get_random_int_in_range(1,kvp_frame_max_elements);
00354     val_added = FALSE;
00355 
00356     for (;vals_to_add > 0; vals_to_add--)
00357     {
00358         gchar *key;
00359         KvpValue *val;
00360 
00361         key = NULL;
00362         while (key == NULL) {
00363           key = get_random_string_without("/");
00364           if (*key == '\0') {
00365             g_free(key);
00366             key = NULL;
00367           }
00368         }
00369 
00370         val = get_random_kvp_value_depth (-1, depth + 1);
00371         if (!val)
00372         {
00373           g_free(key);
00374           if (!val_added)
00375             vals_to_add++;
00376           continue;
00377         }
00378 
00379         val_added = TRUE;
00380 
00381         kvp_frame_set_slot_nc(ret, key, val);
00382 
00383         g_free(key);
00384     }
00385 
00386     return ret;
00387 }
00388 
00389 KvpFrame *
00390 get_random_kvp_frame (void)
00391 {
00392   return get_random_kvp_frame_depth (0);
00393 }
00394 
00395 KvpValue *
00396 get_random_kvp_value(int type)
00397 {
00398   return get_random_kvp_value_depth (type, 0);
00399 }
00400 
00401 /* ================================================================= */
00402 /* Numeric stuff */
00403 
00404 #define RAND_IN_RANGE(X) (((X)*((gint64) (rand()+1)))/RAND_MAX)
00405 
00406 gnc_numeric
00407 get_random_gnc_numeric(void)
00408 {
00409     gint64 numer;
00410     gint64 deno;
00411 
00412     if (RAND_MAX/8 > rand())
00413     {
00414        /* Random number between 1 and 6000 */
00415        deno = RAND_IN_RANGE(6000ULL);
00416     }
00417     else
00418     {
00419        gint64 norm = RAND_IN_RANGE (10ULL);
00420 
00421        /* multiple of 10, between 1 and 10 000 million */
00422        deno = 1;
00423        while (norm)
00424        {
00425           deno *= 10;
00426           norm --;
00427        }
00428     }
00429 
00430     /* Arbitrary random numbers can cause pointless overflow
00431      * during calculations.  Limit dynamic range in hopes
00432      * of avoiding overflow. */
00433     numer = get_random_gint64()/100000;
00434     if (0 == numer) numer = 1;
00435     return gnc_numeric_create(numer, deno);
00436 }
00437 /*
00438 static GList *
00439 get_random_guids(int max)
00440 {
00441   GList *guids = NULL;
00442   int num_guids;
00443 
00444   if (max < 1) return NULL;
00445 
00446   num_guids = get_random_int_in_range (1, max);
00447 
00448   while (num_guids-- > 0)
00449     g_list_prepend (guids, get_random_guid ());
00450 
00451   return guids;
00452 }
00453 *//*
00454 static void
00455 free_random_guids(GList *guids)
00456 {
00457   GList *node;
00458 
00459   for (node = guids; node; node = node->next)
00460     g_free (node->data);
00461 
00462   g_list_free (guids);
00463 }
00464 *//*
00465 static QofQueryOp
00466 get_random_queryop(void)
00467 {
00468   QofQueryOp op = get_random_int_in_range (1, QOF_QUERY_XOR);
00469   if (gnc_engine_debug_random) printf ("op = %d, ", op);
00470   return op;
00471 }
00472 *//*
00473 static GSList *
00474 get_random_kvp_path (void)
00475 {
00476   GSList *path;
00477   gint len;
00478 
00479   path = NULL;
00480   len = get_random_int_in_range (1, kvp_max_depth);
00481 
00482   while (len--)
00483     path = g_slist_prepend (path, get_random_string ());
00484 
00485   return g_slist_reverse (path);
00486 }
00487 *//*
00488 static void
00489 free_random_kvp_path (GSList *path)
00490 {
00491   GSList *node;
00492 
00493   for (node = path; node; node = node->next)
00494     g_free (node->data);
00495 
00496   g_slist_free (path);
00497 }
00498 */
00499 typedef enum {
00500   BY_STANDARD = 1,
00501   BY_DATE,
00502   BY_DATE_ENTERED,
00503   BY_DATE_RECONCILED,
00504   BY_NUM,
00505   BY_AMOUNT,
00506   BY_MEMO,
00507   BY_DESC,
00508   BY_NONE
00509 } sort_type_t;
00510 
00511 typedef struct
00512 {
00513   QofIdType where;
00514   GSList *path;
00515   QofQuery *q;
00516 } KVPQueryData;
00517 
00518 TestQueryTypes
00519 get_random_query_type (void)
00520 {
00521   switch (get_random_int_in_range (0, 4))
00522   {
00523     case 0: return SIMPLE_QT;
00524     case 4: return GUID_QT;
00525     default: return SIMPLE_QT;
00526   }
00527 }

Generated on Fri May 12 17:57:21 2006 for QOF by  doxygen 1.4.4