7 #include "gnc-exp-parser.h"
9 #include "test-stuff.h"
10 #include <unittest-support.h>
12 static GList *tests = NULL;
16 const char * test_name;
18 gboolean should_succeed;
20 int expected_error_offset;
25 #define add_pass_test(n, e, r) _add_pass_test((n), (e), (r), __FILE__, __LINE__)
28 _add_pass_test (
const char *test_name,
const char *exp,
gnc_numeric result,
char *file,
int line)
32 node->test_name = test_name;
33 node->exp = exp ? exp : test_name;
34 node->should_succeed = TRUE;
35 node->expected_result = result;
39 tests = g_list_append (tests, node);
43 #define add_fail_test(n,e,o) _add_fail_test((n), (e), (o), __FILE__, __LINE__)
46 _add_fail_test (
const char *test_name,
const char *exp,
int expected_error_offset,
char *file,
int line)
50 node->test_name = test_name;
51 node->exp = exp ? exp : test_name;
52 node->should_succeed = FALSE;
53 node->expected_error_offset = expected_error_offset;
57 tests = g_list_append (tests, node);
66 gchar *msg =
"[func_op()] function eval error: [[func_op(]\n";
67 guint loglevel = G_LOG_LEVEL_CRITICAL, hdlr;
71 hdlr = g_log_set_handler (
"gnc.gui", loglevel,
72 (GLogFunc)test_checked_handler, &check);
73 g_test_message (
"Running test \"%s\" [%s] = ", node->test_name, node->exp);
74 succeeded = gnc_exp_parser_parse (node->exp, &result, &error_loc);
75 g_log_remove_handler (
"gnc.gui", hdlr);
78 pass = (succeeded == node->should_succeed);
79 if ( pass && node->should_succeed )
83 g_test_message (
"%0.4f [%s]\n",
85 (pass ?
"PASS" :
"FAIL" ) );
88 if (succeeded != node->should_succeed)
90 failure_args (node->test_name, node->file, node->line,
91 "parser %s on \"%s\"",
92 succeeded ?
"succeeded" :
"failed",
101 failure_args (node->test_name, node->file, node->line,
"wrong result");
105 else if (node->expected_error_offset != -1)
107 if (error_loc != node->exp + node->expected_error_offset)
109 failure_args (node->test_name, node->file, node->line,
"wrong offset; expected %d, got %d",
110 node->expected_error_offset, (error_loc - node->exp));
115 success (node->test_name);
119 run_parser_tests (
void)
123 for (node = tests; node; node = node->next)
124 run_parser_test (node->data);
130 gnc_exp_parser_init ();
131 success (
"initialize expression parser");
133 add_fail_test (
"null expression", NULL, -1);
134 add_fail_test (
"empty expression",
"", 0);
135 add_fail_test (
"whitespace",
" \t\n", 4);
136 add_fail_test (
"bad expression",
"\\", 0);
137 add_fail_test (
"bad expression",
"1 +", 3);
139 add_fail_test (
"bad expression",
"1 2", 3);
141 add_fail_test (
"bad expression",
"1 ç", 2);
142 add_fail_test (
"bad expression",
"ç 1", 0);
143 add_fail_test (
"bad expression",
"1 asdf", 6);
144 add_fail_test (
"bad expression",
"asdf 1", 6);
145 add_fail_test (
"bad expression",
"asdf jkl", 8);
146 add_fail_test (
"bad expression",
" (5 + 23)/ ", 14);
147 add_fail_test (
"bad expression",
" ((((5 + 23)/ ", 17);
148 add_fail_test (
"divide by zero",
" 4 / (1 - 1)", -1);
150 add_pass_test (
"zero",
"0", gnc_numeric_zero ());
151 add_pass_test (
"zero with whitespace",
"\n\t 0 ", gnc_numeric_zero ());
152 add_pass_test (
"1 + 2", NULL, gnc_numeric_create (3, 1));
153 add_pass_test (
"17.3 - 12.3000", NULL, gnc_numeric_create (5, 1));
154 add_pass_test (
"5 * 6", NULL, gnc_numeric_create (30, 1));
155 add_pass_test (
" 34 / (22) ", NULL, gnc_numeric_create (34, 22));
156 add_pass_test (
" (4 + 5 * 2) - 7 / 3", NULL, gnc_numeric_create (35, 3));
157 add_pass_test(
"(a = 42) + (b = 12) - a", NULL, gnc_numeric_create( 12, 1 ) );
158 add_fail_test(
"AUD $1.23", NULL, 4);
159 add_fail_test(
"AUD $0.0", NULL, 4);
160 add_fail_test(
"AUD 1.23", NULL, 8);
161 add_fail_test(
"AUD 0.0", NULL, 7);
162 add_fail_test(
"AUD 1.2 + CAN 2.3", NULL, 7);
163 add_fail_test(
"AUD $1.2 + CAN $2.3", NULL, 4);
165 add_pass_test(
"1 + 2 * 3 + 4 + 5 * 6 * 7", NULL, gnc_numeric_create(221, 1) );
166 add_pass_test(
"1 - 2 * 3 + 4 - 5 * 6 * 7", NULL, gnc_numeric_create(-211, 1) );
167 add_pass_test(
"Conrad's bug",
168 "22.32 * 2 + 16.8 + 34.2 * 2 + 18.81 + 85.44"
169 "- 42.72 + 13.32 + 15.48 + 23.4 + 115.4",
170 gnc_numeric_create(35897, 100) );
173 scm_c_eval_string(
"(define (gnc:error->string tag args) (define (write-error port) (if (and (list? args) (not (null? args))) (let ((func (car args))) (if func (begin (display \"Function: \" port) (display func port) (display \", \" port) (display tag port) (display \"\n\n\" port))))) (false-if-exception (apply display-error (fluid-ref the-last-stack) port args)) (display-backtrace (fluid-ref the-last-stack) port) (force-output port)) (false-if-exception (call-with-output-string write-error)))");
175 scm_c_eval_string(
"(define (gnc:plus a b) (+ a b))" );
176 add_pass_test(
"plus(2 : 1)", NULL, gnc_numeric_create(3, 1));
177 add_fail_test(
"plus(1:2) plus(3:4)", NULL, 15);
178 add_pass_test(
"plus( 1 : 2 ) + 3", NULL, gnc_numeric_create( 6, 1 ) );
179 add_pass_test(
"plus( 1 : 2 ) * 3", NULL, gnc_numeric_create( 9, 1 ) );
180 add_pass_test(
"plus( 1 + 2 : 3 ) * 5", NULL, gnc_numeric_create( 30, 1 ) );
181 add_pass_test(
"plus( ( 1 + 2 ) * 3 : 4 ) + 5", NULL, gnc_numeric_create( 18, 1) );
182 add_pass_test(
"5 + plus( ( 1 + 2 ) * 3 : 4 )", NULL, gnc_numeric_create( 18, 1) );
183 add_pass_test(
"plus( plus( 1 : 2 ) : 3 )", NULL, gnc_numeric_create( 6, 1 ) );
184 add_pass_test(
"plus( 4 : plus( plus( 1 : 2 ) : 3))", NULL, gnc_numeric_create( 10, 1 ) );
186 scm_c_eval_string(
"(define (gnc:sub a b) (- a b))" );
187 add_pass_test(
"sub( 1 : 2 ) + 4", NULL, gnc_numeric_create( 3, 1 ) );
189 add_pass_test(
"sub( (1 + 2 * 3) : 4 ) + 5",
190 NULL, gnc_numeric_create( 8, 1 ) );
191 add_pass_test(
"sub( 1 : 2 ) + sub( 3 : 4 ) + 5",
192 NULL, gnc_numeric_create( 3, 1 ) );
193 add_pass_test(
"sub( a = 42 : sub( plus( 1 : 2 ) : 6 * 7 )) + a",
194 NULL, gnc_numeric_create( 123, 1 ) );
196 scm_c_eval_string(
"(define (gnc:test_str str b)"
197 " (+ b (cond ((equal? str \"one\") 1)"
198 " ((equal? str \"two\") 2)"
199 " ((equal? str \"three\") 3)"
201 add_pass_test(
"test_str( \"one\" : 1 )", NULL, gnc_numeric_create( 2, 1 ) );
202 add_pass_test(
"test_str( \"two\" : 2 )", NULL, gnc_numeric_create( 4, 1 ) );
203 add_fail_test(
"test_str( 3 : \"three\" )", NULL, 23 );
204 add_pass_test(
"test_str( \"asdf\" : 1 )", NULL, gnc_numeric_create( 1, 1 ) );
205 add_fail_test(
"\"asdf\" + 0", NULL, 8);
207 scm_c_eval_string(
"(define (gnc:blindreturn val) val)" );
208 add_pass_test(
"blindreturn( 123.1 )", NULL, gnc_numeric_create( 1231, 10 ) );
209 add_pass_test(
"blindreturn( 123.01 )", NULL, gnc_numeric_create( 12301, 100 ) );
210 add_pass_test(
"blindreturn( 123.001 )", NULL, gnc_numeric_create( 123001, 1000 ) );
214 gnc_exp_parser_shutdown ();
215 success (
"shutdown expression parser");
219 test_variable_expressions()
222 gchar *errLoc = NULL;
223 GHashTable *vars = g_hash_table_new(g_str_hash, g_str_equal);
224 do_test(gnc_exp_parser_parse_separate_vars(
"123 + a", &num, &errLoc, vars),
"parsing");
225 do_test(g_hash_table_size(vars) == 1,
"'a' is the variable; good job, gnc-exp-parser!");
226 success(
"variable found");
230 real_main (
void *closure,
int argc,
char **argv)
234 test_variable_expressions();
235 print_test_results();
239 int main (
int argc,
char **argv )
242 scm_boot_guile( argc, argv, real_main, NULL );
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
An exact-rational-number library for gnucash. (to be renamed qofnumeric.h in libqof2) ...
gdouble gnc_numeric_to_double(gnc_numeric n)
gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code)