0

I am writing a testing script. It executes program with *.in files passed as input and compares its output with *.out files using diff command.

However, I don't want to print diff output, but to check if there is any and if so, then add *.in file name to the list of failed tests.

The problem is I have no idea how to check if command produces output without printing it.

My script now:

failed_tests=""

for filename in $directory/*.in; do

    command=< ${filename} ./${program} | diff - ${filename%.in}.out

    # Check if command produces output.
    if command; then
        # Add filename to failed tests list.
        failed_tests="${failed_tests} ${filename}"
    fi

done

echo $failed_tests

Thank you in advance for all the answers.

4 Answers 4

5

Your approach is doable, however you must capture $command in either `` or $(), also, $filename should act as input but not redirecting its contents. On the side note, you may want to remove the curly braces in the variable, it should work as long as the adjacent character is not a separator e.g. _

command=$(./$program $filename | diff - -q $filename%.in.out)

-q option in diff means to report only when .out is differ. if without square brackets only works with a program or command with exit status. e.g. grep

if [[ -n $command ]]; then
    # Add filename to failed tests list.
    failed_tests="$failed_tests $filename"
fi

-n option means not empty

Finally, the same approach outside of the loop:

if [[ -n $failed_tests ]]; then
    #do something here
fi
Sign up to request clarification or add additional context in comments.

3 Comments

Great answer. It worked and made me understand solution very quickly. On the side note, redirecting content is used in testing only and is necessary in this case. $program is my own program written in C and is meant gets commands from stdout with scanf(). It also has parameters, but they are responsible for other things. I understand you mean that generally, however, it should be done the other way, right?
Okay, if that's the case, your original $command should work, just remember to wrap around in `` or $() and add -q in your diff. command=$(<$filename ./program <param> | diff - -q $filename%.in.out)
A test such as -n $command should wrap the variable in double quotes, such as -n "$command", since if the variable is empty or undefined, it evaluates to nothing, and the -n then causes an error as it requires a parameter.
1

diff has an exit status of 0 if there are no differences, non-zero otherwise. You can use the -q option to suppress most output, and redirect the rest of it to /dev/null. Then, the if statement can test the exit status directly.

# Also, use an array to store a list of filenames
failed_tests=()
for filename in "$directory"/*.in; do
    if ./"$program" "$filename" | diff -q - "${filename%.in}.out" > /dev/null; then
        failed_tests+=( "$filename" )
    fi
done

1 Comment

It works, but the opposite way I needed. The condition equals true when there's no output, and equals false when there is. I just added '!' before it. if ! ./"$program" < "$filename" | diff -q - "${filename%.in}.out" > /dev/null; then Also, thanks for the array suggestion. It seems more elegant this way.
0

You can react on the output of diff -q with

if [ -n "$(diff -q file1 file2)" ]; then 
   echo different
fi

You want to compare the output of your prog, that is possible with process substitution:

if [ -n "$(diff -q $(command "${filename}") file2)" ]; then 
   echo different
fi

Comments

-2

To get output from command you can use varibale=$(command) or

variable=$`command`

Then you can use some simple condition on variable contents.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.