Main: generate tests for printf format parser

This commit is contained in:
Alex Kotov 2022-05-27 05:03:05 +03:00
parent 7a06114ab6
commit 7041066109
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
5 changed files with 451 additions and 0 deletions

2
.gitignore vendored
View File

@ -118,6 +118,8 @@
/tests/test_ntoa
/tests/test_pfa
/tests/test_pfa_assert
/tests/test_printf_fmt_gen
/tests/test_printf_fmt_gen.c
/tests/test_printf_gen
/tests/test_printf_gen.c
/tests/test_units_human

View File

@ -17,6 +17,7 @@ libkernaux_a_SOURCES = \
src/libc.c
CLEANFILES = \
tests/test_printf_fmt_gen.c \
tests/test_printf_gen.c
if ASM_I386
@ -143,6 +144,9 @@ libkernaux_a_SOURCES += src/printf_fmt.c
if ENABLE_TESTS
TESTS += examples/printf_fmt
endif
if ENABLE_TESTS_PYTHON
TESTS += tests/test_printf_fmt_gen
endif
endif
if WITH_UNITS
@ -278,6 +282,14 @@ tests_test_pfa_assert_SOURCES = \
$(libkernaux_a_SOURCES) \
tests/test_pfa_assert.c
tests_test_printf_fmt_gen_SOURCES = \
$(libkernaux_a_SOURCES) \
tests/test_printf_fmt_gen.c \
tests/printf_fmt_gen.py \
tests/printf_fmt_gen.jinja \
common/printf.yml \
common/printf_orig.yml
tests_test_printf_gen_SOURCES = \
$(libkernaux_a_SOURCES) \
tests/test_printf_gen.c \
@ -290,5 +302,8 @@ tests_test_units_human_SOURCES = \
$(libkernaux_a_SOURCES) \
tests/test_units_human.c
tests/test_printf_fmt_gen.c: tests/printf_fmt_gen.py tests/printf_fmt_gen.jinja common/printf_fmt.yml
python3 tests/printf_fmt_gen.py
tests/test_printf_gen.c: tests/printf_gen.py tests/printf_gen.jinja common/printf.yml common/printf_orig.yml
python3 tests/printf_gen.py

340
common/printf_fmt.yml Normal file
View File

@ -0,0 +1,340 @@
- in:
format: 's'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: str
base: 0
- in:
format: '-s'
width: null
precision: null
out:
flags: [left]
width: 0
precision: 0
type: str
base: 0
- in:
format: '+s'
width: null
precision: null
out:
flags: [plus]
width: 0
precision: 0
type: str
base: 0
- in:
format: ' s'
width: null
precision: null
out:
flags: [space]
width: 0
precision: 0
type: str
base: 0
- in:
format: '#s'
width: null
precision: null
out:
flags: [hash]
width: 0
precision: 0
type: str
base: 0
- in:
format: '0s'
width: null
precision: null
out:
flags: [zeropad]
width: 0
precision: 0
type: str
base: 0
- in:
format: '123s'
width: null
precision: null
out:
flags: []
width: 123
precision: 0
type: str
base: 0
- in:
format: '*s'
width: 123
precision: null
out:
flags: []
width: 123
precision: 0
type: str
base: 0
- in:
format: '.123s'
width: null
precision: null
out:
flags: [precision]
width: 0
precision: 123
type: str
base: 0
- in:
format: '.*s'
width: null
precision: 123
out:
flags: [precision]
width: 0
precision: 123
type: str
base: 0
- in:
format: 'ls'
width: null
precision: null
out:
flags: [long]
width: 0
precision: 0
type: str
base: 0
- in:
format: 'lls'
width: null
precision: null
out:
flags: [long, long_long]
width: 0
precision: 0
type: str
base: 0
- in:
format: 'hs'
width: null
precision: null
out:
flags: [short]
width: 0
precision: 0
type: str
base: 0
- in:
format: 'hhs'
width: null
precision: null
out:
flags: [short, char]
width: 0
precision: 0
type: str
base: 0
- in:
format: 'd'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: int
base: 10
- in:
format: 'i'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: int
base: 10
- in:
format: 'u'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: uint
base: 10
- in:
format: 'x'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: uint
base: 16
- in:
format: 'X'
width: null
precision: null
out:
flags: [uppercase]
width: 0
precision: 0
type: uint
base: 16
- in:
format: 'o'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: uint
base: 8
- in:
format: 'b'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: uint
base: 2
- in:
format: 'f'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: float
base: 0
- in:
format: 'F'
width: null
precision: null
out:
flags: [uppercase]
width: 0
precision: 0
type: float
base: 0
- in:
format: 'e'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: exp
base: 0
- in:
format: 'E'
width: null
precision: null
out:
flags: [uppercase]
width: 0
precision: 0
type: exp
base: 0
- in:
format: 'g'
width: null
precision: null
out:
flags: [adapt_exp]
width: 0
precision: 0
type: exp
base: 0
- in:
format: 'G'
width: null
precision: null
out:
flags: [adapt_exp, uppercase]
width: 0
precision: 0
type: exp
base: 0
- in:
format: 'c'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: char
base: 0
- in:
format: 's'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: str
base: 0
- in:
format: '%'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: percent
base: 0
- in:
format: '_'
width: null
precision: null
out:
flags: []
width: 0
precision: 0
type: none
base: 0

View File

@ -0,0 +1,35 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/printf_fmt.h>
#include <assert.h>
int main()
{
{% for case in cases %}
{
const char *format = {{ escape_str(case.in.format) }};
struct KernAux_PrintfFmt_Spec spec = KernAux_PrintfFmt_Spec_create();
KernAux_PrintfFmt_Spec_eval_flags(&spec, &format);
if (KernAux_PrintfFmt_Spec_eval_width1(&spec, &format)) {
KernAux_PrintfFmt_Spec_eval_width2(&spec, {{ none_to_zero(case.in.width) }});
}
if (KernAux_PrintfFmt_Spec_eval_precision1(&spec, &format)) {
KernAux_PrintfFmt_Spec_eval_precision2(&spec, {{ none_to_zero(case.in.precision) }});
}
KernAux_PrintfFmt_Spec_eval_length(&spec, &format);
KernAux_PrintfFmt_Spec_eval_type(&spec, &format);
assert(spec.flags == {{ escape_flags(case.out.flags) }});
assert(spec.width == {{ case.out.width }});
assert(spec.precision == {{ case.out.precision }});
assert(spec.type == {{ escape_type(case.out.type) }});
assert(spec.base == {{ case.out.base }});
}
{% endfor %}
return 0;
}

59
tests/printf_fmt_gen.py Normal file
View File

@ -0,0 +1,59 @@
from jinja2 import Environment, FileSystemLoader
from os import path
from yaml import SafeLoader, safe_load
CASES_FILENAME = 'printf_fmt.yml'
TEMPLATE_FILENAME = 'printf_fmt_gen.jinja'
TEST_FILENAME = 'test_printf_fmt_gen.c'
ROOT_DIRPATH = path.dirname(path.dirname(path.join(path.abspath(__file__))))
COMMON_DIRPATH = path.join(ROOT_DIRPATH, 'common')
TESTS_DIRPATH = path.join(ROOT_DIRPATH, 'tests')
CASES_FILEPATH = path.join(COMMON_DIRPATH, CASES_FILENAME)
TEST_FILEPATH = path.join(TESTS_DIRPATH, TEST_FILENAME)
def main():
cases = safe_load(open(CASES_FILEPATH))
jinja_env = Environment(
keep_trailing_newline=True,
loader=FileSystemLoader(TESTS_DIRPATH),
)
jinja_template = jinja_env.get_template(TEMPLATE_FILENAME)
result = jinja_template.render(
cases=cases,
escape_flags=escape_flags,
escape_str=escape_str,
escape_type=escape_type,
none_to_zero=none_to_zero,
)
with open(TEST_FILEPATH, 'w') as f:
f.write(result)
def escape_flag(flag):
return 'KERNAUX_PRINTF_FMT_FLAGS_' + flag.upper()
def escape_flags(flags):
if len(flags) == 0:
return '0'
return '(' + ' | '.join(map(escape_flag, flags)) + ')'
def escape_str(s):
return '"' + s + '"'
def escape_type(type_):
return 'KERNAUX_PRINTF_FMT_TYPE_' + type_.upper()
def none_to_zero(num):
if num is None:
return '0'
else:
return str(num)
if __name__ == '__main__':
main()