* Parse flavors * Batch folder is now created/deleted properly * Shared libraries as symlinks in special dir * Simple README file * Get binary info * Simple cfg retrieval * Lifter has path to cfg as argument * Flags for eventual evaluation * Check policy and presence of cfg file * Print results of getting the cfgs * Check of batch sanity fix * run_test cli parsing * Add abi_libraries directory parsing * Shared libraries directory parsing * Lift and recompile * Before actual test implementation * Playground for testing * Actual testing * Split test cases on per binary bases * Add some commits * Result print * Enhance README.txt * Populate.py to copy needed binaries * Add short decsription of populate.py * Support flavor all * add ida frontend implementation * Basic tag files * Basic inputs * Missing comma * Change inputs handling * Separate function for copy files * Naming convention * Handle missing test case class * Create bin if it is missing * Create so_dir if it is missing * Remove not used cmd argument * Add several more test_suites * ida frontend lift function can now be selected * Smarter tests * BasicTest does not need setUp * Prevent system-wide installed binaries from being run instead of tested * Simple comment * Pass rest of are passed to lift * Fix parser error with unspecified lift_args * Variable name * Change default interpreter to python3 * Fix optional argument parsing for the subsequent lift * typo in mcsema-disass * More details in README * Simplify usage of IDA frontend * ida frontend stores logs * Add script to compile programs and generate tags if desired * Year on copyright * Add hello world src examples of tests. * Add test addition example to README * Correct extension for log files * Basic linker flags * Fix crash if file in bin is missing when tag is present * Bunch of test files * Empty runs * Test_suite name should have maxsplit=1 * Dynamically create test_suites for src programs from definitions * Define cases * Stdin * Split tests into another file * WIP: stdin from string * Another string to be matched if binary is pie * Fix typo in test case * Add color support * Improve stdout output * Add wrappers to make colors more use friendly * Move object representation of test results into separate file * Add magneta * Cleaner verbose output * Log partial results, so they can be dumped into file later for comparison * Replace usage of internals of color.Colors * Refactor how constants are hidden in Colors * Add load/save test results into json * Simple printer of multiple results * result_data.compare() now takes formatter as argument which handles all printing * result_data compare() code cleanup * Missing closing bracket in get_cfg * Test cases now correctly process stdin * Add option to save log as json * Move global variable input_dir into correct module * Add missing suites for files compiled from sources * Compile does not crash when tags are not being stubbed * Fix passing stdin into Popen - input is bytes instead of str * Some tests no longer print floats * populate: Add color support * run_tests: Multithread support * run_tests: Introduces option to specify number of threads to use * get_cfg: Introduces option to specify number of threads to use * Update README with compile.py information * Change --lib_dir to --runtime_lib to avoid llvm version problems * WIP: Set default compiler to clang-8 * Logs are now stored inside batch_name_cfg/logs * Fix bug in log file filename generation * get_cfg: If all is specified as flavor, even empty tag files are selected * Changed run_tests.py --libc_dir to --abi_lib_dir to match mcsema-lift naming conventions * run_test: Timeout is now set to 5sec per test * run_tests: timeout is static attribute of BaseTest. * run_tests: Expand grep tests * run_tests: timeout is now logged as type of test result * src: Add test for global ctors/dtors. * src: Compile script can now use user-defined compilators * run: Add runners for global ctor/dtor tests. * compile: TAGS can now be specified as first line in src file * src: Add TAGS to source files * compile: Source files can now contain more complex header * compile: Config is now responsible for whole process * src: reflect changes in compile script * Missing copyright header * Add util script * populate: Reflect changes in tags structure * get_cfg: Replace flavors by tags to be consistent * get_cfg: Reflect changes in tags structure * run: Parse configs * run: Rework lift to use class instead of random stuff everywhere * run: Removed unittest * run: Remove tests.py * src: Add headers to src tests * run: Obliterate last remnants of tests.py * Update README to reflect changes * Change README from plaintext to markdown * Update .remill_commit_id * Update .remill_commit_id
5.0 KiB
New attempt to create a better test suite. In development process, use at your own peril.
Use:
-
You can use
populate.pyto copy binaries to be tested from/binor/usr/bin. Directory that contains configs is iterated and each binary that has present at least one config file is searched for. In case it is not found error is written on standard output, but the script continues with the rest.Example:
./populate.py > not_exists not found anywhere > Found /bin/echo > Found /bin/grep -
In case you want to try your own sources you can use
compile.pywhich compiles all sources fromsrcdirectory. If option--stub_tagsis used, the corresponding tag files are created. -
First create a batch of cfg file using
get_cfg.py-- you can select tags to run only subset of all tests (they are specified intagsdirectory).- tag all will get cfg for every file with at least one config present
- there are several policies that allows modification of already existing batches
Example:
# Every file present in the `bin` directory will be lifted # into cfg file. # If a batch with name first_batch is present it will be deleted. python get_cfg.py --disass dyninst --tags all --batch first_batch --batch_policy D # Lifts all missing files that have tags C. # In case some file has already present cfg, # it is not replaced python get_cfg.py --disass dyninst --tags C --batch first_batch --batch_policy C # Updates all files with tag echo, leaves rest of the batch untouched python get_cfg.py --disass dyninst --tags echo --batch first_batch --batch_policy U -
Once batch is created
run_tests.pycan be run.
Config/Test files (tags/):
Directory tags (name to be changed) contains two types of files (beware, whitespaces are used as delimiters, therefore they matter):
-
binary.kind.config, which has following internal structure:TAGS: one two ... LIFT_OPTS: +one +two 87 !threeTAGSspecify tags of this config, whileLIFT_OPTSrepresent specific lift options. Options prefixed by+are added and prefix!means that the options is not used even though it would normally be by default. One binary can have multiple config files.At the moment each config should contain exactly one of the following two tags:
c,cpp. They are later used to determine which compiler to use when recompiling. -
binary.test, which has following internal structure:TEST: cmd_option1 ... STDIN: -Fpath/to/file/ or string FILES: Not implemented yet TEST: ... ...For simple test cases it is easier to write this kind of test specification than the one used in python sources.
STDIN:after file is optional and so isFILES:. If value ofSTDIN:is prefixed by F corresponding file is loaded (it can be relative to the root of test dir) and used as stdin.
src/
Files presented in src are meant to be compiled by compile.py and can have special header:
/* TAGS: ... */
/* CC_OPTS: ... */
/* LD_OPTS: ... */
/* LIFT_OPTS: kind1 ... */
/* LIFT_OPTS: kind2 ... */
...
/* TEST: */
/* STDIN: */
...
Everything except CC_OPTS: and LD_OPTS: is used to generated appropriate .config/.test files. CC_OPTS: and LD_OPTS: are forwarded to the compiler.
Complex tests
Not every test can be described by simple "language" of the .test files, therefore it is needed to have a way to define those more complex ones.
In run_tests.py a global array g_complex_test is present, which is used to store more advanced configurations. It has following data type:
{ str : [ TestDetails ] }
The structure is rather intuitive -- each binary has one entry and can have multiple test cases stored in array of TestDetails. TestDetails currently have following options:
cmd (set in __init___): array of command line arguments
files: files that are used by the program
-> it is needed to copy them into appropriate location
check: files that are output of the program
-> it is needed to compare them
As usual, files can be specified by relative paths from root directory of tests.
Directory structure:
get_cfg.py # script to create new cfg files
run_tests.py # runs the selected batches
populate.py # tries to copy binaries from `/bin` or `/usr/bin` based on tags files
bin
|- base_test
|- ... rest of tested binaries
tags
|- base_test.default.config
|- ... for each binary at least one config file
|- base.test
|- .. optional test files
# Folders containing cfg files (there may be a reason you want to have several,
# for example compare frontends or have cfgs of some special flavor)
batch1_cfg
|- base_test.cfg
|- ...
batch2_cfg
|- base_test.cfg
|- ...
# Symlinks to shared libraries used by original binaries
# Links themselves are created by get_cfg.py
shared_libs
|- libc.so
|- ...
# Inputs for the run_tests.py
inputs
|- input1.txt
|- program1
|- ...