check_sol -- Skrypt do automatycznego sprawdzania poprawności programów, tj. zgodności wyjścia programu z wyjściem wzorcowym dla zadanych plików wejściowych. Główne funkcje:
- kompilacja kodu najbardziej popularnych języków lub użycie skompilowanego programu,
- automatyczne uruchomienie programu dla zbioru lub całego katalogu plików wejściowych (.in) oraz sprawdzenie wyjścia standardowego/błędów,
- porównywanie identycznościowe wyjścia programu z wzorcowym; można jednak dostarczyć własny program
sprawdzający, dowolnie definiujący zgodność wyjść (patrz opcja
--compare
), - czytelna, pokolorowana, konfigurowalna postać wyjścia,
- pomiar i limity czasu wykonania oraz zajętej pamięci,
- generowanie samych testów.
- program
time
(najczęściej/usr/bin/time
, nie mylić z poleceniem powłoki o tejże nazwie), - uprawnienia do wykonania polecenia
ulimit
, jeśli używane są limity czasu lub pamięci, - odpowiednie kompilatory w przypadku podania pliku z kodem jako argumentu.
W celu instalacji należy uruchomić załączony skrypt install.sh
. Zainstaluje on pliki w podanym
katalogu (domyślnie ~/.check_sol
), uzupełni odpowiednio konfigurację oraz wykona testowe
uruchomienie skryptu. Żeby wygodniej korzystać ze skryptu check_sol, można po pierwszej instalacji
umieścić link do niego w katalogu na zmiennej $PATH
, na przykład
ln -s <katalog-instalacji>/check_sol /usr/local/bin/check_sol
W trybie normalnym, dla każdego testu wypisywany jest jeden wiersz wyniku:
-
numer i nazwa testu,
-
orientacyjna zużyta pamięć, w kiB, jeśli program działał wystarczająco długo żeby ją zmierzyć,
-
czas wykonanie programu, w sekundach z dokładnością do setnych,
-
wynik testu:
AC
-- Answer Correct, odpowiedź zgodna z wzorcową,TL
-- Time Limit (Exceeded), przekroczony limit czasu wykonania,ML
-- Memory Limit (Exceeded), przekroczony limit zajmowanej pamięci,WA
-- Wrong Answer, odpowiedź niezgodna z wzorcową,RE
-- Runtime Error, błąd wykonania????
-- inny błąd (np. brak plików)
W trzech ostatnich przypadkach w kolejnym wierszu zostanie wypisany opis błędu.
W trybie skróconego wyjścia (patrz --short-output
) dla każdego testu wypisywany jest tylko jeden
znak wyniku testu, analogicznie jak wyżej.
Po zakończeniu testowania wyświetlane jest podsumowanie -- liczba wyników różnego rodzaju, maksymalny czas oraz pamięć dla testu.
W pliku check_sol_example.png
zobaczyć można przykład wyjścia skryptu dla danych spreparowanych
tak, by pokazywać różne możliwe przypadki.
-s | --solution PLIK
kod programu do sprawdzenia. Obsługiwane są pliki.cpp
,.cc
,.c
,.pas
, inne należy skompilować ręcznie i użyć opcji-S
. Domyślne flagi kompilacji ustawione są w plikucheck_sol.cfg
, ale honorowane są ustawienia zmiennych środowiskowych. Podanie tego parametru lub-S
jest konieczne.-S | --sol-exec PLIK
skompilowany program do sprawdzenia. Powinien mieć prawa do uruchomienia. Podanie tego parametru lub-s
jest konieczne.-i | --input PLIKI
pliki wejściowe, dla których ma zostać uruchomiony program. Argumentem może być plik lub lista plików, jak również katalog -- wtedy użyte zostaną wszystkie zawarte w nim pliki.in
. Parametr konieczny.-o | --output KATALOG
katalog zawierający plik[i] wyjściowe. Muszą mieć nazwy identyczne z podanymi plikami wejściowymi oraz rozszerzenie.out
. Parametr konieczny.-c | --compare PLIK
kod programu sprawdzającego zgodność wyjść. Obecnie obsługiwany jest tylko format .cpp (aczkolwiek można dostarczyć inny przez-C
). Jeśli nie zostanie podany ten parametr ani-C
, zostanie użyta domyślna sprawdzaczka, określona w pliku konfiguracyjnym. Aby dowiedzieć się, jak powinien wyglądać program sprawdzający, przeczytaj komentarz na początkudefault_compare.cpp
w katalogu instalacyjnym.-C | --comp-exec PLIK
skompilowany program sprawdzający zgodność wyjść.-e | --no-errors
powoduje zatrzymanie sprawdzania po pierwszym błędnym teście.-m | --mem-limit LICZBA
ustawia limit pamięci dla programu naLICZBA
kilobajtów (lubLICZBA
megabajtów, jeśliLICZBA
ma dopisekM
). Uwaga: przy zbyt niskich (kilkanaście MiB i mniej) limitach zachowanie programów jest dość nieokreślone.-M | -Mem-limit LICZBA
alias do-m <LICZBA>M
(limit pamięci w MiB).-t | --time-limit LICZBA
ustawia limit czasu wykonania jednego testu naLICZBA
sekund.-h | --short-output
zamiast jednego wiersza wyniku dla każdego testu wypisuje pojedynczy znak statusu sprawdzenia -- przydatne przy testowaniu na dużej liczbie przykładów.-N | --no-delete
nie usuwa plików tymczasowych tworzonych przez program. Przydatne w połączeniu z--no-errors
, gdyż te pliki zawierają dane dot. wykonania ostatniego testu.-E | --check-stderr
porównuje również standardowe wyjście błędu programów. Zakłada, że wzorcowe wyjścia błędu mają rozszerzenie.err
i znajdują się w katalogu z plikami.out
.-g | --gen-outs
zamiast porównywać plikami.out
w katalogu podanym w-o
, używa zadanego programu do jego wygenerowania. Przy-E
generuje w tymże katalogu również pliki.err
. Uwaga: generowane pliki nadpisują dotychczasowe pliki o tej samej nazwie.-G | --gen-tests PLIK
uznaje plik rozwiązania za generator testów, przyjmujący parametry określone w PLIKu konfiguracyjnym. Zobacz sekcję Generowanie testów, opisującą format tych plików. Opcja generowania wyłącza-g
, zaś opcje sprawdzenia nie mają znaczenia. Pozostają aktywne limity czasu i pamięci. Uwaga: generowane pliki nadpisują dotychczasowe.
check_sol -s zadanie.cpp -i testy -o testy
: najprostsze sprawdzenie kodu zadanie.cpp
na wszystkich plikach .in
z katalogu testy.
check_sol -s zadanie.cc -i tests/in -o tests/out -E -t 1 -m 50M -e
: skompilowanie pliku
zadanie.cc
i uruchomienie go na wszystkich plikach wejściowych z katalogu tests/in
, sprawdzając
zgodność z wyjściami .out
i .err
w katalogu tests/out
, z limitem 1 sekundy i 50MiB pamięci
oraz przerwaniem testowania po pierwszym błędzie.
check_sol -S generator -G gen_cfg -i testy
: wygenerowanie testów do katalogu testy
programem
generator
na podstawie konfiguracji w pliku gen_cfg
.
Można zamiast pliku rozwiązania podać program generujący testy. Program taki powinien przyjmować odpowiednią liczbę parametrów z wiersza poleceń. Liczba generowanych testów, ich nazwa i parametry powinny zostać zapisane w skrypcie konfiguracyjnym. Skrypt powinien ustawiać następujące zmienne:
TEST_NAME
-- prefiks nazwy generowanych plików wejściowych (nazwa01.in
, ...)TEST_COUNT
-- liczba testów do wygenerowaniaPARAMS
-- lista parametrów generatoraparam1, ...
-- tablice o nazwach wskazywanych przez$PARAMS
, zawierające przynajmniej$TEST_COUNT
elementów- zamiast
PARAMS
oraz osobnych tablic można zdefiniować tablicęGEN_TESTS_PARAMS
, zawierającą przynajmniej$TEST_COUNT
elementów -- wierszy gotowych do przekazania generatorowi.
Zaleca się, żeby jako jeden z parametrów podać ziarno generatora liczb losowych. Można wtedy, zamiast wysyłać duże pliki wejściowe, wysłać sam generator i plik konfiguracyjny, uzyskując na dowolnej maszynie taki sam zestaw testów. Ponadto, skrypt może zawierać inne komendy, zostaną one wykonane przed rozpoczęciem generowania (nawet wymienione zmienne mogą być generowane, a nie podane wprost). Parametry powinny mieć unikalne nazwy.
Przykładowy prosty generator, wypisujący n
losowych liczb z zakresu [0..n)
:
sscanf(argv[1], "%d", &seed);
sscanf(argv[2], "%d", &n);
srand(seed);
for (int i=0; i<n; ++i) printf("%d ", rand()%n);
Przykładowy plik konfiguracyjny powyższego generatora:
TEST_NAME=nazwa
TEST_COUNT=5
PARAMS="P_SEED P_ILE"
P_SEED=(123 950 1209 5392 2)
P_ILE=(4 10 50 123 500000)
Konfiguracja tych samych testów, przy użyciu drugiego sposobu definiowania zmiennych:
TEST_NAME=nazwa
TEST_COUNT=5
GEN_TESTS_PARAMS=("123 4" "950 10" "1209 50" "5392 123" "2 500000")
W katalogu instalacyjnym znajduje się plik check_sol.cfg
. Można w nim ustawić domyślne
kompilatory i ich flagi oraz nieco skonfigurować kolory i szerokość wyjścia skryptu.
- W czasie sprawdzeń nie powinien być uruchomiony inny program o nazwie identycznej ze sprawdzanym
(gdzie programy kompilowane przez
check_sol
mają rozszerzenie.e
. - Program (z zamierzenia) nie jest całkowicie idiotoodporny -- argumenty wykonania powinny być użyte zgodnie z przeznaczeniem.
- Przerwanie programu sygnałem SIGABRT wykrywane jest jako przekroczenie limitu pamięci, gdzie prawdziwa jest implikacja w lewo -- ten sygnał pojawia się też np. po niezłapanym wyjątku...
Znalezione błędy, jak i sugestie nowych funkcjonalności można zgłaszać przez GitHub:
https://github.com/quezak/check_sol/issues
- v2.11: opcja
-M
- v2.10: nowa domyślna sprawdzaczka
- v2.05: możliwość podania wyszczególnionych plików wejściowych
- v2.03: wczytywanie ze środowiska ustawień kompilacji
- v2.0: generowanie testów, selftest przy instalacji
- v1.9: opcja generowania plików wyjściowych
- v1.8-1.89: liczne poprawki związane z czytelnością i stylem kodu.
- v1.7.1: dodane sprawdzenie wyjścia błędów.
- v1.7: wersja z momentu założenia repozytorium. Liczyła kilka ładnych lat i nie była napisana zbyt ładnie.