Testando o código C ++ com comandos bash

1

Eu li um problema de programação e então escrevi código para ele. Mas eu pensei que meu algoritmo não estava funcionando direito, então eu escrevi outro pedaço de código que não era o ideal, mas, eu acho, correto.

Agora eu tenho cerca de 100 conjuntos de dados de entrada e saída e quero dar essa entrada para os dois programas C ++ e comparar as saídas. Se houver diferenças nas saídas, descobrirei se meu código não está correto.

Meu problema é que existem muitos casos de teste (cerca de 100) e as saídas são grandes arquivos de texto e não consigo verificá-los sozinhos. Gostaria de saber como posso fazer isso com funções e comandos do bash?

Meus arquivos de texto de entrada são input1.txt , input2.txt etc. Meus arquivos de texto de saída são semelhantes às entradas. Meus programas são escritos em C ++.

    
por hossein hosseinvand 08.01.2012 / 21:17

2 respostas

1

A melhor maneira de comparar arquivos de texto é com o comando diff :

diff output1.txt output1.txt

Para uma comparação de massa, você pode chamar diff em um loop:

for x in input*.txt; do
  slow-program <"$x" >"$x.out-slow"
  fast-program <"$x" >"$x.out-fast"
  diff "$x.out-slow" "$x.out-fast"
done

Se o snippet acima produzir alguma saída, seu programa rápido está com bugs. No bash / ksh / zsh, você não precisa armazenar os arquivos intermediários no disco. No entanto, isso não é necessariamente uma coisa boa, uma vez que é provável que seja útil inspecionar os diferentes resultados em seu próprio ritmo.

for x in input*.txt; do
  diff <(slow-program <"$x") <(fast-program <"$x")
done

Pode ser mais conveniente colocar entradas e saídas em diretórios separados e realizar um diff recursivo.

for x in inputs/*; do slow-program <"$x" >"slow/${x##*/}"; done
for x in inputs/*; do fast-program <"$x" >"fast/${x##*/}"; done
diff -ru slow fast

Minha recomendação seria escrever um makefile que executa os testes e executa as comparações (em destinos separados). (Use abas onde eu coloquei 8 espaços.)

all_test_inputs = $(wildcard input*.txt)  # relies on GNU make
%.out-slow: %.txt slow-program
        ./slow-program <$< >[email protected]
        mv [email protected] $@
%.out-fast: %.txt fast-program
        ./fast-program <$< >[email protected]
        mv [email protected] $@
%.diff: %.out-slow %.out-fast
        -diff $*.out-slow $*.out-fast >[email protected]
        mv [email protected] $@
# Test that all diff files are empty
test: $(all_test_inputs:%.txt=%.diff)
        for x in $^; do ! test -s "$x"; done
.PHONY: test

Execute make test para processar todos os arquivos de entrada (somente para os arquivos de entrada ou os programas que foram alterados desde a última vez) e compare os resultados. O comando será bem-sucedido se, e somente se, todos os testes forem executados corretamente e a saída de ambos os programas for idêntica em cada caso.

    
por 08.01.2012 / 22:52
1

Supondo que você tenha compilado seus programas como prog1 e prog2 e que eles produzam sua saída em stdout , você poderia fazer algo assim:

#! /bin/bash

for input in input*.txt ; do
  ./prog1 $input > $input.out1
  ./prog2 $input > $input.out2
  if cmp $input.out1 $input.out2 > /dev/null ; then
     echo Programs disagreed on $input
  else
     echo Programs agreed on $input
  fi
done

Isto compara o byte de arquivos de saída para byte. Você também pode usar diff para comparação.
A saída de todas as execuções será em arquivos chamados inputX.txt.out1 ou .out2 , para que você possa inspecionar os casos em que eles não correspondem.

    
por 08.01.2012 / 21:34

Tags