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()
