mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bugs#308554, 334811: Add basic validation and test-cases for invalid expressions.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@13715 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
a4952b7cae
commit
6dbc113082
@ -13,6 +13,11 @@
|
|||||||
|
|
||||||
2006-03-30 Joshua Sled <jsled@asynchronous.org>
|
2006-03-30 Joshua Sled <jsled@asynchronous.org>
|
||||||
|
|
||||||
|
* src/calculation/expression_parser.c (primary_exp):
|
||||||
|
* src/app-utils/test/test-exp-parser.c (test_parser): Add basic
|
||||||
|
validation and test-cases for invalid expressions. Bugs#308554,
|
||||||
|
334811.
|
||||||
|
|
||||||
* accounts/C/acctchrt_checkbook.gnucash-xea: Revoke placeholder
|
* accounts/C/acctchrt_checkbook.gnucash-xea: Revoke placeholder
|
||||||
status from leaf Expense account in Simple Checkbook account
|
status from leaf Expense account in Simple Checkbook account
|
||||||
tree. Bug#334777.
|
tree. Bug#334777.
|
||||||
|
@ -14,18 +14,18 @@ static GList *tests = NULL;
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char * test_name;
|
const char * test_name;
|
||||||
|
|
||||||
const char * exp;
|
const char * exp;
|
||||||
|
|
||||||
gboolean should_succeed;
|
gboolean should_succeed;
|
||||||
|
|
||||||
gnc_numeric expected_result;
|
gnc_numeric expected_result;
|
||||||
|
|
||||||
int expected_error_offset;
|
int expected_error_offset;
|
||||||
|
const char * file;
|
||||||
|
int line;
|
||||||
} TestNode;
|
} TestNode;
|
||||||
|
|
||||||
|
#define add_pass_test(n, e, r) _add_pass_test((n), (e), (r), __FILE__, __LINE__)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_pass_test (const char *test_name, const char *exp, gnc_numeric result)
|
_add_pass_test (const char *test_name, const char *exp, gnc_numeric result, char *file, int line)
|
||||||
{
|
{
|
||||||
TestNode *node = g_new0 (TestNode, 1);
|
TestNode *node = g_new0 (TestNode, 1);
|
||||||
|
|
||||||
@ -33,13 +33,16 @@ add_pass_test (const char *test_name, const char *exp, gnc_numeric result)
|
|||||||
node->exp = exp ? exp : test_name;
|
node->exp = exp ? exp : test_name;
|
||||||
node->should_succeed = TRUE;
|
node->should_succeed = TRUE;
|
||||||
node->expected_result = result;
|
node->expected_result = result;
|
||||||
|
node->file = file;
|
||||||
|
node->line = line;
|
||||||
|
|
||||||
tests = g_list_append (tests, node);
|
tests = g_list_append (tests, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define add_fail_test(n,e,o) _add_fail_test((n), (e), (o), __FILE__, __LINE__)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_fail_test (const char *test_name, const char *exp,
|
_add_fail_test (const char *test_name, const char *exp, int expected_error_offset, char *file, int line)
|
||||||
int expected_error_offset)
|
|
||||||
{
|
{
|
||||||
TestNode *node = g_new0 (TestNode, 1);
|
TestNode *node = g_new0 (TestNode, 1);
|
||||||
|
|
||||||
@ -47,6 +50,8 @@ add_fail_test (const char *test_name, const char *exp,
|
|||||||
node->exp = exp;
|
node->exp = exp;
|
||||||
node->should_succeed = FALSE;
|
node->should_succeed = FALSE;
|
||||||
node->expected_error_offset = expected_error_offset;
|
node->expected_error_offset = expected_error_offset;
|
||||||
|
node->file = file;
|
||||||
|
node->line = line;
|
||||||
|
|
||||||
tests = g_list_append (tests, node);
|
tests = g_list_append (tests, node);
|
||||||
}
|
}
|
||||||
@ -59,7 +64,7 @@ run_parser_test (TestNode *node)
|
|||||||
char *error_loc;
|
char *error_loc;
|
||||||
|
|
||||||
result = gnc_numeric_error( -1 );
|
result = gnc_numeric_error( -1 );
|
||||||
printf( "Running test \"%s\" = ", node->test_name );
|
printf("Running test \"%s\" [%s] = ", node->test_name, node->exp);
|
||||||
succeeded = gnc_exp_parser_parse (node->exp, &result, &error_loc);
|
succeeded = gnc_exp_parser_parse (node->exp, &result, &error_loc);
|
||||||
{
|
{
|
||||||
int pass;
|
int pass;
|
||||||
@ -74,7 +79,7 @@ run_parser_test (TestNode *node)
|
|||||||
|
|
||||||
if (succeeded != node->should_succeed)
|
if (succeeded != node->should_succeed)
|
||||||
{
|
{
|
||||||
failure_args (node->test_name, __FILE__, __LINE__,
|
failure_args (node->test_name, node->file, node->line,
|
||||||
"parser %s on \"%s\"",
|
"parser %s on \"%s\"",
|
||||||
succeeded ? "succeeded" : "failed",
|
succeeded ? "succeeded" : "failed",
|
||||||
node->exp);
|
node->exp);
|
||||||
@ -85,7 +90,7 @@ run_parser_test (TestNode *node)
|
|||||||
{
|
{
|
||||||
if (!gnc_numeric_equal (result, node->expected_result))
|
if (!gnc_numeric_equal (result, node->expected_result))
|
||||||
{
|
{
|
||||||
failure_args (node->test_name, __FILE__, __LINE__, "wrong result");
|
failure_args (node->test_name, node->file, node->line, "wrong result");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +98,8 @@ run_parser_test (TestNode *node)
|
|||||||
{
|
{
|
||||||
if (error_loc != node->exp + node->expected_error_offset)
|
if (error_loc != node->exp + node->expected_error_offset)
|
||||||
{
|
{
|
||||||
failure_args (node->test_name, __FILE__, __LINE__, "wrong offset");
|
failure_args (node->test_name, node->file, node->line, "wrong offset; expected %d, got %d",
|
||||||
|
node->expected_error_offset, (error_loc - node->exp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,8 +127,11 @@ test_parser (void)
|
|||||||
add_fail_test ("whitespace", " \t\n", 4);
|
add_fail_test ("whitespace", " \t\n", 4);
|
||||||
add_fail_test ("bad expression", "\\", 0);
|
add_fail_test ("bad expression", "\\", 0);
|
||||||
add_fail_test ("bad expression", "1 +", 3);
|
add_fail_test ("bad expression", "1 +", 3);
|
||||||
/* FIXME: This should be a failure test... */
|
/* Bug#334811 - http://bugzilla.gnome.org/show_bug.cgi?id=334811 */
|
||||||
//add_fail_test ("bad expression", "1 2", 2);
|
add_fail_test ("bad expression", "1 2", 3);
|
||||||
|
/* Bug#308554 - http://bugzilla.gnome.org/show_bug.cgi?id=308554 */
|
||||||
|
add_fail_test ("bad expression", "1 ç", 2);
|
||||||
|
add_fail_test ("bad expression", "1 asdf", 6);
|
||||||
add_fail_test ("bad expression", " (5 + 23)/ ", 14);
|
add_fail_test ("bad expression", " (5 + 23)/ ", 14);
|
||||||
add_fail_test ("bad expression", " ((((5 + 23)/ ", 17);
|
add_fail_test ("bad expression", " ((((5 + 23)/ ", 17);
|
||||||
add_fail_test ("divide by zero", " 4 / (1 - 1)", -1);
|
add_fail_test ("divide by zero", " 4 / (1 - 1)", -1);
|
||||||
@ -150,6 +159,7 @@ test_parser (void)
|
|||||||
"- 42.72 + 13.32 + 15.48 + 23.4 + 115.4",
|
"- 42.72 + 13.32 + 15.48 + 23.4 + 115.4",
|
||||||
gnc_numeric_create(35897, 100) );
|
gnc_numeric_create(35897, 100) );
|
||||||
|
|
||||||
|
// This must be defined for the function-parsing to work.
|
||||||
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)))");
|
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)))");
|
||||||
|
|
||||||
scm_c_eval_string( "(define (gnc:plus a b) (+ a b))" );
|
scm_c_eval_string( "(define (gnc:plus a b) (+ a b))" );
|
||||||
|
@ -1136,6 +1136,16 @@ primary_exp (parser_env_ptr pe)
|
|||||||
if (pe->error_code)
|
if (pe->error_code)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Bug#334811, 308554: apply some basic grammar constraints.
|
||||||
|
if (pe->Token == VAR_TOKEN
|
||||||
|
|| pe->Token == STR_TOKEN
|
||||||
|
|| pe->Token == NUM_TOKEN)
|
||||||
|
{
|
||||||
|
add_token(pe, EOS);
|
||||||
|
pe->error_code = EXPRESSION_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rslt->value = pe->numeric_value;
|
rslt->value = pe->numeric_value;
|
||||||
pe->numeric_value = NULL;
|
pe->numeric_value = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -48,6 +48,7 @@ typedef enum
|
|||||||
NOT_A_FUNC,
|
NOT_A_FUNC,
|
||||||
PARSER_OUT_OF_MEMORY,
|
PARSER_OUT_OF_MEMORY,
|
||||||
NUMERIC_ERROR,
|
NUMERIC_ERROR,
|
||||||
|
EXPRESSION_ERROR,
|
||||||
PARSER_NUM_ERRORS
|
PARSER_NUM_ERRORS
|
||||||
}
|
}
|
||||||
ParseError;
|
ParseError;
|
||||||
|
Loading…
Reference in New Issue
Block a user