mirror of
https://github.com/tailix/libkernaux.git
synced 2025-03-31 17:25:22 -04:00
Common: generate original tests for printf
This commit is contained in:
parent
880fdd0ba7
commit
74128be3ff
6 changed files with 173 additions and 9 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -118,4 +118,6 @@
|
|||
/tests/test_pfa
|
||||
/tests/test_pfa_assert
|
||||
/tests/test_printf
|
||||
/tests/test_printf_gen
|
||||
/tests/test_printf_gen.c
|
||||
/tests/test_units_human
|
||||
|
|
16
Makefile.am
16
Makefile.am
|
@ -16,6 +16,9 @@ libkernaux_a_SOURCES = \
|
|||
src/assert.c \
|
||||
src/libc.c
|
||||
|
||||
CLEANFILES = \
|
||||
tests/test_printf_gen.c
|
||||
|
||||
if ASM_I386
|
||||
libkernaux_a_SOURCES += src/asm/i386.S
|
||||
endif
|
||||
|
@ -128,6 +131,12 @@ TESTS += \
|
|||
examples/snprintf \
|
||||
examples/snprintf_va \
|
||||
tests/test_printf
|
||||
if ENABLE_TESTS_PYTHON
|
||||
TESTS += tests/test_printf_gen
|
||||
noinst_SCRIPTS = tests/printf_gen.py
|
||||
noinst_DATA = \
|
||||
tests/printf_orig.yml
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -264,6 +273,13 @@ tests_test_printf_SOURCES = \
|
|||
$(libkernaux_a_SOURCES) \
|
||||
tests/test_printf.c
|
||||
|
||||
tests_test_printf_gen_SOURCES = \
|
||||
$(libkernaux_a_SOURCES) \
|
||||
tests/test_printf_gen.c
|
||||
|
||||
tests_test_units_human_SOURCES = \
|
||||
$(libkernaux_a_SOURCES) \
|
||||
tests/test_units_human.c
|
||||
|
||||
tests/test_printf_gen.c: tests/printf_gen.py tests/printf_orig.yml
|
||||
python3 tests/printf_gen.py
|
||||
|
|
|
@ -11,11 +11,25 @@ RSpec.describe KernAux, '.sprintf' do
|
|||
it { is_expected.to eq 'Hello, World!' }
|
||||
|
||||
context 'using original tests' do
|
||||
printf_yml = File.expand_path('../../../../../tests/printf.yml', __dir__)
|
||||
printf_yml =
|
||||
File.expand_path('../../../../../tests/printf_orig.yml', __dir__)
|
||||
|
||||
YAML.safe_load_file(printf_yml).each do |test|
|
||||
expected = test['result']
|
||||
args = test['args']
|
||||
|
||||
args = test['args'].map do |arg|
|
||||
if arg.is_a? String
|
||||
arg
|
||||
else
|
||||
arg.map do |item|
|
||||
if item.is_a? Array
|
||||
item[0]
|
||||
else
|
||||
item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "transforms #{args.inspect} to #{expected.inspect}" do
|
||||
expect(described_class.sprintf(*args)).to eq expected
|
||||
|
|
63
tests/printf_gen.jinja
Normal file
63
tests/printf_gen.jinja
Normal file
|
@ -0,0 +1,63 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <kernaux/printf.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
static const char *const data = "foobar";
|
||||
|
||||
static char buffer[BUFFER_SIZE];
|
||||
static size_t buffer_index;
|
||||
|
||||
static void test_putchar(const char chr, void *const arg)
|
||||
{
|
||||
assert(arg == data);
|
||||
|
||||
if (buffer_index >= BUFFER_SIZE) {
|
||||
printf("Buffer overflow!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
buffer[buffer_index++] = chr;
|
||||
}
|
||||
|
||||
static void test(const char *const expected, const char *const format, ...)
|
||||
{
|
||||
va_list va;
|
||||
int result;
|
||||
|
||||
memset(buffer, '\0', sizeof(buffer));
|
||||
buffer_index = 0;
|
||||
va_start(va, format);
|
||||
result = kernaux_vprintf(test_putchar, (char*)data, format, va);
|
||||
va_end(va);
|
||||
assert((size_t)result == strlen(expected));
|
||||
assert(strcmp(expected, buffer) == 0);
|
||||
|
||||
memset(buffer, '\0', sizeof(buffer));
|
||||
buffer_index = 0;
|
||||
va_start(va, format);
|
||||
result = kernaux_vsnprintf(buffer, sizeof(buffer), format, va);
|
||||
va_end(va);
|
||||
assert((size_t)result == strlen(expected));
|
||||
assert(strcmp(expected, buffer) == 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{% for case in cases %}
|
||||
{% if not case.fixme %}
|
||||
printf("%s\n", {{ escape_str(case.result) }});
|
||||
test({{ escape_str(case.result) }}, {{ escape_str(fmt(case.args)) }}{{ values(case.args) }});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
return 0;
|
||||
}
|
68
tests/printf_gen.py
Normal file
68
tests/printf_gen.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
from jinja2 import Environment, FileSystemLoader
|
||||
from os import path
|
||||
from yaml import SafeLoader, safe_load
|
||||
|
||||
CASES_ORIG_FILENAME = 'printf_orig.yml'
|
||||
TEMPLATE_FILENAME = 'printf_gen.jinja'
|
||||
TEST_FILENAME = 'test_printf_gen.c'
|
||||
|
||||
TESTS_DIRPATH = path.dirname(path.abspath(__file__))
|
||||
|
||||
CASES_ORIG_FILEPATH = path.join(TESTS_DIRPATH, CASES_ORIG_FILENAME)
|
||||
TEST_FILEPATH = path.join(TESTS_DIRPATH, TEST_FILENAME)
|
||||
|
||||
def main():
|
||||
cases_orig = safe_load(open(CASES_ORIG_FILEPATH))
|
||||
cases = cases_orig
|
||||
|
||||
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_str=escape_str,
|
||||
fmt=fmt,
|
||||
values=values,
|
||||
)
|
||||
|
||||
with open(TEST_FILEPATH, 'w') as f:
|
||||
f.write(result)
|
||||
|
||||
def escape_char(c):
|
||||
return "'" + c + "'"
|
||||
|
||||
def escape_str(s):
|
||||
return '"' + s + '"'
|
||||
|
||||
def fmt(args):
|
||||
fmt = ''
|
||||
for arg in args:
|
||||
if type(arg) is list:
|
||||
fmt += arg[0]
|
||||
else:
|
||||
fmt += arg
|
||||
return fmt
|
||||
|
||||
def values(args):
|
||||
values = ''
|
||||
|
||||
for arg in args:
|
||||
if type(arg) is list and len(arg) >= 2:
|
||||
if len(arg) >= 3:
|
||||
values += ', ' + str(arg[1])
|
||||
arg[1] = arg[2]
|
||||
|
||||
if type(arg[1]) is str:
|
||||
values += ', ' + escape_str(arg[1])
|
||||
elif type(arg[1]) is list:
|
||||
values += ', ' + escape_char(arg[1][0])
|
||||
else:
|
||||
values += ', ' + str(arg[1])
|
||||
|
||||
return values
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -67,7 +67,7 @@
|
|||
- result: 'EDCB5433'
|
||||
args: [['% X', 3_989_525_555]]
|
||||
- result: 'x'
|
||||
args: [['% c', 'x']]
|
||||
args: [['% c', ['x']]]
|
||||
|
||||
# + flag
|
||||
|
||||
|
@ -110,7 +110,7 @@
|
|||
- result: 'EDCB5433'
|
||||
args: [['%+X', 3_989_525_555]]
|
||||
- result: 'x'
|
||||
args: [['%+c', 'x']]
|
||||
args: [['%+c', ['x']]]
|
||||
- result: '+'
|
||||
args: [['%+.0d', 0]]
|
||||
|
||||
|
@ -199,6 +199,7 @@
|
|||
args: ['Hello testing']
|
||||
- result: 'Hello testing'
|
||||
args: [['Hello testing%s']]
|
||||
fixme: true
|
||||
- result: 'Hello testing'
|
||||
args: [['Hello testing%s', '']]
|
||||
- result: 'Hello testing'
|
||||
|
@ -259,7 +260,7 @@
|
|||
- result: 'EDCB5433'
|
||||
args: [['%1X', 3_989_525_555]]
|
||||
- result: 'x'
|
||||
args: [['%1c', 'x']]
|
||||
args: [['%1c', ['x']]]
|
||||
|
||||
# width 20
|
||||
|
||||
|
@ -290,7 +291,7 @@
|
|||
- result: ' EDCB5433'
|
||||
args: [['%20X', 3_989_525_555]]
|
||||
- result: ' x'
|
||||
args: [['%20c', 'x']]
|
||||
args: [['%20c', ['x']]]
|
||||
|
||||
# width *20
|
||||
|
||||
|
@ -321,7 +322,7 @@
|
|||
- result: ' EDCB5433'
|
||||
args: [['%*X', 20, 3_989_525_555]]
|
||||
- result: ' x'
|
||||
args: [['%*c', 20, 'x']]
|
||||
args: [['%*c', 20, ['x']]]
|
||||
|
||||
# width -20
|
||||
|
||||
|
@ -354,7 +355,7 @@
|
|||
- result: 'EDCB5433 '
|
||||
args: [['%-20X', 3_989_525_555]]
|
||||
- result: 'x '
|
||||
args: [['%-20c', 'x']]
|
||||
args: [['%-20c', ['x']]]
|
||||
- result: '| 9| |9 | | 9|'
|
||||
args: [['|%5d| ', 9], ['|%-2d|', 9], [' |%5d|', 9]]
|
||||
- result: '| 10| |10| | 10|'
|
||||
|
@ -393,7 +394,7 @@
|
|||
- result: 'EDCB5433 '
|
||||
args: [['%0-20X', 3_989_525_555]]
|
||||
- result: 'x '
|
||||
args: [['%0-20c', 'x']]
|
||||
args: [['%0-20c', ['x']]]
|
||||
|
||||
# padding 20
|
||||
|
Loading…
Add table
Reference in a new issue