@ -3,6 +3,7 @@ package test
import (
"fmt"
"regexp"
"strconv"
"strings"
)
@ -31,6 +32,18 @@ func PipeGrep(expression string) Pipe {
} )
}
// LineCount counts the number of lines received
//
// This excludes empty lines.
func LineCount ( ) Pipe {
return CustomPipe ( func ( s string ) ( string , error ) {
lines := strings . FieldsFunc ( s , func ( r rune ) bool {
return r == '\n'
} )
return fmt . Sprintf ( "%d\n" , len ( lines ) ) , nil
} )
}
// Tester is the end of a pipe for testing purposes.
//
// Once multiple commands have been piped together in a pipeline, we can
@ -69,6 +82,72 @@ func EmptyInput() Tester {
} )
}
type op int
const (
eq op = iota
ne
gt
ge
lt
le
)
func ( op op ) String ( ) string {
switch op {
case eq :
return "=="
case ne :
return "!="
case gt :
return ">"
case ge :
return ">="
case lt :
return "<"
case le :
return "<="
}
panic ( fmt . Sprintf ( "Unknown operator %d" , op ) )
}
// IntCompare reads the input from the pipeline and compares it to a value using `op`
//
// If the input is not an int, this fails.
func IntCompare ( op op , value int ) Tester {
return CustomTester ( func ( in string ) error {
n , err := strconv . Atoi ( in )
if err != nil {
return fmt . Errorf ( "not an integer %q: %s" , in , err )
}
var result bool
switch op {
case eq :
result = n == value
case ne :
result = n != value
case gt :
result = n > value
case ge :
result = n >= value
case lt :
result = n < value
case le :
result = n <= value
default :
panic ( fmt . Sprintf ( "Unsupported operator %d, make sure the operation is implemented for IntCompare" , op ) )
}
if ! result {
return fmt . Errorf ( "comparison failed: %d %s %d -> %t" , n , op , value , result )
}
return nil
} )
}
// PipeChecker is a kind of checker that essentially lets users write mini
// gadgets that pipe inputs together, and compose those to end as a true/false
// statement, which translates to an error.