Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
hammer
Manage
Activity
Members
Labels
Plan
Issues
80
Issue boards
Milestones
Wiki
Code
Merge requests
7
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Hammer
hammer
Compare revisions
0813b6995d344af14f8f2e7ed5042f30f99cdfd6 to master
Compare revisions
Changes are shown as if the
source
revision was being merged into the
target
revision.
Learn more about comparing revisions.
Source
hammer/hammer
Select target project
No results found
master
Select Git revision
Swap
Target
vyrus001/hammer
Select target project
hammer/hammer
mlp/hammer
xentrac/hammer
pesco/hammer
letitiali/hammer
nobody/hammer
kia/hammer-sandbox
vyrus001/hammer
denleylam/hammer
9 results
0813b6995d344af14f8f2e7ed5042f30f99cdfd6
Select Git revision
Show changes
Only incoming changes from source
Include changes to target since source was created
Compare
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/t_regression.c
+383
-1
383 additions, 1 deletion
src/t_regression.c
src/test_suite.c
+2
-0
2 additions, 0 deletions
src/test_suite.c
src/test_suite.h
+213
-42
213 additions, 42 deletions
src/test_suite.h
with
598 additions
and
43 deletions
src/t_regression.c
View file @
5b4ea546
#include
<glib.h>
#include
<stdint.h>
#include
<stdlib.h>
#include
"glue.h"
#include
"hammer.h"
#include
"test_suite.h"
...
...
@@ -187,7 +188,7 @@ static void test_charset_bits(void) {
.
free
=
NULL
,
};
test_charset_bits__buf
[
32
]
=
0xAB
;
HCharset
cs
=
new_charset
(
&
alloc
);
new_charset
(
&
alloc
);
for
(
size_t
i
=
0
;
i
<
32
;
i
++
)
g_check_cmp_uint32
(
test_charset_bits__buf
[
i
],
==
,
0
);
g_check_cmp_uint32
(
test_charset_bits__buf
[
32
],
==
,
0xAB
);
...
...
@@ -270,6 +271,378 @@ static void test_bug_19() {
g_assert_true
(
1
);
}
static
void
test_flatten_null
()
{
// h_act_flatten() produces a flat sequence from a nested sequence. it also
// hapens to produce a one-element sequence when given a non-sequence token.
// but given a null token (as from h_epsilon_p() or h_ignore()), it would
// previously segfault.
//
// let's make sure the behavior is consistent and a singular null token
// produces the same thing as a sequence around h_epsilon_p() or h_ignore().
HParser
*
A
=
h_many
(
h_ch
(
'a'
));
HParser
*
B
=
h_ch
(
'b'
);
HParser
*
C
=
h_sequence
(
h_ch
(
'c'
),
NULL
);
HParser
*
V
=
h_action
(
h_epsilon_p
(),
h_act_flatten
,
NULL
);
HParser
*
W
=
h_action
(
B
,
h_act_flatten
,
NULL
);
HParser
*
X
=
h_action
(
h_sequence
(
h_ignore
(
A
),
NULL
),
h_act_flatten
,
NULL
);
HParser
*
Y
=
h_action
(
h_sequence
(
h_epsilon_p
(),
NULL
),
h_act_flatten
,
NULL
);
HParser
*
Z
=
h_action
(
h_sequence
(
A
,
B
,
C
,
NULL
),
h_act_flatten
,
NULL
);
g_check_parse_match
(
V
,
PB_PACKRAT
,
""
,
0
,
"()"
);
g_check_parse_match
(
W
,
PB_PACKRAT
,
"b"
,
1
,
"(u0x62)"
);
g_check_parse_match
(
X
,
PB_PACKRAT
,
""
,
0
,
"()"
);
g_check_parse_match
(
Y
,
PB_PACKRAT
,
""
,
0
,
"()"
);
g_check_parse_match
(
Z
,
PB_PACKRAT
,
"aabc"
,
4
,
"(u0x61 u0x61 u0x62 u0x63)"
);
#if 0 // XXX ast->bit_length and ast->index are currently not set
// let's also check that position and length info get attached correctly...
HParseResult *p = h_parse(h_sequence(A,V,B, NULL), (uint8_t *)"aaab", 4);
// top-level token
assert(p != NULL);
assert(p->ast != NULL);
g_check_cmp_int64(p->bit_length, ==, 32);
g_check_cmp_size(p->ast->bit_length, ==, 32);
g_check_cmp_size(p->ast->index, ==, 0);
g_check_cmp_int((int)p->ast->bit_offset, ==, 0);
// the empty sequence
HParsedToken *tok = H_INDEX_TOKEN(p->ast, 1);
assert(tok != NULL);
assert(tok->token_type == TT_SEQUENCE);
assert(tok->seq->used == 0);
g_check_cmp_size(tok->bit_length, ==, 0);
g_check_cmp_size(tok->index, ==, 2);
g_check_cmp_int((int)tok->bit_offset, ==, 0);
#endif // 0
}
#if 0 // XXX ast->bit_length and ast->index are currently not set
static void test_ast_length_index() {
HParser *A = h_many(h_ch('a'));
HParser *B = h_ch('b');
HParser *C = h_sequence(h_ch('c'), NULL);
const uint8_t input[] = "aabc";
size_t len = sizeof input - 1; // sans null
HParseResult *p = h_parse(h_sequence(A,B,C, NULL), input, len);
assert(p != NULL);
assert(p->ast != NULL);
// top-level token
g_check_cmp_int64(p->bit_length, ==, (int64_t)(8 * len));
g_check_cmp_size(p->ast->bit_length, ==, 8 * len);
g_check_cmp_size(p->ast->index, ==, 0);
HParsedToken *tok;
// "aa"
tok = H_INDEX_TOKEN(p->ast, 0);
g_check_cmp_size(tok->bit_length, ==, 16);
g_check_cmp_size(tok->index, ==, 0);
// "a", "a"
tok = H_INDEX_TOKEN(p->ast, 0, 0);
g_check_cmp_size(tok->bit_length, ==, 8);
g_check_cmp_size(tok->index, ==, 0);
tok = H_INDEX_TOKEN(p->ast, 0, 1);
g_check_cmp_size(tok->bit_length, ==, 8);
g_check_cmp_size(tok->index, ==, 1);
// "b"
tok = H_INDEX_TOKEN(p->ast, 1);
g_check_cmp_size(tok->bit_length, ==, 8);
g_check_cmp_size(tok->index, ==, 2);
// "c"
tok = H_INDEX_TOKEN(p->ast, 2);
g_check_cmp_size(tok->bit_length, ==, 8);
g_check_cmp_size(tok->index, ==, 3);
tok = H_INDEX_TOKEN(p->ast, 2, 0);
g_check_cmp_size(tok->bit_length, ==, 8);
g_check_cmp_size(tok->index, ==, 3);
}
#endif // 0
static
void
test_issue91
()
{
// this ambiguous grammar caused intermittent (?) assertion failures when
// trying to compile with the LALR backend:
//
// assertion "action->type == HLR_SHIFT" failed: file "src/backends/lalr.c",
// line 34, function "follow_transition"
//
// cf. https://gitlab.special-circumstanc.es/hammer/hammer/issues/91
H_RULE
(
schar
,
h_ch_range
(
' '
,
'~'
));
/* overlaps digit */
H_RULE
(
digit
,
h_ch_range
(
'0'
,
'9'
));
H_RULE
(
digits
,
h_choice
(
h_repeat_n
(
digit
,
2
),
digit
,
NULL
));
H_RULE
(
p
,
h_many
(
h_choice
(
schar
,
digits
,
NULL
)));
int
r
=
h_compile
(
p
,
PB_LALR
,
NULL
);
g_check_cmp_int
(
r
,
==
,
-
2
);
}
// a different instance of issue 91
static
void
test_issue87
()
{
HParser
*
a
=
h_ch
(
'a'
);
HParser
*
a2
=
h_ch_range
(
'a'
,
'a'
);
HParser
*
p
=
h_many
(
h_many
(
h_choice
(
a
,
a2
,
NULL
)));
int
r
=
h_compile
(
p
,
PB_LALR
,
NULL
);
g_check_cmp_int
(
r
,
==
,
-
2
);
}
static
void
test_issue92
()
{
HParser
*
a
=
h_ch
(
'a'
);
HParser
*
b
=
h_ch
(
'b'
);
HParser
*
str_a
=
h_indirect
();
HParser
*
str_b
=
h_choice
(
h_sequence
(
b
,
str_a
,
NULL
),
str_a
,
NULL
);
//h_sequence(h_optional(b), str_a, NULL); // this works
HParser
*
str_a_
=
h_optional
(
h_sequence
(
a
,
str_b
,
NULL
));
HParser
*
str
=
str_a
;
h_bind_indirect
(
str_a
,
str_a_
);
/*
* grammar generated from the above:
*
* A -> B -- "augmented" with a fresh start symbol
* B -> C -- B = str_a
* | ""
* C -> "a" D -- C = h_sequence(a, str_b)
* D -> E -- D = str_b
* | B
* E -> "b" B -- E = h_sequence(b, str_a)
*
* transformed to the following "enhanced grammar":
*
* S -> 0B3
* 0B3 -> 0C2
* | ""
* 1B4 -> 1C2
* | ""
* 6B8 -> 6C2
* | "" (*) here
* 0C2 -> "a" 1D7
* 1C2 -> "a" 1D7
* 6C2 -> "a" 1D7
* 1D7 -> 1E5
* | 1B4
* 1E5 -> "b" 6B8
*/
/*
* the following call would cause an assertion failure.
*
* assertion "!h_stringmap_empty(fs)" failed: file
* "src/backends/lalr.c", line 341, function "h_lalr_compile"
*
* the bug happens when trying to compute h_follow() for 6B8 in state 6,
* production "" (*). intermediate results could end up in the memoization
* table and be treated as final by later calls to h_follow(). the problem
* could appear or not depending on the order of nonterminals (i.e. pointers)
* in a hashtable.
*/
int
r
=
h_compile
(
str
,
PB_LALR
,
NULL
);
g_check_cmp_int
(
r
,
==
,
0
);
}
static
void
test_issue83
()
{
HParser
*
p
=
h_sequence
(
h_sequence
(
NULL
,
NULL
),
h_nothing_p
(),
NULL
);
/*
* A -> B
* B -> C D
* C -> ""
* D -x
*
* (S) -> 0B1
* 0B1 -> 0C2 2D3
* 0C2 -> "" (*) h_follow()
* 2D3 -x
*/
/*
* similar to issue 91, this would cause the same assertion failure, but for
* a different reason. the follow set of 0C2 above is equal to the first set
* of 2D3, but 2D3 is an empty choice. The first set of an empty choice
* is legitimately empty. the asserting in h_lalr_compile() missed this case.
*/
int
r
=
h_compile
(
p
,
PB_LALR
,
NULL
);
g_check_cmp_int
(
r
,
==
,
0
);
}
/*
* This is Meg's cut-down bug 60 test case
*/
static
void
test_bug60
()
{
/* There is probably an even smaller example that shows the issue */
HParser
*
zed
=
NULL
;
HParser
*
alpha
=
NULL
;
HParser
*
vchar
=
NULL
;
HParser
*
why
=
NULL
;
HParser
*
plural_zed
=
NULL
;
HParser
*
plural_zed_zed
=
NULL
;
HParser
*
a_to_zed
=
NULL
;
HParser
*
alphas
=
NULL
;
HParser
*
rule
=
NULL
;
HParser
*
rulelist
=
NULL
;
HParser
*
p
=
NULL
;
HParseResult
*
r
=
NULL
;
int
n
;
zed
=
h_ch
(
'z'
);
vchar
=
h_ch_range
(
0x79
,
0x7a
);
/* allows y and z */
alpha
=
h_ch
(
'a'
);
why
=
h_ch
(
'y'
);
plural_zed
=
h_sequence
(
why
,
h_many
(
h_choice
(
alpha
,
vchar
,
NULL
)),
NULL
);
plural_zed_zed
=
h_choice
(
plural_zed
,
zed
,
NULL
);
alphas
=
h_choice
(
alpha
,
h_sequence
(
plural_zed_zed
,
alpha
,
NULL
),
NULL
);
a_to_zed
=
h_sequence
(
zed
,
h_many
(
h_sequence
(
h_many1
(
alphas
),
zed
,
NULL
)),
NULL
);
rule
=
h_sequence
(
a_to_zed
,
plural_zed_zed
,
NULL
);
rulelist
=
h_many1
(
h_choice
(
rule
,
h_sequence
(
h_many
(
alphas
),
plural_zed_zed
,
NULL
),
NULL
));
p
=
rulelist
;
g_check_parse_ok
(
p
,
PB_GLR
,
"ayzza"
,
5
);
g_check_parse_match
(
p
,
PB_GLR
,
"ayzza"
,
5
,
"(((u0x61) (u0x79 (u0x7a u0x7a u0x61))))"
);
}
/*
* This is the original bug60 test case; cut down from an ABNF parser
*/
#define BUG60_ABNF_SCAN_UP_TO 64
static
void
test_bug60_abnf
()
{
HParser
*
newline
=
NULL
;
HParser
*
alpha
=
NULL
;
HParser
*
sp
=
NULL
;
HParser
*
vchar
=
NULL
;
HParser
*
equal
=
NULL
;
HParser
*
semicolon
=
NULL
;
HParser
*
comment
=
NULL
;
HParser
*
c_nl
=
NULL
;
HParser
*
c_sp
=
NULL
;
HParser
*
defined_as
=
NULL
;
HParser
*
alphas
=
NULL
;
HParser
*
rule
=
NULL
;
HParser
*
rulelist
=
NULL
;
HParser
*
p
=
NULL
;
int
i
,
j
,
r
,
s_size
;
char
*
s
=
NULL
;
const
char
*
test_string_template
=
"x = y z%s;%s
\n\n
"
;
char
buf_1
[
BUG60_ABNF_SCAN_UP_TO
+
1
];
char
buf_2
[
2
*
BUG60_ABNF_SCAN_UP_TO
+
1
];
newline
=
h_ch
(
'\n'
);
alpha
=
h_choice
(
h_ch_range
(
'A'
,
'Z'
),
h_ch_range
(
'a'
,
'z'
),
NULL
);
sp
=
h_ch
(
' '
);
vchar
=
h_ch_range
(
0x21
,
0x7e
);
equal
=
h_ch
(
'='
);
semicolon
=
h_ch
(
';'
);
comment
=
h_sequence
(
semicolon
,
h_many
(
h_choice
(
sp
,
vchar
,
NULL
)),
newline
,
NULL
);
c_nl
=
h_choice
(
comment
,
newline
,
NULL
);
c_sp
=
h_choice
(
sp
,
h_sequence
(
c_nl
,
sp
,
NULL
),
NULL
);
defined_as
=
h_sequence
(
h_many
(
c_sp
),
equal
,
h_many
(
c_sp
),
NULL
);
alphas
=
h_sequence
(
alpha
,
h_many
(
h_sequence
(
h_many1
(
c_sp
),
alpha
,
NULL
)),
h_many
(
c_sp
),
NULL
);
rule
=
h_sequence
(
alpha
,
defined_as
,
alphas
,
c_nl
,
NULL
);
rulelist
=
h_many1
(
h_choice
(
rule
,
h_sequence
(
h_many
(
c_sp
),
c_nl
,
NULL
),
NULL
));
p
=
rulelist
;
g_check_compilable
(
p
,
PB_GLR
,
1
);
/* Have a buffer for the string */
s_size
=
strlen
(
test_string_template
)
+
3
*
BUG60_ABNF_SCAN_UP_TO
+
1
;
s
=
malloc
(
s_size
);
g_check_cmp_ptr
(
s
,
!=
,
NULL
);
/*
* Try to parse all the different strings according to the template up to
* the scan limit.
*
* Correct behavior: it parses for all values of i, j.
* Bugged behavior: when i % 3 != 0, parse failures begin to occur at
* j == (i / 3) + (i % 3).
*/
for
(
i
=
0
;
i
<
BUG60_ABNF_SCAN_UP_TO
;
++
i
)
{
memset
(
buf_1
,
' '
,
i
);
buf_1
[
i
]
=
0
;
for
(
j
=
0
;
j
<
2
*
BUG60_ABNF_SCAN_UP_TO
;
++
j
)
{
memset
(
buf_2
,
'x'
,
j
);
buf_2
[
j
]
=
0
;
snprintf
(
s
,
s_size
,
test_string_template
,
buf_1
,
buf_2
);
g_check_parse_ok_no_compile
(
p
,
s
,
strlen
(
s
));
}
}
free
(
s
);
}
static
void
test_bug95_lalr_k_param
()
{
/*
* The LR backends had been left hardcoded to k = 1 and were ignoring the param value
* This example compiles for LALR(k) where k = 2
* but does not compile for k = 1
* This shows that the parameter is being used rather than ignored.
* The default value of k when the param == NULL is set to k = 1
*/
HParser
*
a
=
h_ch
(
'a'
);
HParser
*
b
=
h_ch
(
'b'
);
HParser
*
c
=
h_ch
(
'c'
);
HParser
*
B
=
h_indirect
();
HParser
*
A
=
h_sequence
(
a
,
B
,
c
,
NULL
);
HParser
*
B_
=
h_choice
(
B
,
b
,
NULL
);
h_bind_indirect
(
B
,
B_
);
HParser
*
p
=
A
;
if
(
h_compile
(
p
,
PB_LALR
,
(
void
*
)
1
)
==
0
)
{
g_test_message
(
"should not compile for lalr(1)"
);
g_test_fail
();
}
g_check_compilable
(
p
,
PB_LALR
,
2
);
g_check_parse_match_no_compile
(
p
,
"abc"
,
3
,
"(u0x61 u0x62 u0x63)"
);
/* The next test shows that the default works for compile with param == NULL */
/* (default is k = 1) */
g_check_parse_match
(
h_sequence
(
a
,
b
,
c
,
NULL
),
PB_LALR
,
"abc"
,
3
,
"(u0x61 u0x62 u0x63)"
);
}
void
register_regression_tests
(
void
)
{
g_test_add_func
(
"/core/regression/bug118"
,
test_bug118
);
g_test_add_func
(
"/core/regression/seq_index_path"
,
test_seq_index_path
);
...
...
@@ -280,4 +653,13 @@ void register_regression_tests(void) {
g_test_add_func
(
"/core/regression/cfg_many_seq"
,
test_cfg_many_seq
);
g_test_add_func
(
"/core/regression/charset_bits"
,
test_charset_bits
);
g_test_add_func
(
"/core/regression/bug19"
,
test_bug_19
);
g_test_add_func
(
"/core/regression/flatten_null"
,
test_flatten_null
);
//XXX g_test_add_func("/core/regression/ast_length_index", test_ast_length_index);
g_test_add_func
(
"/core/regression/issue91"
,
test_issue91
);
g_test_add_func
(
"/core/regression/issue87"
,
test_issue87
);
g_test_add_func
(
"/core/regression/issue92"
,
test_issue92
);
g_test_add_func
(
"/core/regression/issue83"
,
test_issue83
);
g_test_add_func
(
"/core/regression/bug60"
,
test_bug60
);
g_test_add_func
(
"/core/regression/bug60_abnf"
,
test_bug60_abnf
);
g_test_add_func
(
"/core/regression/bug95_lalrk_param"
,
test_bug95_lalr_k_param
);
}
This diff is collapsed.
Click to expand it.
src/test_suite.c
View file @
5b4ea546
...
...
@@ -25,6 +25,7 @@ extern void register_parser_tests();
extern
void
register_grammar_tests
();
extern
void
register_misc_tests
();
extern
void
register_mm_tests
();
extern
void
register_names_tests
();
extern
void
register_benchmark_tests
();
extern
void
register_regression_tests
();
...
...
@@ -38,6 +39,7 @@ int main(int argc, char** argv) {
register_grammar_tests
();
register_misc_tests
();
register_mm_tests
();
register_names_tests
();
register_regression_tests
();
if
(
g_test_slow
()
||
g_test_perf
())
register_benchmark_tests
();
...
...
This diff is collapsed.
Click to expand it.
src/test_suite.h
View file @
5b4ea546
...
...
@@ -35,6 +35,18 @@
} \
} while(0)
/* Comparison for ptr types; only == and != will work */
#define g_check_cmp_ptr(p1, op, p2) do { \
const void *_p1 = (p1); \
const void *_p2 = (p2); \
if (!(_p1 op _p2)) { \
g_test_message("Check failed: (%s): (%p %s %p)", \
#p1 " " #op " " #p2, \
_p1, #op, _p2); \
g_test_fail(); \
} \
} while (0);
#define g_check_bytes(len, n1, op, n2) do { \
const uint8_t *_n1 = (n1); \
const uint8_t *_n2 = (n2); \
...
...
@@ -56,6 +68,32 @@
} \
} while(0)
#define g_check_maybe_string_eq(n1, n2) do { \
const char *_n1 = (n1); \
const char *_n2 = (n2); \
if (_n1 != _n2 && _n1 != NULL && _n2 != NULL) { \
if (!(strcmp(_n1, _n2) == 0)) { \
g_test_message("Check failed: (%s) (\"%s\" == \"%s\")", \
#n1 " == " #n2, _n1, _n2); \
g_test_fail(); \
} \
} else { \
if (_n1 != NULL || _n2 != NULL) { \
if (_n1 != NULL && _n2 == NULL) { \
g_test_message("Check failed: (%s) (\"%s\" == NULL)", \
#n1 " == " #n2, _n1); \
g_test_fail(); \
} else if (_n1 == NULL && _n2 != NULL) { \
g_test_message("Check failed: (%s) (NULL == \"%s\")", \
#n1 " == " #n2, _n2); \
g_test_fail(); \
} \
/* else both are not-NULL, but point to the same string - succeed */
\
} \
/* else both are NULL, succeed */
\
} \
} while(0)
#define g_check_regular(lang) do { \
if (!lang->isValidRegular(lang->env)) { \
g_test_message("Language is not regular"); \
...
...
@@ -71,24 +109,36 @@
} while(0)
#define g_check_compilable(lang, backend, params) do { \
if (!h_compile(lang, backend, params)) { \
g_test_message("Language is not %s(%s)", #backend, params); \
int r = h_compile((HParser *)(lang), (HParserBackend)(backend), (void *)(params)); \
if (r != 0) { \
g_test_message("Language is not %s(%s)", #backend, #params); \
g_test_fail(); \
} \
} while(0)
#define print_arena_stats(arena) do { \
if (g_test_verbose()) { \
HArenaStats stats; \
h_allocator_stats(arena, &stats); \
g_test_message("Parse used %zd bytes, wasted %zd bytes. " \
"Inefficiency: %5f%%", \
stats.used, stats.wasted, \
stats.wasted * 100. / (stats.used+stats.wasted)); \
} \
} while(0)
#define g_check_parse_failed__m(mm__, parser, backend, input, inp_len) do { \
int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend)backend, NULL); \
if(skip != 0) { \
g_test_message("Compile failed
"
); \
g_test_message("Compile failed
on line %d", __LINE__
); \
g_test_fail(); \
break; \
} \
HParseResult *result = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
if (NULL != result) { \
h_parse_result_free(result); \
g_test_message("Check failed: shouldn't have succeeded, but did"); \
HParseResult *res = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
if (NULL != res) { \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
g_test_message("Check failed: parse shouldn't have succeeded, but did on line %d", __LINE__); \
g_test_fail(); \
} \
} while(0)
...
...
@@ -96,36 +146,61 @@
#define g_check_parse_failed(p, be, input, len) \
g_check_parse_failed__m(&system_allocator, p, be, input, len)
#define g_check_parse_ok(parser, backend, input, inp_len) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend) backend, NULL); \
#define g_check_parse_failed_no_compile__m(mm__, parser, input, inp_len) do { \
HParseResult *res = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
if (NULL != res) { \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
g_test_message("Check failed: shouldn't have succeeded, but did on ;ine %d", __LINE__); \
g_test_fail(); \
} \
} while(0)
#define g_check_parse_failed_no_compile(p, input, len) \
g_check_parse_failed__m(&system_allocator, p, input, len)
#define g_check_parse_ok__m(mm__, parser, backend, input, inp_len) do { \
int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend) backend, NULL); \
if(skip) { \
g_test_message("Compile failed"); \
g_test_fail(); \
break; \
} \
HParseResult *res = h_parse
(
parser, (const uint8_t*)input, inp_len); \
HParseResult *res = h_parse
__m(mm__,
parser, (const uint8_t*)input, inp_len); \
if (!res) { \
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
} else { \
HArenaStats stats; \
h_allocator_stats(res->arena, &stats); \
g_test_message("Parse used %zd bytes, wasted %zd bytes. " \
"Inefficiency: %5f%%", \
stats.used, stats.wasted, \
stats.wasted * 100. / (stats.used+stats.wasted)); \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
#define g_check_parse_match(parser, backend, input, inp_len, result) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend) backend, NULL); \
#define g_check_parse_ok(p, be, input, len) \
g_check_parse_ok__m(&system_allocator, p, be, input, len)
#define g_check_parse_ok_no_compile__m(mm__, parser, input, inp_len) do { \
HParseResult *res = h_parse__m(mm__, parser, (const uint8_t*)input, inp_len); \
if (!res) { \
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
} else { \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
#define g_check_parse_ok_no_compile(p, input, len) \
g_check_parse_ok_no_compile__m(&system_allocator, p, input, len)
#define g_check_parse_match__m(mm__, parser, backend, input, inp_len, result) do { \
int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend) backend, NULL); \
if(skip) { \
g_test_message("Compile failed"); \
g_test_fail(); \
break; \
} \
HParseResult *res = h_parse(parser, (const uint8_t*)input, inp_len); \
HParseResult *res = h_parse
__m(mm__, (HParser *)
(parser
)
, (const uint8_t*)input, inp_len); \
if (!res) { \
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
...
...
@@ -133,16 +208,31 @@
char* cres = h_write_result_unamb(res->ast); \
g_check_string(cres, ==, result); \
(&system_allocator)->free(&system_allocator, cres); \
HArenaStats stats; \
h_allocator_stats(res->arena, &stats); \
g_test_message("Parse used %zd bytes, wasted %zd bytes. " \
"Inefficiency: %5f%%", \
stats.used, stats.wasted, \
stats.wasted * 100. / (stats.used+stats.wasted)); \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
#define g_check_parse_match(parser, backend, input, inp_len, result) \
g_check_parse_match__m(&system_allocator, parser, backend, input, inp_len, result)
#define g_check_parse_match_no_compile__m(mm__, parser, input, inp_len, result) do { \
HParseResult *res = h_parse__m(mm__, (HParser *)(parser), (const uint8_t*)input, inp_len); \
if (!res) { \
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
} else { \
char* cres = h_write_result_unamb(res->ast); \
g_check_string(cres, ==, result); \
(&system_allocator)->free(&system_allocator, cres); \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
#define g_check_parse_match_no_compile(parser, input, inp_len, result) \
g_check_parse_match_no_compile__m(&system_allocator, parser, input, inp_len, result)
#define g_check_parse_chunks_failed__m(mm__, parser, backend, chunk1, c1_len, chunk2, c2_len) do { \
int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend)backend, NULL); \
if(skip) { \
...
...
@@ -154,7 +244,7 @@
} while(0)
#define g_check_parse_chunks_failed___m(mm__, parser, chunk1, c1_len, chunk2, c2_len) do { \
HSuspendedParser *s = h_parse_start__m(mm__, parser); \
HSuspendedParser *s = h_parse_start__m(mm__,
(HParser *)(
parser)
)
; \
if(!s) { \
g_test_message("Chunk-wise parsing not available"); \
g_test_fail(); \
...
...
@@ -187,7 +277,7 @@
} while(0)
#define g_check_parse_chunks_ok_(parser, chunk1, c1_len, chunk2, c2_len) do { \
HSuspendedParser *s = h_parse_start(parser); \
HSuspendedParser *s = h_parse_start(
(HParser *)(
parser)
)
; \
if(!s) { \
g_test_message("Chunk-wise parsing not available"); \
g_test_fail(); \
...
...
@@ -200,12 +290,7 @@
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
} else { \
HArenaStats stats; \
h_allocator_stats(res->arena, &stats); \
g_test_message("Parse used %zd bytes, wasted %zd bytes. " \
"Inefficiency: %5f%%", \
stats.used, stats.wasted, \
stats.wasted * 100. / (stats.used+stats.wasted)); \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
...
...
@@ -221,7 +306,7 @@
} while(0)
#define g_check_parse_chunks_match_(parser, chunk1, c1_len, chunk2, c2_len, result) do { \
HSuspendedParser *s = h_parse_start(parser); \
HSuspendedParser *s = h_parse_start(
(HParser *)(
parser)
)
; \
if(!s) { \
g_test_message("Chunk-wise parsing not available"); \
g_test_fail(); \
...
...
@@ -237,12 +322,98 @@
char* cres = h_write_result_unamb(res->ast); \
g_check_string(cres, ==, result); \
(&system_allocator)->free(&system_allocator, cres); \
HArenaStats stats; \
h_allocator_stats(res->arena, &stats); \
g_test_message("Parse used %zd bytes, wasted %zd bytes. " \
"Inefficiency: %5f%%", \
stats.used, stats.wasted, \
stats.wasted * 100. / (stats.used+stats.wasted)); \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
#define g_check_parse_chunk_failed__m(mm__, parser, backend, chunk1, c1_len) do { \
int skip = h_compile__m(mm__, (HParser *)(parser), (HParserBackend)backend, NULL); \
if(skip) { \
g_test_message("Compile failed"); \
g_test_fail(); \
break; \
} \
g_check_parse_chunk_failed___m(mm__, parser, chunk1, c1_len); \
} while(0)
#define g_check_parse_chunk_failed___m(mm__, parser, chunk1, c1_len) do { \
HSuspendedParser *s = h_parse_start__m(mm__, (HParser *)(parser)); \
if(!s) { \
g_test_message("Chunk-wise parsing not available"); \
g_test_fail(); \
break; \
} \
h_parse_chunk(s, (const uint8_t*)chunk1, c1_len); \
HParseResult *res = h_parse_finish(s); \
if (NULL != res) { \
h_parse_result_free(res); \
g_test_message("Check failed: shouldn't have succeeded, but did"); \
g_test_fail(); \
} \
} while(0)
#define g_check_parse_chunk_failed(p, be, c1, c1_len) \
g_check_parse_chunk_failed__m(&system_allocator, p, be, c1, c1_len)
#define g_check_parse_chunk_failed_(p, c1, c1_len) \
g_check_parse_chunk_failed___m(&system_allocator, p, c1, c1_len)
#define g_check_parse_chunk_ok(parser, backend, chunk1, c1_len) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend)backend, NULL); \
if(skip) { \
g_test_message("Compile failed"); \
g_test_fail(); \
break; \
} \
g_check_parse_chunk_ok_(parser, chunk1, c1_len); \
} while(0)
#define g_check_parse_chunk_ok_(parser, chunk1, c1_len) do { \
HSuspendedParser *s = h_parse_start((HParser *)(parser)); \
if(!s) { \
g_test_message("Chunk-wise parsing not available"); \
g_test_fail(); \
break; \
} \
h_parse_chunk(s, (const uint8_t*)chunk1, c1_len); \
HParseResult *res = h_parse_finish(s); \
if (!res) { \
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
} else { \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
#define g_check_parse_chunk_match(parser, backend, chunk1, c1_len, result) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend) backend, NULL); \
if(skip) { \
g_test_message("Compile failed"); \
g_test_fail(); \
break; \
} \
g_check_parse_chunk_match_(parser, chunk1, c1_len, result); \
} while(0)
#define g_check_parse_chunk_match_(parser, chunk1, c1_len, result) do { \
HSuspendedParser *s = h_parse_start((HParser *)(parser)); \
if(!s) { \
g_test_message("Chunk-wise parsing not available"); \
g_test_fail(); \
break; \
} \
h_parse_chunk(s, (const uint8_t*)chunk1, c1_len); \
HParseResult *res = h_parse_finish(s); \
if (!res) { \
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
} else { \
char* cres = h_write_result_unamb(res->ast); \
g_check_string(cres, ==, result); \
(&system_allocator)->free(&system_allocator, cres); \
print_arena_stats(res->arena); \
h_parse_result_free(res); \
} \
} while(0)
...
...
@@ -321,7 +492,7 @@
#define g_check_cmp_int64(n1, op, n2) g_check_inttype("%" PRId64, int64_t, n1, op, n2)
#define g_check_cmp_uint32(n1, op, n2) g_check_inttype("%u", uint32_t, n1, op, n2)
#define g_check_cmp_uint64(n1, op, n2) g_check_inttype("%" PRIu64, uint64_t, n1, op, n2)
#define g_check_cmp_
ptr
(n1, op, n2) g_check_inttype("%
p
",
void *
, n1, op, n2)
#define g_check_cmp_
size
(n1, op, n2) g_check_inttype("%
zu
",
size_t
, n1, op, n2)
#define g_check_cmpfloat(n1, op, n2) g_check_inttype("%g", float, n1, op, n2)
#define g_check_cmpdouble(n1, op, n2) g_check_inttype("%g", double, n1, op, n2)
...
...
This diff is collapsed.
Click to expand it.
Prev
1
2
3
4
Next