From: Tim Janik Date: Tue, 20 Nov 2007 15:00:27 +0000 (+0000) Subject: Implemented g_test_rand*(). X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=e47c4253f9d83500c30f7b635b0b5da1300645ef;p=dana%2Fcg-glib.git Implemented g_test_rand*(). * gtestframework.h: fixed g_assert_cmp*() to evaluate arguments only once. added g_assert_cmpuint(). completed g_test_rand*() to cover bits, ints, doubles and ranges. * gtestframework.c: fixed "--seed" option and implemented g_test_rand*(). svn path=/trunk/; revision=5881 --- diff --git a/glib/gtestframework.c b/glib/gtestframework.c index 64225dab..86a73472 100644 --- a/glib/gtestframework.c +++ b/glib/gtestframework.c @@ -47,6 +47,7 @@ struct GTestSuite }; /* --- prototypes --- */ +static void test_run_seed (const gchar *rseed); static void test_trap_clear (void); /* --- variables --- */ @@ -59,7 +60,8 @@ static gboolean g_test_run_once = TRUE; static gboolean test_run_quiet = FALSE; static gboolean test_run_list = FALSE; static gchar *test_run_output = NULL; -static gchar *test_run_seed = NULL; +static gchar *test_run_seedstr = NULL; +static GRand *test_run_rand = NULL; static gchar *test_run_name = ""; static GSList *test_paths = NULL; static GTestSuite *test_suite_root = NULL; @@ -151,15 +153,15 @@ parse_args (gint *argc_p, test_run_list = TRUE; argv[i] = NULL; } - else if (strcmp ("-seed", argv[i]) == 0 || strncmp ("-seed=", argv[i], 6) == 0) + else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0) { - gchar *equal = argv[i] + 5; + gchar *equal = argv[i] + 6; if (*equal == '=') - test_run_seed = equal + 1; + test_run_seedstr = equal + 1; else if (i + 1 < argc) { argv[i++] = NULL; - test_run_seed = argv[i]; + test_run_seedstr = argv[i]; } argv[i] = NULL; } @@ -181,6 +183,7 @@ g_test_init (int *argc, char ***argv, ...) { + static char seedstr[4 + 4 * 8 + 1]; va_list args; gpointer vararg1; g_return_if_fail (argc != NULL); @@ -193,9 +196,92 @@ g_test_init (int *argc, va_end (args); g_return_if_fail (vararg1 == NULL); + /* setup random seed string */ + g_snprintf (seedstr, sizeof (seedstr), "R02S%08x%08x%08x%08x", g_random_int(), g_random_int(), g_random_int(), g_random_int()); + test_run_seedstr = seedstr; + + /* parse args, sets up mode, changes seed, etc. */ parse_args (argc, argv); + /* verify GRand reliability, needed for reliable seeds */ + if (1) + { + GRand *rg = g_rand_new_with_seed (0xc8c49fb6); + guint32 t1 = g_rand_int (rg), t2 = g_rand_int (rg), t3 = g_rand_int (rg), t4 = g_rand_int (rg); + // g_print ("GRand-current: 0x%x 0x%x 0x%x 0x%x\n", t1, t2, t3, t4); + if (t1 != 0xfab39f9b || t2 != 0xb948fb0e || t3 != 0x3d31be26 || t4 != 0x43a19d66) + g_warning ("random numbers are not GRand-2.2 compatible, seeds may be broken (check $G_RANDOM_VERSION)"); + g_rand_free (rg); + } + /* check rand seed */ + test_run_seed (test_run_seedstr); + if (test_run_seedstr == seedstr) + g_printerr ("NOTE: random-seed: %s\n", test_run_seedstr); +} + +static void +test_run_seed (const gchar *rseed) +{ + guint seed_failed = 0; + if (test_run_rand) + g_rand_free (test_run_rand); + test_run_rand = NULL; + while (strchr (" \t\v\r\n\f", *rseed)) + rseed++; + if (strncmp (rseed, "R02S", 4) == 0) // seed for random generator 02 (GRand-2.2) + { + const char *s = rseed + 4; + if (strlen (s) >= 32) // require 4 * 8 chars + { + guint32 seedarray[4]; + gchar *p, hexbuf[9] = { 0, }; + memcpy (hexbuf, s + 0, 8); + seedarray[0] = g_ascii_strtoull (hexbuf, &p, 16); + seed_failed += p != NULL && *p != 0; + memcpy (hexbuf, s + 8, 8); + seedarray[1] = g_ascii_strtoull (hexbuf, &p, 16); + seed_failed += p != NULL && *p != 0; + memcpy (hexbuf, s + 16, 8); + seedarray[2] = g_ascii_strtoull (hexbuf, &p, 16); + seed_failed += p != NULL && *p != 0; + memcpy (hexbuf, s + 24, 8); + seedarray[3] = g_ascii_strtoull (hexbuf, &p, 16); + seed_failed += p != NULL && *p != 0; + if (!seed_failed) + { + test_run_rand = g_rand_new_with_seed_array (seedarray, 4); + return; + } + } + } + g_error ("Unknown or invalid random seed: %s", rseed); +} + +gint32 +g_test_rand_int (void) +{ + return g_rand_int (test_run_rand); +} + +gint32 +g_test_rand_int_range (gint32 begin, + gint32 end) +{ + return g_rand_int_range (test_run_rand, begin, end); +} + +double +g_test_rand_double (void) +{ + return g_rand_double (test_run_rand); +} + +double +g_test_rand_double_range (double range_start, + double range_end) +{ + return g_rand_double_range (test_run_rand, range_start, range_end); } GTestSuite* @@ -284,6 +370,7 @@ test_case_run (GTestCase *tc) if (!test_run_quiet) g_print ("%s: ", test_run_name); void *fixture = g_malloc0 (tc->fixture_size); + test_run_seed (test_run_seedstr); if (tc->fixture_setup) tc->fixture_setup (fixture); tc->fixture_test (fixture); diff --git a/glib/gtestframework.h b/glib/gtestframework.h index 69687a99..beec33e3 100644 --- a/glib/gtestframework.h +++ b/glib/gtestframework.h @@ -27,18 +27,26 @@ typedef struct GTestCase GTestCase; typedef struct GTestSuite GTestSuite; /* assertion API */ -#define g_assert_cmpstr(s1, cmp, s2) do { if (g_strcmp0 (s1, s2) cmp 0) ; else \ - g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ - #s1 " " #cmp " " #s2, s1, #cmp, s2); } while (0) -#define g_assert_cmpint(n1, cmp, n2) do { if (n1 cmp n2) ; else \ - g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ - #n1 " " #cmp " " #n2, n1, #cmp, n2, 'i'); } while (0) -#define g_assert_cmphex(n1, cmp, n2) do { if (n1 cmp n2) ; else \ - g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ - #n1 " " #cmp " " #n2, n1, #cmp, n2, 'x'); } while (0) -#define g_assert_cmpfloat(n1,cmp,n2) do { if (n1 cmp n2) ; else \ - g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ - #n1 " " #cmp " " #n2, n1, #cmp, n2, 'f'); } while (0) +#define g_assert_cmpstr(s1, cmp, s2) do { const char *__s1 = (s1), *__s2 = (s2); \ + if (g_strcmp0 (__s1, __s2) cmp 0) ; else \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #s1 " " #cmp " " #s2, __s1, #cmp, __s2); } while (0) +#define g_assert_cmpint(n1, cmp, n2) do { gint64 __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'i'); } while (0) +#define g_assert_cmpuint(n1, cmp, n2) do { guint64 __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'i'); } while (0) +#define g_assert_cmphex(n1, cmp, n2) do { guint64 __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'x'); } while (0) +#define g_assert_cmpfloat(n1,cmp,n2) do { long double __n1 = (n1), __n2 = (n2); \ + if (__n1 cmp __n2) ; else \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #n1 " " #cmp " " #n2, __n1, #cmp, __n2, 'f'); } while (0) int g_strcmp0 (const char *str1, const char *str2); // g_assert(condition) /*...*/ @@ -95,7 +103,12 @@ gboolean g_test_trap_reached_timeout (void); #define g_test_trap_assert_stderr(serrpattern) g_test_trap_assertions (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, 0, 0, 0, serrpattern) /* provide seed-able random numbers for tests */ -double g_test_rand_range (double range_start, +#define g_test_rand_bit() (0 != (g_test_rand_int() & (1 << 15))) +gint32 g_test_rand_int (void); +gint32 g_test_rand_int_range (gint32 begin, + gint32 end); +double g_test_rand_double (void); +double g_test_rand_double_range (double range_start, double range_end); /* semi-internal API */