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