From 7e177790c3d48909f72f85fe4d3775e645b1c7f9 Mon Sep 17 00:00:00 2001 From: Yves Chevallier Date: Fri, 11 Oct 2024 15:45:30 +0200 Subject: [PATCH] Update todo --- TODO.md | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 7 deletions(-) diff --git a/TODO.md b/TODO.md index 027fb67..6c31376 100644 --- a/TODO.md +++ b/TODO.md @@ -2,26 +2,107 @@ ## To Do -- [ ] Support GDB unit test +- [ ] Support GDB unit test (Allowing to test C functions) - [ ] Support Builtin unit test - - [ ] Eval filter - [ ] Input/Output filters - [ ] EvalInputFilter - [ ] Iter class +- [ ] Loops and Random values in tests +- [ ] Refactor output (cli interface) +- [ ] Migrate to pydantic +- [ ] Migrate from TinyKernel to RestrictedPython - [ ] Short test summary info +- [ ] Implement standalone tests ## New Features +### C unit tests + +We may use the following to capture the prototype of a function: + +```python +from elftools.elf.elffile import ELFFile + +def extract_dwarf_info(filename): + with open(filename, 'rb') as f: + elffile = ELFFile(f) + if not elffile.has_dwarf_info(): + print('No DWARF info found in', filename) + return + + dwarf_info = elffile.get_dwarf_info() + + # Parcourir les unités de compilation pour trouver les fonctions + for cu in dwarf_info.iter_CUs(): + print('Found a compilation unit:', cu.get_top_DIE().attributes) + for die in cu.iter_DIEs(): + if die.tag == 'DW_TAG_subprogram': + name = die.attributes['DW_AT_name'].value.decode('utf-8') + print('Function:', name) + + # Si l'élément DIE a des enfants (arguments de fonction) + for child in die.iter_children(): + if child.tag == 'DW_TAG_formal_parameter': + param_name = child.attributes['DW_AT_name'].value.decode('utf-8') + param_type = child.attributes['DW_AT_type'] + print(f'Param: {param_name}, Type: {param_type}') + +extract_dwarf_info('foo.o') +``` + +```yaml +version: 1 +tests: + - name: Test function add + function: + name: add + filename: foo.c + types: [int, float, str] # Would be nice to identify it automatically + build_cmd: gcc -flto {{filename}} runner.c # Default value + args: [1, 2] + stdout: 3 +``` + ### Standalone Unit test ```python -from baygon import UnitTest +# test_foo.py +# Add with: 'foo.py' + +@baygon.stdin('2\n3\n') +@baygon.args('2', '3') +def test_blabla(stdout, stderr, exit_status, execution_time): + assert stdout == '5\n' + assert exit_status == 0 + +def test_bibi(executable: Executable): + res = executable.run(args=['2', '3'], stdin='2\n3\n') + assert res.stdout == '5\n' + assert res.exit_status == 0 +``` + +### Loops + +Using different singleton iterators. They use internal states to generate value at each call. When an iterator is used, the test is repeated for each values generated by the iterator. + +- `iter(min, max, step=1)` +- `rand(min, max, n=1, seed=42, unique=True)` + +Variables and expressions: + +- `{{a=42}}` Assign value to a variable, return the variable value +- `{{a * 2}}` Return the value of the expression -class Test(UnitTest): - def test_version(self): - res = self.functions.add(2, 3) - self.assert_equal(res, 5) +```yaml +version: 1 +fixture: + - 'fixture.py:myfixture' +tests: + - name: Test loop + args: [{{a=random(min=10, max=100, n=100)}}, 2] + stdout: + - contains: {{a}} ``` ### Presentation