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 #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
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
00130
00131
00132
00133
00134
00135
00136
00137
00138
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
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
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
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
00419 deno = RAND_IN_RANGE (6000ULL);
00420 }
00421 else
00422 {
00423 gint64 norm = RAND_IN_RANGE (10ULL);
00424
00425
00426 deno = 1;
00427 while (norm)
00428 {
00429 deno *= 10;
00430 norm--;
00431 }
00432 }
00433
00434
00435
00436
00437 numer = get_random_gint64 () / 100000;
00438 if (0 == numer)
00439 numer = 1;
00440 return qof_numeric_create (numer, deno);
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
00500
00501
00502
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 }