commit
d251f7a79b
|
@ -20,6 +20,7 @@ SUBDIRS = doc progtest
|
|||
|
||||
path_src = src
|
||||
path_test = test
|
||||
path_aux = build-aux
|
||||
|
||||
# all source files will be run through hoxsl; see `applies' target
|
||||
apply_src := $(shell find "$(path_src)" "$(path_test)" \
|
||||
|
@ -49,6 +50,7 @@ applies: $(apply_dest)
|
|||
|
||||
test: check
|
||||
check: | applies
|
||||
for test in $(path_aux)/test/test-*; do ./$$test || exit 1; done
|
||||
$(path_test)/runner
|
||||
|
||||
progtest: FORCE
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Compiles a "magic" CSV file into a normal CSV
|
||||
#
|
||||
# Copyright (C) 2016 R-T Specialty, LLC.
|
||||
# Copyright (C) 2016, 2018 R-T Specialty, LLC.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -45,6 +45,28 @@
|
|||
##
|
||||
|
||||
|
||||
# Expand variable with its value, if any
|
||||
function expand_vars( s, value )
|
||||
{
|
||||
# attempt to parse variable (may expand into a range)
|
||||
if ( match( s, /^\$([a-zA-Z_-]+)$/, m ) )
|
||||
{
|
||||
value = vars[ m[1] ];
|
||||
|
||||
if ( value == "" )
|
||||
{
|
||||
print "error: unknown variable reference: `$" m[1] "'" > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
# Expand line
|
||||
function parseline( i, m, j, me, orig )
|
||||
{
|
||||
if ( i > NF )
|
||||
|
@ -55,6 +77,10 @@ function parseline( i, m, j, me, orig )
|
|||
|
||||
orig = $i
|
||||
|
||||
# expand variables before any processing so that expansions
|
||||
# can include any type of formatting
|
||||
$i = expand_vars( $i )
|
||||
|
||||
if ( match( $i, /^([0-9]+\/){2}[0-9]+$/, m ) )
|
||||
{
|
||||
cmd = "date --date=" $i " +%s"
|
||||
|
@ -78,17 +104,18 @@ function parseline( i, m, j, me, orig )
|
|||
return
|
||||
}
|
||||
|
||||
# attempt to parse variable (may expand into a range)
|
||||
if ( match( $i, /^\$([a-zA-Z_-]+)$/, m ) )
|
||||
{
|
||||
$i = vars[ m[1] ];
|
||||
}
|
||||
|
||||
# parse range
|
||||
if ( match( $i, /^([0-9]+)--([0-9]+)$/, m ) )
|
||||
if ( match( $i, /^([^-]+)--([^-]+)$/, m ) )
|
||||
{
|
||||
j = m[1]
|
||||
me = m[2]
|
||||
j = expand_vars( m[1] )
|
||||
me = expand_vars( m[2] )
|
||||
|
||||
if ( !match( j, /^[0-9]+$/ ) || !match( me, /^[0-9]+$/ ) )
|
||||
{
|
||||
print "error: invalid range: `" $i "'" > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
$i = j
|
||||
|
@ -117,7 +144,12 @@ BEGIN {
|
|||
|
||||
# lines that begin with a colon are variable definitions
|
||||
/^:/ {
|
||||
match( $0, /^:([a-zA-Z_-]+)=(.*?)$/, m )
|
||||
if ( !match( $0, /^:([a-zA-Z_-]+)=(.*?)$/, m ) )
|
||||
{
|
||||
print "error: invalid variable definition: `" $0 "'" > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
|
||||
vars[ m[1] ] = m[2]
|
||||
next
|
||||
}
|
||||
|
|
|
@ -0,0 +1,269 @@
|
|||
#!/bin/bash
|
||||
# Test csvm2csv
|
||||
#
|
||||
# Copyright (C) 2018 R-T Specialty, LLC.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
cd "$( dirname "$0" )"
|
||||
|
||||
|
||||
# just to ensure that we run all the tests
|
||||
declare -i testsum=0
|
||||
|
||||
|
||||
# Run test case with input and expected values
|
||||
run-test()
|
||||
{
|
||||
local -r input="${1?Missing input}"
|
||||
local -r expected="${2?Missing expected}"
|
||||
|
||||
((testsum++))
|
||||
|
||||
# SUT invocation
|
||||
declare -r given=$( ../csvm2csv < <( cat <<< "$input" ) )
|
||||
|
||||
test $? -eq 0 || return 1
|
||||
|
||||
# expected output
|
||||
diff <( cat <<< "$expected" ) <( cat <<< "$given" )
|
||||
}
|
||||
|
||||
|
||||
|
||||
test-comment()
|
||||
{
|
||||
local -r input='# comment before header should be removed
|
||||
header, line
|
||||
# this is also a comment
|
||||
1, 2
|
||||
# which should be ignored
|
||||
3, 4'
|
||||
|
||||
local -r expected='header,line
|
||||
1,2
|
||||
3,4'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-range()
|
||||
{
|
||||
declare -r input='header, line
|
||||
1--3, 2
|
||||
3--5, 4--6'
|
||||
|
||||
declare -r expected='header,line
|
||||
1,2
|
||||
2,2
|
||||
3,2
|
||||
3,4
|
||||
3,5
|
||||
3,6
|
||||
4,4
|
||||
4,5
|
||||
4,6
|
||||
5,4
|
||||
5,5
|
||||
5,6'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-delim()
|
||||
{
|
||||
declare -r input='header, line
|
||||
1;4, 2
|
||||
4;3, 6;9'
|
||||
|
||||
declare -r expected='header,line
|
||||
1,2
|
||||
4,2
|
||||
4,6
|
||||
4,9
|
||||
3,6
|
||||
3,9'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-var()
|
||||
{
|
||||
declare -r input='header, line
|
||||
:foo=1
|
||||
:bar_baz-quux=2
|
||||
$foo,1
|
||||
$bar_baz-quux,$foo'
|
||||
|
||||
declare -r expected='header,line
|
||||
1,1
|
||||
2,1'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-range-delim()
|
||||
{
|
||||
declare -r input='header, line
|
||||
1--3;5--6, 2'
|
||||
|
||||
declare -r expected='header,line
|
||||
1,2
|
||||
2,2
|
||||
3,2
|
||||
5,2
|
||||
6,2'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-var-in-range-delim()
|
||||
{
|
||||
declare -r input='header, line
|
||||
:foo=1
|
||||
:bar=3
|
||||
$foo--$bar, $foo;$bar'
|
||||
|
||||
declare -r expected='header,line
|
||||
1,1
|
||||
1,3
|
||||
2,1
|
||||
2,3
|
||||
3,1
|
||||
3,3'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-var-with-range-delim()
|
||||
{
|
||||
declare -r input='header, line
|
||||
:foo=1--2;4
|
||||
:bar=5
|
||||
$foo;$bar, 1'
|
||||
|
||||
declare -r expected='header,line
|
||||
1,1
|
||||
2,1
|
||||
4,1
|
||||
5,1'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-var-with-var()
|
||||
{
|
||||
declare -r input='header, line
|
||||
:foo=2
|
||||
:bar=4
|
||||
:range=$foo--$bar
|
||||
:baz=$range;$foo
|
||||
$baz, 5'
|
||||
|
||||
declare -r expected='header,line
|
||||
2,5
|
||||
3,5
|
||||
4,5
|
||||
2,5'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
# :foo=0 should be considered to be defined
|
||||
test-var-zero-ref()
|
||||
{
|
||||
declare -r input='header, line
|
||||
:foo=0
|
||||
$foo'
|
||||
|
||||
declare -r expected='header,line
|
||||
0'
|
||||
|
||||
run-test "$input" "$expected"
|
||||
}
|
||||
|
||||
|
||||
test-fail-unknown-var-ref()
|
||||
{
|
||||
((testsum++))
|
||||
|
||||
local -r result=$(
|
||||
../csvm2csv 2>&1 <<< '$undefined' \
|
||||
&& echo '(test failure: expected failure)'
|
||||
)
|
||||
|
||||
grep -q 'unknown.*\$undefined' <<< "$result" \
|
||||
|| return 1
|
||||
}
|
||||
|
||||
|
||||
test-fail-non-numeric-range()
|
||||
{
|
||||
((testsum++))
|
||||
|
||||
local -r result=$(
|
||||
../csvm2csv 2>&1 <<< 'A--Z' \
|
||||
&& echo '(test failure: expected failure)'
|
||||
)
|
||||
|
||||
grep -q 'invalid range.*A--Z' <<< "$result" \
|
||||
|| return 1
|
||||
}
|
||||
|
||||
|
||||
test-fail-invalid-var-dfn()
|
||||
{
|
||||
((testsum++))
|
||||
|
||||
local -r result=$(
|
||||
../csvm2csv 2>&1 <<< ':BAD@#=var' \
|
||||
&& echo '(test failure: expected failure)'
|
||||
)
|
||||
|
||||
grep -q 'invalid variable definition.*:BAD@#=var' <<< "$result" \
|
||||
|| return 1
|
||||
}
|
||||
|
||||
|
||||
test-comment \
|
||||
&& test-range \
|
||||
&& test-delim \
|
||||
&& test-var \
|
||||
&& test-range-delim \
|
||||
&& test-var-in-range-delim \
|
||||
&& test-var-with-range-delim \
|
||||
&& test-var-with-var \
|
||||
&& test-var-zero-ref \
|
||||
&& test-fail-unknown-var-ref \
|
||||
&& test-fail-non-numeric-range \
|
||||
&& test-fail-invalid-var-dfn \
|
||||
|| {
|
||||
echo 'csvm2csv test failed' >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# safety check
|
||||
test "$testsum" -eq 12 || {
|
||||
echo 'error: did not run all csvm2csv tests!' >&2
|
||||
exit 1
|
||||
}
|
Loading…
Reference in New Issue