Coder Motor
Coder Motor

Reputation: 135

How To Loop through n Test cases In Makefile?

I want my Makefile to automate my testing for me. Basically I would have a bunch of test cases that my code runs on. I want the user to specify the number of test cases rather than that being hard coded in.

Basically I want something like this:

gcc main.c -o main

./main < test1.txt > output1.txt
./main < test2.txt > output2.txt
./main < test3.txt > output3.txt
./main < test4.txt > output4.txt
.
.
.
./main < test<n>.txt > output<n>.txt #for some value n

And turn it into something like this:

gcc main.c -o main

#of course this wouldn't be the syntax, but I just need the Makefile version of a loop, where all one has to do is change the n value 
for(int i = 0; i < n+1; i++){
   ./main < test<i>.txt > output<i>.txt;
}

Thanks :)

Upvotes: 2

Views: 711

Answers (1)

code_fodder
code_fodder

Reputation: 16361

Now updated to answer the question properly

What you might want to do (by the look of it) is have your makefile do various things for you:

# Target to build "main" its the first target and therefore the default 
# call "make" to run
main:
    @gcc main.c -o main

# Arbitrary max number of tests, can be overwritten by passing the variable in
NUM_TESTS=100
# Find all the tests, put them into an ordered list, then take the first 
# 1 to NUM_TESTS of them. Finally substitute test* for output*
TEST_OUTPUTS=$(subst test,output,$(wordlist 1,$(NUM_TESTS),$(sort $(wildcard test*.txt))))

# Target to do your testing, call "make test NUM_TESTS=3" or "make test" 
# to run all tests (up to 100).
.PHONY: test
test: $(TEST_OUTPUTS)

# Pattern rule to run each test - you don't call this directly
# Note: this has a dependency on main so if main is not built it 
# will get built first
output%.txt: test%.txt main
    @./main < $< > $@

# Target to clean up output files, call "make clean"
.PHONY: clean
clean:
    rm -f main
    rm -f $(TEST_OUTPUTS)

Use by:

  • make build - build main
  • make test - run all tests that are found upto 100 (the max can be changed)
  • make test NUM_TESTS=3 - run the first 3 tests (if they exist found)
  • make test NUM_TESTS=3 -j6 - same as before but run 6 parallel jobs (or use -j for as many parallel jobs as possible) - i.e. run the tests in parallel

Explanation: The pattern rule will generate a file output*.txt depending on the file test*.txt. But we want to call the rule outputX.txt for this we generate a list of output files by searching for all output files (in variable TEST_OUTPUTS) and then selecting the number of tests we want. We can do this by passing in a variable or if we don't pass in a variable then it does upto 100 tests (or whatever you set the maximum to be.

Note: I did not run this, so I would consider is to be pseudo code, but it should be pretty close)

Upvotes: 4

Related Questions