1
2 #include <glib.h>
3 #include <gio/gio.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 #include "../src/ctpl.h"
9 #include "ctpl-test-lib.h"
10
11
12 /*
13 * FIXME: support exponents in input/output values
14 */
15
16
17 /*#define LOGFILE stdout*/
18
19
20 /* creates a string representing a "float" from two longs: m.n */
21 static gchar *
float_string(glong m,glong d)22 float_string (glong m,
23 glong d)
24 {
25 gchar *f;
26 gchar *p;
27
28 g_return_val_if_fail (d >= 0 || m == 0, NULL);
29
30 if (m == 0) {
31 if (d >= 0) {
32 f = g_strdup_printf ("0.%ld", d);
33 } else {
34 f = g_strdup_printf ("-0.%ld", -d);
35 }
36 } else {
37 f = g_strdup_printf ("%ld.%ld", m, d);
38 }
39 /* now strip extra 0's */
40 for (p = strchr (f, 0) - 1; p[0] == '0' && p[-1] != '.'; p--) {
41 p[0] = 0;
42 }
43
44 return f;
45 }
46
47 /* strips @sfx from the end of @s */
48 static void
rstripstr(gchar * s,const gchar * sfx)49 rstripstr (gchar *s,
50 const gchar *sfx)
51 {
52 gsize s_len = strlen (s);
53 gsize sfx_len = strlen (sfx);
54
55 if (s_len > sfx_len) {
56 if (strcmp (&s[s_len - sfx_len], sfx) == 0) {
57 s[s_len - sfx_len] = 0;
58 }
59 }
60 }
61
62 /* actual test that check if the float represented by float_string(m, d) is
63 * output as the same string by CTPL */
64 static gboolean
test_float(glong m,glong d)65 test_float (glong m,
66 glong d)
67 {
68 gchar *ctpl_f;
69 gchar *real_f;
70 gboolean ret = FALSE;
71 gchar *env;
72 GError *err = NULL;
73
74 real_f = float_string (m, d);
75 env = g_strconcat ("float = ", real_f, ";", NULL);
76 ctpl_f = ctpltest_parse_string ("{float}", env, &err);
77 if (! ctpl_f) {
78 g_warning ("Failed to parse test template: %s", err->message);
79 g_error_free (err);
80 } else {
81 /* strip extra .0 if present */
82 rstripstr (real_f, ".0");
83 ret = strcmp (real_f, ctpl_f) == 0;
84
85 if (! ret) {
86 fprintf (stderr, "** %s expected, got %s\n", real_f, ctpl_f);
87 }
88 #ifdef LOGFILE
89 {
90 static glong n = 0;
91
92 if (n == 100000) {
93 fprintf (LOGFILE, "%s =\n%s\n", real_f, ctpl_f);
94 n = 0;
95 } else {
96 n++;
97 }
98 }
99 #endif
100 }
101 g_free (env);
102 g_free (ctpl_f);
103 g_free (real_f);
104
105 return ret;
106 }
107
108
109 /* test cases.
110 * try not to make checks take too much time if they get activated by default,
111 * so anyone can run this safely. */
112
113 #define PERCENT(max, n) \
114 (((max) == 0) ? (0.0) : (100.0 * (n) / (max)))
115
116 /* test many really small (-1.0, +1.0) values */
117 static int
test_1(void)118 test_1 (void)
119 {
120 glong m;
121 glong d;
122 int ret = 0;
123
124 #define M_MIN -1
125 #define M_MAX +1
126 #define M_STEP 1
127 #define D_MIN 0
128 #define D_MAX +10000000
129 #define D_STEP 1111
130
131 for (m = M_MIN; m < M_MAX; m += M_STEP) {
132 for (d = D_MIN; d < D_MAX; d += D_STEP) {
133 if (! test_float (m, d)) {
134 ret = 1;
135 }
136 }
137 }
138
139 return ret;
140 }
141
142 /* test on random values (but relatively small) */
143 static int
test_2(void)144 test_2 (void)
145 {
146 guint i;
147 guint n_success = 0;
148
149 for (i = 0; i < 100000; i++) {
150 if (test_float (g_random_int_range (-100000, 100000),
151 g_random_int_range (0, 999999999))) {
152 n_success ++;
153 }
154 }
155 g_debug ("%d/%d tests suceeded (%.2f%%)",
156 n_success, i, PERCENT (i, n_success));
157
158 return n_success == i ? 0 : 1;
159 }
160
161 int
main(void)162 main (void)
163 {
164 g_type_init ();
165
166 return (test_1 () +
167 test_2 ());
168 }
169
170