#!/bin/bash # This script expands test-matrix expressions into indiviual featuressets # # The basic element is a feature, which is just a name: # "a" == enable feature a # # A featureset is a comma separated list of features: # "a,b,c" == enable feature a, b and c # # A test-matrix is a list of featuresets to test and are specified by # separating featuresets by '+': # "a,b+a,c+e" == featuresets "a,b", "a,c" and "e" # # At any point in the expression where a feature is expected you can # instead specify an entire test-matrix by enclosing a sub-expression # in brackets. The result is the combinatorial combination of the # sub-test-matrix with the current featureset. # # For example: # # "a,{b+c}" == "a,b+a,c" # or: # "a,b,{c,d+e,f}" == "a,b,c,d+a,b,e,f" # # This can happen multiple times in an optionset which will fully expand all # instances: # "a,{b+c},{d+e}" == "a,{b+c},d+a,{b+c},e" == "a,b,d+a,c,d+a,{b+c},e" == "a,b,d+a,c,d+a,b,e+a,c,e" # # # The common way to use this is to either list all the options to instance the test for each case: # foo+bar+gazonk # Or to create all combination of features: # {foo+nofoo},{bar+nobar} tokens=( ) current_token="" function next_token { if [ ${#tokens[@]} -eq 0 ]; then current_token="$" else current_token=${tokens[0]} tokens=("${tokens[@]:1}") fi } parse_res="" function parse { local res=( ) local cur=( ) while true; do next_token local t=$current_token if [ $t == "}" -o $t == "$" ]; then break; elif [ $t == "{" ]; then parse local sub=$parse_res if [ ${#cur} -eq 0 ]; then cur=( ${sub[@]} ) else local sub_res=( ) for left in "${cur[@]}"; do for right in $sub; do sub_res+=("$left,$right") done done cur=( ${sub_res[@]} ) fi elif [ $t == "+" ]; then res+=( "${cur[@]}" ) cur=( ) else # ,t if [ ${#cur} -eq 0 ]; then cur=( $t ) else for i in "${!cur[@]}"; do cur[$i]="${cur[$i]:+${cur[$i]},}$t" done fi fi done if [ ${#cur} -ne 0 ]; then res+=( "${cur[@]}" ) fi parse_res="${res[@]}" } tests="" dist_tests="" extra_dist_tests="" function parse_test { if [[ $1 =~ ^(.*).sh\{(.*)\}$ ]]; then tokens=( $(awk -v RS='[{}+,]' '{if ($0 != "" && $0 != "\n") print $0; if (RT != "" && RT != ",") print RT}' <<< "${BASH_REMATCH[2]}") ) parse for r in $parse_res; do tests="$tests ${BASH_REMATCH[1]}@$r.wrap" done extra_dist_tests="$extra_dist_tests ${BASH_REMATCH[1]}.sh" else dist_tests="$dist_tests $1" fi } for test in $1; do parse_test $test done echo "# This file is autogenerated by make update-test-matrix, don't edit" echo "TEST_MATRIX= \\" for f in $tests; do echo " ${f} \\" done echo " \$(NULL)" echo "TEST_MATRIX_DIST= \\" for f in $dist_tests; do echo " ${f} \\" done echo " \$(NULL)" echo "TEST_MATRIX_EXTRA_DIST= \\" for f in $extra_dist_tests; do echo " ${f} \\" done echo " \$(NULL)"