# This is the old test generating code. # It has two defects: # (1) The size of a test case is not controllable. # (2) Simple tests get repeated a lot, which is useless. # #function leaf() { # n = int(rand()*8)+1 # printf substr("01xxxyyz", n, 1) #} #function expr() { # n = rand() # if (n < 0.5) { # leaf() # } else # if (n < 0.6) { # printf "~"; expr() # } else # if (n < 0.8) { # printf "("; expr(); printf "&"; expr(); printf ")" # } else # if (n < 0.9) { # printf "("; expr(); printf "|"; expr(); printf ")" # } else # if (n < 0.05) { # printf "("; expr(); printf ">"; expr(); printf ")" # } else { # printf "("; expr(); printf "="; expr(); printf ")" # } #} #function formula() { # expr() # printf ";\n" #} # #BEGIN { # for (i = 1; i <= 200; i++) formula() #} # # The new test generator works like this: # First, we choose the number of binary operators we want. # Second, we recursively pick a place to split, # generate the operands, choose an operator, and away we go! # Note: I use a Mawk extension, rand(N) = int(rand()*N)+1. function xrand(n) { return int(rand()*n) + 1 } function gen(n ,k ,l ,r) { if (n == 0) { r = substr("01abcdefabcdaba", xrand(15), 1) } else { k = xrand(n-1) l = gen(k) r = gen(n-k+1) r = "(" l substr("&&&&&&|||||^>>>=", xrand(16), 1) r ")" } while (rand() < 0.16) r = "~" r return r } # The other thing is that we keep track of what we generated # so that we don't generate the same test case twice. BEGIN { for (i = 0; i < 200; i++) { for (j = 0; j < 100; j++) { n = int(rand()^1.5 * 100) + 1 s = gen(n) print i, j, n, "'" s "'" # if (!(s in done)) break; } # if 100 tries to get a new test case failed, # generate the last duplicate anyway. done[s] = 1 print s ";" } }