00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00026 #include <sys/types.h>
00027 #include <dirent.h>
00028 #include <fcntl.h>
00029 #include <glib.h>
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <sys/stat.h>
00034 #include <unistd.h>
00035 #include "config.h"
00036 #include "qof.h"
00037 #include "test-engine-stuff.h"
00038 #include "test-stuff.h"
00039
00040 static gboolean glist_strings_only = FALSE;
00041
00042 static GHashTable *exclude_kvp_types = NULL;
00043 static gint kvp_max_depth = 5;
00044 static gint kvp_frame_max_elements = 10;
00045
00046 gboolean gnc_engine_debug_random = FALSE;
00047
00048
00049
00050
00051 void
00052 set_max_kvp_depth (gint max_kvp_depth)
00053 {
00054 kvp_max_depth = MAX (max_kvp_depth, 1);
00055 }
00056
00057 void
00058 set_max_kvp_frame_elements (gint max_kvp_frame_elements)
00059 {
00060 kvp_frame_max_elements = MAX (max_kvp_frame_elements, 1);
00061 }
00062
00063 void
00064 kvp_exclude_type (KvpValueType kvp_type)
00065 {
00066 gint *key;
00067
00068 if (!exclude_kvp_types)
00069 exclude_kvp_types = g_hash_table_new (g_int_hash, g_int_equal);
00070
00071 key = g_new (gint, 1);
00072 *key = kvp_type;
00073
00074 g_hash_table_insert (exclude_kvp_types, key, exclude_kvp_types);
00075 }
00076
00077 static gboolean
00078 kvp_type_excluded (KvpValueType kvp_type)
00079 {
00080 gint key = kvp_type;
00081
00082 if (!exclude_kvp_types)
00083 return FALSE;
00084
00085 if (g_hash_table_lookup (exclude_kvp_types, &key))
00086 return TRUE;
00087
00088 return FALSE;
00089 }
00090
00091 void
00092 random_glist_strings_only (gboolean strings_only)
00093 {
00094 glist_strings_only = strings_only;
00095 }
00096
00097
00098
00099
00100 static gint borked = 80;
00101
00102 static inline gboolean
00103 do_bork (void)
00104 {
00105 if (1 == get_random_int_in_range (0, borked))
00106 {
00107 return TRUE;
00108 }
00109 return FALSE;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static KvpValue *get_random_kvp_value_depth (int type, gint depth);
00126
00127 static GList *
00128 get_random_glist_depth (gint depth)
00129 {
00130 GList *ret = NULL;
00131 int count = get_random_int_in_range (1, 5);
00132 int i;
00133
00134 if (depth >= kvp_max_depth)
00135 return NULL;
00136
00137 for (i = 0; i < count; i++)
00138 {
00139 KvpValueType kvpt;
00140 KvpValue *value;
00141
00142 kvpt = glist_strings_only ? KVP_TYPE_STRING : -2;
00143
00144 do
00145 {
00146 value = get_random_kvp_value_depth (kvpt, depth + 1);
00147 }
00148 while (!value);
00149
00150 ret = g_list_prepend (ret, value);
00151 }
00152
00153 return ret;
00154 }
00155
00156 GList *
00157 get_random_glist (void)
00158 {
00159 return get_random_glist_depth (0);
00160 }
00161
00162
00163
00164
00165 GUID *
00166 get_random_guid (void)
00167 {
00168 GUID *ret;
00169
00170 ret = g_new (GUID, 1);
00171 guid_new (ret);
00172
00173 return ret;
00174 }
00175
00176 bin_data *
00177 get_random_binary_data (void)
00178 {
00179 int len;
00180 bin_data *ret;
00181
00182 len = get_random_int_in_range (20, 100);
00183 ret = g_new (bin_data, 1);
00184 ret->data = g_new (guchar, len);
00185 ret->len = len;
00186
00187 for (len--; len >= 0; len--)
00188 {
00189 ret->data[len] = (guchar) get_random_int_in_range (0, 255);
00190 }
00191
00192 return ret;
00193 }
00194
00195
00196
00197
00198 static KvpFrame *get_random_kvp_frame_depth (gint depth);
00199
00200 static KvpValue *
00201 get_random_kvp_value_depth (int type, gint depth)
00202 {
00203 int datype = type;
00204 KvpValue *ret;
00205
00206 if (datype == -1)
00207 {
00208 datype = get_random_int_in_range (KVP_TYPE_GINT64, KVP_TYPE_FRAME);
00209 }
00210
00211 if (datype == -2)
00212 {
00213 datype =
00214 get_random_int_in_range (KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1);
00215 }
00216
00217 if (datype == KVP_TYPE_FRAME && depth >= kvp_max_depth)
00218 return NULL;
00219
00220 if (datype == KVP_TYPE_GLIST && depth >= kvp_max_depth)
00221 return NULL;
00222
00223 if (kvp_type_excluded (datype))
00224 return NULL;
00225
00226 switch (datype)
00227 {
00228 case KVP_TYPE_GINT64:
00229 ret = kvp_value_new_gint64 (get_random_gint64 ());
00230 break;
00231
00232 case KVP_TYPE_DOUBLE:
00233 ret = NULL;
00234 break;
00235
00236 case KVP_TYPE_NUMERIC:
00237 ret = kvp_value_new_numeric (get_random_qof_numeric ());
00238 break;
00239
00240 case KVP_TYPE_STRING:
00241 {
00242 gchar *tmp_str;
00243 tmp_str = get_random_string ();
00244 if (!tmp_str)
00245 return NULL;
00246
00247 ret = kvp_value_new_string (tmp_str);
00248 g_free (tmp_str);
00249 }
00250 break;
00251
00252 case KVP_TYPE_GUID:
00253 {
00254 GUID *tmp_guid;
00255 tmp_guid = get_random_guid ();
00256 ret = kvp_value_new_guid (tmp_guid);
00257 g_free (tmp_guid);
00258 }
00259 break;
00260 case KVP_TYPE_BINARY:
00261 {
00262 bin_data *tmp_data;
00263 tmp_data = get_random_binary_data ();
00264 ret = kvp_value_new_binary (tmp_data->data, tmp_data->len);
00265 g_free (tmp_data->data);
00266 g_free (tmp_data);
00267 }
00268 break;
00269
00270 case KVP_TYPE_GLIST:
00271 ret = kvp_value_new_glist_nc (get_random_glist_depth (depth + 1));
00272 break;
00273
00274 case KVP_TYPE_FRAME:
00275 {
00276 KvpFrame *tmp_frame;
00277 tmp_frame = get_random_kvp_frame_depth (depth + 1);
00278 ret = kvp_value_new_frame (tmp_frame);
00279 kvp_frame_delete (tmp_frame);
00280 }
00281 break;
00282
00283 default:
00284 ret = NULL;
00285 break;
00286 }
00287 return ret;
00288 }
00289
00290 static KvpFrame *
00291 get_random_kvp_frame_depth (gint depth)
00292 {
00293 KvpFrame *ret;
00294 int vals_to_add;
00295 gboolean val_added;
00296
00297 if (depth >= kvp_max_depth)
00298 return NULL;
00299
00300 ret = kvp_frame_new ();
00301
00302 vals_to_add = get_random_int_in_range (1, kvp_frame_max_elements);
00303 val_added = FALSE;
00304
00305 for (; vals_to_add > 0; vals_to_add--)
00306 {
00307 gchar *key;
00308 KvpValue *val;
00309
00310 key = NULL;
00311 while (key == NULL)
00312 {
00313 key = get_random_string_without ("/");
00314 if (*key == '\0')
00315 {
00316 g_free (key);
00317 key = NULL;
00318 }
00319 }
00320
00321 val = get_random_kvp_value_depth (-1, depth + 1);
00322 if (!val)
00323 {
00324 g_free (key);
00325 if (!val_added)
00326 vals_to_add++;
00327 continue;
00328 }
00329
00330 val_added = TRUE;
00331
00332 kvp_frame_set_slot_nc (ret, key, val);
00333
00334 g_free (key);
00335 }
00336
00337 return ret;
00338 }
00339
00340 KvpFrame *
00341 get_random_kvp_frame (void)
00342 {
00343 return get_random_kvp_frame_depth (0);
00344 }
00345
00346 KvpValue *
00347 get_random_kvp_value (int type)
00348 {
00349 return get_random_kvp_value_depth (type, 0);
00350 }
00351
00352
00353
00354
00355 #define RAND_IN_RANGE(X) (((X)*((gint64) (rand()+1)))/RAND_MAX)
00356
00357 QofNumeric
00358 get_random_qof_numeric (void)
00359 {
00360 gint64 numer;
00361 gint64 deno;
00362
00363 if (RAND_MAX / 8 > rand ())
00364 {
00365
00366 deno = RAND_IN_RANGE (6000ULL);
00367 }
00368 else
00369 {
00370 gint64 norm = RAND_IN_RANGE (10ULL);
00371
00372
00373 deno = 1;
00374 while (norm)
00375 {
00376 deno *= 10;
00377 norm--;
00378 }
00379 }
00380
00381
00382
00383
00384 numer = get_random_gint64 () / 100000;
00385 if (0 == numer)
00386 numer = 1;
00387 return qof_numeric_create (numer, deno);
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 typedef enum
00453 {
00454 BY_STANDARD = 1,
00455 BY_DATE,
00456 BY_DATE_ENTERED,
00457 BY_DATE_RECONCILED,
00458 BY_NUM,
00459 BY_AMOUNT,
00460 BY_MEMO,
00461 BY_DESC,
00462 BY_NONE
00463 } sort_type_t;
00464
00465 typedef struct
00466 {
00467 QofIdType where;
00468 GSList *path;
00469 QofQuery *q;
00470 } KVPQueryData;
00471
00472 TestQueryTypes
00473 get_random_query_type (void)
00474 {
00475 switch (get_random_int_in_range (0, 4))
00476 {
00477 case 0:
00478 return SIMPLE_QT;
00479 case 4:
00480 return GUID_QT;
00481 default:
00482 return SIMPLE_QT;
00483 }
00484 }