00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00130
00131
00132
00133
00134
00135
00136
00137
00138
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
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
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
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
00415 deno = RAND_IN_RANGE(6000ULL);
00416 }
00417 else
00418 {
00419 gint64 norm = RAND_IN_RANGE (10ULL);
00420
00421
00422 deno = 1;
00423 while (norm)
00424 {
00425 deno *= 10;
00426 norm --;
00427 }
00428 }
00429
00430
00431
00432
00433 numer = get_random_gint64()/100000;
00434 if (0 == numer) numer = 1;
00435 return gnc_numeric_create(numer, deno);
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
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 }