Search
Ověření správnosti implementance domácích úkolů není nutné vyloženě realizovat odevzdáváním do BRUTE, tzv. zkoušet odevzdat. Mnohem výhodnější je prostě jen odevzdat správně fungující program, čímž lze ušetřit nejen čas, ale také případný maximální počet uploadů a vyhnout se tak dodatečné penalizaci. Pravděpodbně nejlepším způsobem je detailní inspekce a procházení kódů s tím, že je dobré vědět, co se přesně děje na každém řádku kódu a co se může stát v závislosti na konkrétním vstupu. Taková detailní inspekce však vyžaduje jistou dávku zkušenosti, proto jsme pro vás připravili tzv. trial/error možnosti jak ověřit, že program generuje požadovaný výstup.
První způsobem jak otestovat funkčnost programu je využit přiložených vstupních a výstupních souborů. Například HW 1 - Načítání vstupu
$ ./hw1-bab36prga < data/pub01.in 212, -78, 5, 16, 32 Pocet cisel: 5 Pocet kladnych: 4 Pocet zapornych: 1 Procento kladnych: 80.00 Procento zapornych: 20.00 Pocet sudych: 4 Pocet lichych: 1 Procento sudych: 80.00 Procento lichych: 20.00 Prumer: 37.40 Maximum: 212 Minimum: -78
Na první pohled vypadá vše v pořádku, ale není. Což si můžeme ukázat porovnáním v referenčním řešením.
$ ./hw1-bab36prga < data/pub01.in > my.out $ ./bab36prga-hw1-genref < data/pub01.in > ref.out
my.out
bab36prga-hw1-genref
ref.out
$ diff my.out ref.out 2c2 < Pocet cisel: 5 --- > Pocet cisel: 5
Výstupy nejsou identické, ale stále úplně nevidíme rozdíl. Proto zkusíme program hexdump:
hexdump
$ hexdump -C my.out > my.hex $ hexdump -C ref.out > ref.hex
meld
Tam si můžeme všimnout, že jsou nějaké znaky navíc, což nyní uvidíme i v textu.
A když už víme na co se dívat, tak rovnou v hex výstup, např. grafickém 'ghex'.
V případě HW 2 - Kreslení (ASCII art) vygenerujeme pro vstup data/pub01.in výstupní soubor my-pub01.out a porovnáme s přiloženým souborem
data/pub01.in
my-pub01.out
$ ./hw2-bab36prga < data/pub01.in > my-pub01.out $ diff data/pub01.out my-pub01.out 1,7c1,7 < X < X X < X X < XXXXXXX < X X < X X < XXXXXXX --- > x > x x > x x > xxxxxxx > x x > x x > xxxxxxx
vimdiff
$ hexdump -C my-pub01.out
$ diff data/pub01.out my-pub01.out 1,3c1,3 < X < X X < X X --- > X > X X > X X
Převedením do hexavýpisu rozdíl spíše uvidíme
$ hexdump -C my-pub01.out >my-pub01.out.hex $ hexdump -C data/pub01.out >pub01.out.hex $diff pub01.out.hex my-pub01.out.hex 1,5c1,5 < 00000000 20 20 20 58 0a 20 20 58 20 58 0a 20 58 20 20 20 | X. X X. X | < 00000010 58 0a 58 58 58 58 58 58 58 0a 58 20 20 20 20 20 |X.XXXXXXX.X | < 00000020 58 0a 58 20 20 20 20 20 58 0a 58 58 58 58 58 58 |X.X X.XXXXXX| < * < 00000030 --- > 00000000 20 20 20 58 20 20 20 0a 20 20 58 20 58 20 20 0a | X . X X .| > 00000010 20 58 20 20 20 58 20 0a 58 58 58 58 58 58 58 0a | X X .XXXXXXX.| > 00000020 58 20 20 20 20 20 58 0a 58 20 20 20 20 20 58 0a |X X.X X.| > 00000030 58 58 58 58 58 58 58 0a |XXXXXXX.| > 00000038
Z výpisu by již mělo být patrné, že tiskneme mezery až na plnou šiři domečku, což není očekávaný výstup.
Případně ještě lépe můžeme vidět při použití vimdiff nebo jiného rozdílovače.
$ vimdiff pub01.out.hex my-pub01.out.hex
Další možností je využít přiloženého programu pro generování náhodných zadání (vstupních souborů), který zároveň funguje také jako refereční řešení. Například pro HW 3 - Prvočíselný rozklad se generátor/referenční řešení nachází v binárním souboru bab36prga-hw3-genref, který je sestaven pro prostředí v počítačových učebnách, tj.
bab36prga-hw3-genref
$ file bab36prga-hw3-genref bab36prga-hw3-genref: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, stripped
Program má minimalistické rozhraní a nápovědu lze vyvolat přepínačem -h, např. ./bab36prga-hw3-genref -h
-h
./bab36prga-hw3-genref -h
$ ./bab36prga-hw3-genref -h Generator and reference solution of the HW3 Version $Id: bab36prga-hw3-genref.c 499 2019-02-17 21:40:16Z jf $ Usage: ./bab36prga-hw3-genref [-generate] [-optional|-prg-optional] [-h] Generator is enabled by -generate argument and produce a random instance of the HW3 Generator is also invoked if the program binary contains "gener" string, e.g., using symbolic link such as generate Otherwise a reference solution expects the input and produces the output as it is required in the assignment of the 02 -h prints this help message In a case of any troubles report them to the teachers together with the 'Version $Id: bab36prga-hw3-genref.c 499 2019-02-17 21:40:16Z jf $'
Ve vychozím použití funguje jako refereční řešení očekávájící vstup na stdin a generuje výstup na stdout, např.
stdin
stdout
$ ./bab36prga-hw3-genref <data/data/pub01-m.in >pub01-ref.out $ diff data/pub01-m.out pub01-ref.out
data/pub01-m.out
V případě uvedení argument -generate program vypíše na stdout náhodný vstup
-generate
$ ./bab36prga-hw3-genref -generate > my01.in Generate random instance for HW2 $ cat my01.in 8804431 0
$ ./bab36prga-hw3-genref <my01.in >my01.out $ cat my01.out Prvociselny rozklad cisla 8804431 je: 347 x 25373
V případě domácího úkolu, který má povinnou a volitelnou část, lze generátor přepnout do režimu generování vstupu pro volitelné zadání přepínačem -optional. Například v případě HW 6 - Maticové počty se standardní zadání generuje
-optional
$ ./bab36prga-hw6-genref -generate Generate a random instance for HW6 1 5 33 48 47 33 -40 + 1 5 -48 1 -43 9 -46
$ ./bab36prga-hw6-genref -generate -optional Generate a random instance for HW6 5 6 -33 17 49 -36 47 12 32 -22 17 43 -1 -20 -35 6 -41 10 5 8 37 -18 42 -23 34 15 11 3 -7 30 -2 -3 + 5 6 17 39 -18 -34 -47 16 -6 -27 9 -5 3 -23 -48 -35 -11 7 -25 -24 -9 20 -45 27 -15 16 33 -20 49 -19 28 -9 - 5 6 -20 -17 -37 35 49 7 -42 -40 4 -36 -13 -42 31 26 -33 -44 -47 -40 -22 -42 38 13 -23 21 -4 -24 4 -26 17 5 + 5 6 -10 36 -16 41 45 45 -48 -1 -41 -11 8 40 18 -23 -2 21 -12 27 -19 28 42 -40 -49 -12 -14 5 -36 5 13 -11 + 5 6 -25 -7 45 -30 -12 -1 -28 49 38 -18 -9 -42 9 39 -19 47 -32 -35 25 13 -25 -22 3 -36 -14 -30 19 49 9 28 + 5 6 23 -1 -45 -39 48 29 12 -11 -39 -47 49 21 42 -19 -30 13 -4 -2 -24 21 26 29 35 -38 49 -43 -39 9 -13 16
stderr
Náhodně generovanými vstupy sice nelze zaručit plné otestování aplikace, ale lze výrazně zvýšit odhalení chyby. Ručně generovat jednotky nebo desítky či stovky náhodných vstupů je zbytečně pracné a můžeme použít krátkého programu pro příkazový interpret. V archivu je tak vedle generátoru/referečního řešení přiložen skript generate_solution.sh, který např. vytvoří čtyři vstupní soubory a k tomu odpovídající referenční řešení:
generate_solution.sh
$ cat #!/bin/sh HW=hw2 PROGRAM=./bab36prga-$HW-genref mkdir -p files for i in `seq 1 4` do PROBLEM=files/$HW-$i echo "Generate random input '$PROBLEM.in'" $PROGRAM -generate > $PROBLEM.in 2>/dev/null echo "Solve '$PROBLEM.in' and store the reference solution to '$PROBLEM.out'" $PROGRAM < $PROBLEM.in > $PROBLEM.out 2>$PROBLEM.err done
seq
Skriptu lze podobným způsobem využít pro dávkové otestování vlastního programu a porovnání s referenčním řešení, viz Skriptování v Bournově shellu
Další z možností jak lze implementaci úkolu testovat je přímé použití implementovaných funkcí v nějaké programu. Sestavení takového testovacího programu s novou implementací vyžaduje zdrojové kódy nebo alespoň přeložené soubory (object file - .o). V případě, že chceme pouze změnit implementaci konkrétních funkci aniž bychom měnili rozhraní, můžeme využít mechanismu dynamicky linkovaných knihoven, kdy se konkrétní implementace linkuje k programu až při jeho spuštění. Binární testovací program tak zůstává identický a jediné co měníme je příslušná dynamická knihovna, která zachovává stejné rozhraní definované v příslušném hlavičkovém souboru.
V úloze HW 7 - Kruhová fronta v poli je cílem implementovat sadu funkcí pro práci s kruhovou frontou a to dle rozhraní předepsaného v queue.h, proto se přímo nabízí sestavit z implementace queue.c dynamickou knihovnu, což lze realizovat například volámím
queue.h
queue.c
clang -fPIC -shared queue.c -o libqueue.so
Makefile
A pak již stačí spustit testovací program bab36prga-hw7-test, který hledá dynamickou knihovnu v aktuálním pracovním adresáři, což lze například ověřit
bab36prga-hw7-test
$ ldd bab36prga-hw7-test bab36prga-hw7-test: libqueue.so => ./libqueue.so (0x2c423000) libc.so.7 => /lib/libc.so.7 (0x2c624000)
Toho je docíleno linkováním
clang bab36prga-hw7-test.c queue.c -o bab36prga-hw7-test -L. -Wl,-rpath=. -lqueue
-lqueue
-L.
rpath
-Wl,
Po úspěšném sestavaní dynamické knihovny vlastní implementace lze spustit testovací program např.
$ ./bab36prga-hw7-test Basic test ........... PASSED Overflow test ........ PASSED Multiple queues test . PASSED Reallocation test .... PASSED All tests passed
Nebo v případě dodatečného testování funkcionality volitelného zadání jako
$ ./bab36prga-hw7-test -prg-optional Basic test ........... PASSED Overflow test ........ PASSED Multiple queues test . PASSED Reallocation test .... PASSED Shrink test .......... PASSED All tests passed