ADDED:
* `stringsx` package
** `stringsx.Indent()`, to indent/prefix multiline strings
** `stringsx.Redact()`, to mask strings
** `stringsx.TrimLines()`, like strings.TrimSpace() but multiline
** `stringsx.TrimSpaceLeft()`, like strings.TrimSpace() but only to the
left of a string.
** `stringsx.TrimSpaceRight()`, like strings.TrimSpace() but only to the
right of a string.
452 lines
9.4 KiB
Go
452 lines
9.4 KiB
Go
package stringsx
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
type (
|
|
testIndentSet struct {
|
|
name string
|
|
orig string
|
|
indent string
|
|
lvl uint
|
|
ws bool
|
|
empty bool
|
|
tgt string
|
|
}
|
|
testRedactSet struct {
|
|
name string
|
|
orig string
|
|
leading uint
|
|
trailing uint
|
|
tgt string
|
|
newline bool
|
|
mask string // defaults to DefMaskStr.
|
|
}
|
|
testTrimLinesSet struct {
|
|
name string
|
|
orig string
|
|
left bool
|
|
right bool
|
|
tgt string
|
|
}
|
|
testTrimSet struct {
|
|
name string
|
|
orig string
|
|
tgt string
|
|
}
|
|
)
|
|
|
|
func TestIndent(t *testing.T) {
|
|
|
|
var out string
|
|
var tests []testIndentSet = []testIndentSet{
|
|
testIndentSet{
|
|
name: "standard, no trailing newline",
|
|
orig: "foo\nbar\nbaz",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: false,
|
|
empty: false,
|
|
tgt: "\tfoo\n\tbar\n\tbaz",
|
|
},
|
|
testIndentSet{
|
|
name: "standard, trailing newline",
|
|
orig: "foo\nbar\nbaz\n",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: false,
|
|
empty: false,
|
|
tgt: "\tfoo\n\tbar\n\tbaz\n",
|
|
},
|
|
testIndentSet{
|
|
name: "standard, trailing newline with empty",
|
|
orig: "foo\nbar\nbaz\n",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: false,
|
|
empty: true,
|
|
tgt: "\tfoo\n\tbar\n\tbaz\n\t",
|
|
},
|
|
testIndentSet{
|
|
name: "standard, trailing newline with ws",
|
|
orig: "foo\nbar\nbaz\n",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: true,
|
|
empty: false,
|
|
tgt: "\tfoo\n\tbar\n\tbaz\n",
|
|
},
|
|
testIndentSet{
|
|
name: "standard, trailing newline with ws and empty",
|
|
orig: "foo\nbar\nbaz\n",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: true,
|
|
empty: true,
|
|
tgt: "\tfoo\n\tbar\n\tbaz\n\t",
|
|
},
|
|
testIndentSet{
|
|
name: "standard, trailing ws newline with empty",
|
|
orig: "foo\nbar\nbaz\n ",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: false,
|
|
empty: true,
|
|
tgt: "\tfoo\n\tbar\n\tbaz\n ",
|
|
},
|
|
testIndentSet{
|
|
name: "standard, trailing ws newline with ws",
|
|
orig: "foo\nbar\nbaz\n ",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: true,
|
|
empty: false,
|
|
tgt: "\tfoo\n\tbar\n\tbaz\n\t ",
|
|
},
|
|
testIndentSet{
|
|
name: "standard, trailing ws newline with ws and empty",
|
|
orig: "foo\nbar\nbaz\n \n",
|
|
indent: "",
|
|
lvl: 1,
|
|
ws: true,
|
|
empty: true,
|
|
tgt: "\tfoo\n\tbar\n\tbaz\n\t \n\t",
|
|
},
|
|
testIndentSet{
|
|
name: "comment",
|
|
orig: "foo\nbar\nbaz",
|
|
indent: "# ",
|
|
lvl: 1,
|
|
ws: false,
|
|
empty: false,
|
|
tgt: "# foo\n# bar\n# baz",
|
|
},
|
|
}
|
|
|
|
for idx, ts := range tests {
|
|
out = Indent(ts.orig, ts.indent, ts.lvl, ts.ws, ts.empty)
|
|
if out == ts.tgt {
|
|
t.Logf("[%d] OK (%s): %#v: got %#v", idx, ts.name, ts.orig, out)
|
|
} else {
|
|
t.Errorf(
|
|
"[%d] FAIL (%s): %#v (len %d):\n"+
|
|
"\t\t\texpected (len %d): %#v\n"+
|
|
"\t\t\tgot (len %d): %#v\n"+
|
|
"\t\t%#v",
|
|
idx, ts.name, ts.orig, len(ts.orig),
|
|
len(ts.tgt), ts.tgt,
|
|
len(out), out,
|
|
ts,
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestRedact(t *testing.T) {
|
|
|
|
var out string
|
|
var tests []testRedactSet = []testRedactSet{
|
|
testRedactSet{
|
|
name: "empty in, empty out",
|
|
orig: "",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "",
|
|
},
|
|
testRedactSet{
|
|
name: "standard",
|
|
orig: "password",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "************************",
|
|
},
|
|
testRedactSet{
|
|
name: "standard with newline",
|
|
orig: "pass\nword",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "************\n************",
|
|
newline: true,
|
|
},
|
|
testRedactSet{
|
|
name: "standard with Windows newline",
|
|
orig: "pass\r\nword",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "************\r\n************",
|
|
newline: true,
|
|
},
|
|
testRedactSet{
|
|
name: "standard with newline without newlines",
|
|
orig: "pass\nword",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "***************************",
|
|
},
|
|
testRedactSet{
|
|
name: "single leading",
|
|
orig: "password",
|
|
leading: 1,
|
|
trailing: 0,
|
|
tgt: "p*********************",
|
|
},
|
|
testRedactSet{
|
|
name: "single trailing",
|
|
orig: "password",
|
|
leading: 0,
|
|
trailing: 1,
|
|
tgt: "*********************d",
|
|
},
|
|
testRedactSet{
|
|
name: "three leading",
|
|
orig: "password",
|
|
leading: 3,
|
|
trailing: 0,
|
|
tgt: "pas***************",
|
|
},
|
|
testRedactSet{
|
|
name: "three trailing",
|
|
orig: "password",
|
|
leading: 0,
|
|
trailing: 3,
|
|
tgt: "***************ord",
|
|
},
|
|
testRedactSet{
|
|
name: "three leading and trailing",
|
|
orig: "password",
|
|
leading: 3,
|
|
trailing: 3,
|
|
tgt: "pas******ord",
|
|
},
|
|
testRedactSet{
|
|
name: "unmask overflow leading",
|
|
orig: "password",
|
|
leading: 5,
|
|
trailing: 4,
|
|
tgt: "************************",
|
|
},
|
|
testRedactSet{
|
|
name: "unmask overflow trailing",
|
|
orig: "password",
|
|
leading: 4,
|
|
trailing: 5,
|
|
tgt: "************************",
|
|
},
|
|
testRedactSet{
|
|
name: "single mask",
|
|
orig: "password",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "********",
|
|
mask: "*",
|
|
},
|
|
testRedactSet{
|
|
name: "standard trailing newline with newlines",
|
|
orig: "password\n",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "************************\n",
|
|
newline: true,
|
|
},
|
|
testRedactSet{
|
|
name: "standard trailing newline without newlines",
|
|
orig: "password\n",
|
|
leading: 0,
|
|
trailing: 0,
|
|
tgt: "***************************",
|
|
},
|
|
}
|
|
|
|
for idx, ts := range tests {
|
|
out = Redact(ts.orig, ts.mask, ts.leading, ts.trailing, ts.newline)
|
|
if out == ts.tgt {
|
|
t.Logf("[%d] OK (%s): %#v: got %#v", idx, ts.name, ts.orig, out)
|
|
} else {
|
|
t.Errorf(
|
|
"[%d] FAIL (%s): %#v (len %d):\n"+
|
|
"\t\t\texpected (len %d): %#v\n"+
|
|
"\t\t\tgot (len %d): %#v\n"+
|
|
"\t\t%#v",
|
|
idx, ts.name, ts.orig, len(ts.orig),
|
|
len(ts.tgt), ts.tgt,
|
|
len(out), out,
|
|
ts,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTrimLines(t *testing.T) {
|
|
|
|
var out string
|
|
var tests []testTrimLinesSet = []testTrimLinesSet{
|
|
testTrimLinesSet{
|
|
name: "none",
|
|
orig: " foo \n bar \n baz ",
|
|
left: false,
|
|
right: false,
|
|
tgt: " foo \n bar \n baz ",
|
|
},
|
|
testTrimLinesSet{
|
|
name: "standard",
|
|
orig: " foo \n bar \n baz ",
|
|
left: true,
|
|
right: true,
|
|
tgt: "foo\nbar\nbaz",
|
|
},
|
|
testTrimLinesSet{
|
|
name: "left only",
|
|
orig: " foo \n bar \n baz ",
|
|
left: true,
|
|
right: false,
|
|
tgt: "foo \nbar \nbaz ",
|
|
},
|
|
testTrimLinesSet{
|
|
name: "right only",
|
|
orig: " foo \n bar \n baz ",
|
|
left: false,
|
|
right: true,
|
|
tgt: " foo\n bar\n baz",
|
|
},
|
|
testTrimLinesSet{
|
|
name: "standard, trailing newline",
|
|
orig: " foo \n bar \n baz \n",
|
|
left: true,
|
|
right: true,
|
|
tgt: "foo\nbar\nbaz\n",
|
|
},
|
|
testTrimLinesSet{
|
|
name: "left only, trailing newline",
|
|
orig: " foo \n bar \n baz \n",
|
|
left: true,
|
|
right: false,
|
|
tgt: "foo \nbar \nbaz \n",
|
|
},
|
|
testTrimLinesSet{
|
|
name: "right only, trailing newline",
|
|
orig: " foo \n bar \n baz \n",
|
|
left: false,
|
|
right: true,
|
|
tgt: " foo\n bar\n baz\n",
|
|
},
|
|
// Since there's no "non-space" boundary, both of these condition tests do the same thing.
|
|
testTrimLinesSet{
|
|
name: "left only, trailing newline and ws",
|
|
orig: " foo \n bar \n baz \n ",
|
|
left: true,
|
|
right: false,
|
|
tgt: "foo \nbar \nbaz \n",
|
|
},
|
|
testTrimLinesSet{
|
|
name: "right only, trailing newline and ws",
|
|
orig: " foo \n bar \n baz \n ",
|
|
left: false,
|
|
right: true,
|
|
tgt: " foo\n bar\n baz\n",
|
|
},
|
|
}
|
|
|
|
for idx, ts := range tests {
|
|
out = TrimLines(ts.orig, ts.left, ts.right)
|
|
if out == ts.tgt {
|
|
t.Logf("[%d] OK (%s): %#v: got %#v", idx, ts.name, ts.orig, out)
|
|
} else {
|
|
t.Errorf(
|
|
"[%d] FAIL (%s): %#v (len %d):\n"+
|
|
"\t\t\texpected (len %d): %#v\n"+
|
|
"\t\t\tgot (len %d): %#v\n"+
|
|
"\t\t%#v",
|
|
idx, ts.name, ts.orig, len(ts.orig),
|
|
len(ts.tgt), ts.tgt,
|
|
len(out), out,
|
|
ts,
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestTrimSpaceLeft(t *testing.T) {
|
|
|
|
var out string
|
|
var tests []testTrimSet = []testTrimSet{
|
|
testTrimSet{
|
|
name: "standard",
|
|
orig: " foo ",
|
|
tgt: "foo ",
|
|
},
|
|
testTrimSet{
|
|
name: "tabs",
|
|
orig: "\t\tfoo\t\t",
|
|
tgt: "foo\t\t",
|
|
},
|
|
testTrimSet{
|
|
name: "newlines",
|
|
orig: "\n\nfoo\n\n",
|
|
tgt: "foo\n\n",
|
|
},
|
|
}
|
|
|
|
for idx, ts := range tests {
|
|
out = TrimSpaceLeft(ts.orig)
|
|
if out == ts.tgt {
|
|
t.Logf("[%d] OK (%s): %#v: got %#v", idx, ts.name, ts.orig, out)
|
|
} else {
|
|
t.Errorf(
|
|
"[%d] FAIL (%s): %#v (len %d):\n"+
|
|
"\t\t\texpected (len %d): %#v\n"+
|
|
"\t\t\tgot (len %d): %#v\n"+
|
|
"\t\t%#v",
|
|
idx, ts.name, ts.orig, len(ts.orig),
|
|
len(ts.tgt), ts.tgt,
|
|
len(out), out,
|
|
ts,
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestTrimSpaceRight(t *testing.T) {
|
|
|
|
var out string
|
|
var tests []testTrimSet = []testTrimSet{
|
|
testTrimSet{
|
|
name: "standard",
|
|
orig: " foo ",
|
|
tgt: " foo",
|
|
},
|
|
testTrimSet{
|
|
name: "tabs",
|
|
orig: "\t\tfoo\t\t",
|
|
tgt: "\t\tfoo",
|
|
},
|
|
testTrimSet{
|
|
name: "newlines",
|
|
orig: "\n\nfoo\n\n",
|
|
tgt: "\n\nfoo",
|
|
},
|
|
}
|
|
|
|
for idx, ts := range tests {
|
|
out = TrimSpaceRight(ts.orig)
|
|
if out == ts.tgt {
|
|
t.Logf("[%d] OK (%s): %#v: got %#v", idx, ts.name, ts.orig, out)
|
|
} else {
|
|
t.Errorf(
|
|
"[%d] FAIL (%s): %#v (len %d):\n"+
|
|
"\t\t\texpected (len %d): %#v\n"+
|
|
"\t\t\tgot (len %d): %#v\n"+
|
|
"\t\t%#v",
|
|
idx, ts.name, ts.orig, len(ts.orig),
|
|
len(ts.tgt), ts.tgt,
|
|
len(out), out,
|
|
ts,
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|