Brutetestaus
Brutetesterin voi kirjoittaa monella tavalla, mutta ainakin jokin tapa on hyvä osata rutiinilla.
Alla esimerkki C++-brutetestaajan rungosta. Varsinainen koodi on tiedostossa koodi.cpp
käännettynä tiedostoon koodi
, bruteratkaisu on tiedostossa brute.cpp
, käännettynä brute
.
#include <bits/stdc++.h> using namespace std; int main() { while (true) { // Generoi sattumanvarainen syöte tiedostoon ofstream f("syote"); int n = rand()%10+1; f << n << endl; f.close(); // Aja molemmat koodit system("./brute < syote > out_brute"); system("./koodi < syote > out_koodi"); // Vertaa tulosteita if (system("diff -b out_brute out_koodi")) { cout << "Virhe löytyi!" << endl; break; } } }
Komento diff
lipulla -b
vertailee kätevästi tulosteita välittämättä ylimääräisistä välilyönneistä, kuten kisajärjestelmätkin.
Välillä ei ole tarkoituskaan, että tulosteet ovat identtisiä, vaan oikeellisuus pitää tarkastaa jollain toisella tavalla. Tällöin tulosteet voidaan lukea käyttäen ifstream
-virtoja:
// Vertaa tulosteiden ensimmäistä lukua ifstream fa("out_brute"), fb("out_koodi"); long a, b; fa >> a; fb >> b; if (a != b) { cout << "Virhe löytyi!" << endl; break; }
Jos ja kun brutetesteri löytää virheen, pysähtymisen jälkeen tiedostot syote
, out_brute
, out_koodi
vastaavat sitä syötettä, jolla virhe löytyi. Koodia voi siis ajaa samalla syötteellä uudestaan. Voi olla hyödyllistä ottaa syöte talteen, ettei vahingossa ylikirjoita sitä myöhemmin.
cp syote syote_rikki ./koodi < syote_rikki
Syötettä voi myös käyttää GDB:ssä (muista oikeat käännösliput, ks. GDB-ohje):
gdb koodi run < syote_rikki
Toinen hyvä kieli brutetesterin toteuttamisielle on Python. Alla esimerkki Python-pohjaisesta testeristä:
import os, random while True: with open("input", "w") as f: n = random.randint(1, 10) f.write(f"{n}\n") os.system("./koodi < input > out_koodi") os.system("./brute < input > out_brute") if os.system("diff -b out_koodi out_brute"): print(":(") exit()