mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
190 lines
5.6 KiB
Go
190 lines
5.6 KiB
Go
// ================================================================
|
|
// Most Miller tests (thousands of them) are command-line-driven via
|
|
// mlr regtest. Here are some cases needing special focus.
|
|
// ================================================================
|
|
|
|
package lib
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
// ----------------------------------------------------------------
|
|
type tDataForHasCaptures struct {
|
|
replacement string
|
|
expectedHasCaptures bool
|
|
expectedMatrix [][]int
|
|
}
|
|
|
|
type tDataForSubGsub struct {
|
|
input string
|
|
sregex string
|
|
replacement string
|
|
expectedOutput string
|
|
}
|
|
|
|
type tDataForMatches struct {
|
|
input string
|
|
sregex string
|
|
expectedOutput bool
|
|
expectedCaptures []string
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
var dataForHasCaptures = []tDataForHasCaptures{
|
|
{"foo", false, nil},
|
|
{"\\0", true, [][]int{{0, 2, 0, 2}}},
|
|
{"\\3", true, [][]int{{0, 2, 0, 2}}},
|
|
{"\\34", true, [][]int{{0, 2, 0, 2}}},
|
|
{"abc\\1def\\2ghi", true, [][]int{{3, 5, 3, 5}, {8, 10, 8, 10}}},
|
|
}
|
|
|
|
var dataForSub = []tDataForSubGsub{
|
|
{"abcde", "c", "X", "abXde"},
|
|
{"abcde", "z", "X", "abcde"},
|
|
{"abcde", "[a-z]", "X", "Xbcde"},
|
|
{"abcde", "[A-Z]", "X", "abcde"},
|
|
|
|
{"abcde", "c", "X", "abXde"},
|
|
{"abcde", "z", "X", "abcde"},
|
|
{"abcde", "[a-z]", "X", "Xbcde"},
|
|
{"abcde", "[A-Z]", "X", "abcde"},
|
|
|
|
{"ab_cde", "(..)_(...)", "\\2\\1", "cdeab"},
|
|
{"ab_cde", "(..)_(...)", "\\2-\\1", "cde-ab"},
|
|
{"ab_cde", "(..)_(...)", "X\\2Y\\1Z", "XcdeYabZ"},
|
|
|
|
{"foofoofoo", "(f.o)", "b\\1r", "bfoorfoofoo"},
|
|
{"foofoofoo", "(f.*o)", "b\\1r", "bfoofoofoor"},
|
|
{"foofoofoo", "(f.o)", "b\\2r", "brfoofoo"},
|
|
{"foofoofoo", "(f.*o)", "b\\2r", "br"},
|
|
}
|
|
|
|
var dataForGsub = []tDataForSubGsub{
|
|
{"abcde", "c", "X", "abXde"},
|
|
{"abcde", "z", "X", "abcde"},
|
|
{"abcde", "[a-z]", "X", "XXXXX"},
|
|
{"abcde", "[A-Z]", "X", "abcde"},
|
|
{"abcde", "[c-d]", "X", "abXXe"},
|
|
|
|
{"abcde", "c", "X", "abXde"},
|
|
{"abcde", "z", "X", "abcde"},
|
|
{"abcde", "[a-z]", "X", "XXXXX"},
|
|
{"abcde", "[A-Z]", "X", "abcde"},
|
|
{"abcde", "[c-d]", "X", "abXXe"},
|
|
|
|
{"abacad", "a(.)", "<\\1>", "<b><c><d>"},
|
|
{"abacad", "a(.)", "<\\2>", "<><><>"},
|
|
}
|
|
|
|
var dataForMatches = []tDataForMatches{
|
|
{"abcde", "[A-Z]", false, []string{"", "", "", "", "", "", "", "", "", ""}},
|
|
{"abcde", "[a-z]", true, []string{"a", "", "", "", "", "", "", "", "", ""}},
|
|
{"...ab_cde...", "(..)_(...)", true, []string{"ab_cde", "ab", "cde", "", "", "", "", "", "", ""}},
|
|
{"...ab_cde...fg_hij...", "(..)_(...)", true, []string{"ab_cde", "ab", "cde", "", "", "", "", "", "", ""}},
|
|
{"foofoofoo", "(f.o)", true, []string{"foo", "foo", "", "", "", "", "", "", "", ""}},
|
|
{"foofoofoo", "(f.*o)", true, []string{"foofoofoo", "foofoofoo", "", "", "", "", "", "", "", ""}},
|
|
}
|
|
|
|
func TestRegexReplacementHasCaptures(t *testing.T) {
|
|
for i, entry := range dataForHasCaptures {
|
|
actualHasCaptures, actualMatrix := ReplacementHasCaptures(entry.replacement)
|
|
if actualHasCaptures != entry.expectedHasCaptures {
|
|
t.Fatalf("case %d replacement \"%s\" expected %v got %v\n",
|
|
i, entry.replacement, entry.expectedHasCaptures, actualHasCaptures,
|
|
)
|
|
}
|
|
if !compareMatrices(actualMatrix, entry.expectedMatrix) {
|
|
t.Fatalf("case %d replacement \"%s\" expected matrix %#v got %#v\n",
|
|
i, entry.replacement, entry.expectedMatrix, actualMatrix,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRegexSub(t *testing.T) {
|
|
for i, entry := range dataForSub {
|
|
actualOutput := RegexStringSub(entry.input, entry.sregex, entry.replacement)
|
|
if actualOutput != entry.expectedOutput {
|
|
t.Fatalf("case %d input \"%s\" sregex \"%s\" replacement \"%s\" expected \"%s\" got \"%s\"\n",
|
|
i, entry.input, entry.sregex, entry.replacement, entry.expectedOutput, actualOutput,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRegexGsub(t *testing.T) {
|
|
for i, entry := range dataForGsub {
|
|
actualOutput := RegexStringGsub(entry.input, entry.sregex, entry.replacement)
|
|
if actualOutput != entry.expectedOutput {
|
|
t.Fatalf("case %d input \"%s\" sregex \"%s\" replacement \"%s\" expected \"%s\" got \"%s\"\n",
|
|
i, entry.input, entry.sregex, entry.replacement, entry.expectedOutput, actualOutput,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRegexMatches(t *testing.T) {
|
|
for i, entry := range dataForMatches {
|
|
actualOutput, actualCaptures := RegexStringMatchWithCaptures(entry.input, entry.sregex)
|
|
if actualOutput != entry.expectedOutput {
|
|
t.Fatalf("case %d input \"%s\" sregex \"%s\" expected %v got %v\n",
|
|
i, entry.input, entry.sregex, entry.expectedOutput, actualOutput,
|
|
)
|
|
}
|
|
if !compareCaptures(actualCaptures, entry.expectedCaptures) {
|
|
t.Fatalf("case %d input \"%s\" sregex \"%s\" expected captures %#v got %#v\n",
|
|
i, entry.input, entry.sregex, entry.expectedCaptures, actualCaptures,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func compareMatrices(
|
|
actualMatrix [][]int,
|
|
expectedMatrix [][]int,
|
|
) bool {
|
|
if actualMatrix == nil && expectedMatrix == nil {
|
|
return true
|
|
}
|
|
if actualMatrix == nil || expectedMatrix == nil {
|
|
return false
|
|
}
|
|
if len(actualMatrix) != len(expectedMatrix) {
|
|
return false
|
|
}
|
|
for i := range expectedMatrix {
|
|
actualRow := actualMatrix[i]
|
|
expectedRow := expectedMatrix[i]
|
|
if len(actualRow) != len(expectedRow) {
|
|
return false
|
|
}
|
|
for j := range expectedRow {
|
|
if actualRow[j] != expectedRow[j] {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func compareCaptures(
|
|
actualCaptures []string,
|
|
expectedCaptures []string,
|
|
) bool {
|
|
if actualCaptures == nil && expectedCaptures == nil {
|
|
return true
|
|
}
|
|
if actualCaptures == nil || expectedCaptures == nil {
|
|
return false
|
|
}
|
|
if len(actualCaptures) != len(expectedCaptures) {
|
|
return false
|
|
}
|
|
for i := range expectedCaptures {
|
|
if actualCaptures[i] != expectedCaptures[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|