Commit 558e7fc3 authored by Russ Cox's avatar Russ Cox

various: avoid func compare

R=gri, r, bradfitz
CC=golang-dev
https://golang.org/cl/5371074
parent c017a829
...@@ -34,7 +34,7 @@ func addTestCases(t []testCase, fn func(*ast.File) bool) { ...@@ -34,7 +34,7 @@ func addTestCases(t []testCase, fn func(*ast.File) bool) {
func fnop(*ast.File) bool { return false } func fnop(*ast.File) bool { return false }
func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out string, fixed, ok bool) { func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string, mustBeGofmt bool) (out string, fixed, ok bool) {
file, err := parser.ParseFile(fset, desc, in, parserMode) file, err := parser.ParseFile(fset, desc, in, parserMode)
if err != nil { if err != nil {
t.Errorf("%s: parsing: %v", desc, err) t.Errorf("%s: parsing: %v", desc, err)
...@@ -46,7 +46,7 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out ...@@ -46,7 +46,7 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out
t.Errorf("%s: printing: %v", desc, err) t.Errorf("%s: printing: %v", desc, err)
return return
} }
if s := string(outb); in != s && fn != fnop { if s := string(outb); in != s && mustBeGofmt {
t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s", t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s",
desc, desc, in, desc, s) desc, desc, in, desc, s)
tdiff(t, in, s) tdiff(t, in, s)
...@@ -75,13 +75,13 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out ...@@ -75,13 +75,13 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out
func TestRewrite(t *testing.T) { func TestRewrite(t *testing.T) {
for _, tt := range testCases { for _, tt := range testCases {
// Apply fix: should get tt.Out. // Apply fix: should get tt.Out.
out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In) out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In, true)
if !ok { if !ok {
continue continue
} }
// reformat to get printing right // reformat to get printing right
out, _, ok = parseFixPrint(t, fnop, tt.Name, out) out, _, ok = parseFixPrint(t, fnop, tt.Name, out, false)
if !ok { if !ok {
continue continue
} }
...@@ -101,7 +101,7 @@ func TestRewrite(t *testing.T) { ...@@ -101,7 +101,7 @@ func TestRewrite(t *testing.T) {
} }
// Should not change if run again. // Should not change if run again.
out2, fixed2, ok := parseFixPrint(t, tt.Fn, tt.Name+" output", out) out2, fixed2, ok := parseFixPrint(t, tt.Fn, tt.Name+" output", out, true)
if !ok { if !ok {
continue continue
} }
......
...@@ -138,6 +138,7 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass ...@@ -138,6 +138,7 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
assign = make(map[string][]interface{}) assign = make(map[string][]interface{})
cfg1 := &TypeConfig{} cfg1 := &TypeConfig{}
*cfg1 = *cfg // make copy so we can add locally *cfg1 = *cfg // make copy so we can add locally
copied := false
// gather function declarations // gather function declarations
for _, decl := range f.Decls { for _, decl := range f.Decls {
...@@ -185,7 +186,8 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass ...@@ -185,7 +186,8 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
if cfg1.Type[s.Name.Name] != nil { if cfg1.Type[s.Name.Name] != nil {
break break
} }
if cfg1.Type == cfg.Type || cfg1.Type == nil { if !copied {
copied = true
// Copy map lazily: it's time. // Copy map lazily: it's time.
cfg1.Type = make(map[string]*Type) cfg1.Type = make(map[string]*Type)
for k, v := range cfg.Type { for k, v := range cfg.Type {
......
...@@ -662,48 +662,49 @@ func TestRunes(t *testing.T) { ...@@ -662,48 +662,49 @@ func TestRunes(t *testing.T) {
} }
type TrimTest struct { type TrimTest struct {
f func([]byte, string) []byte f string
in, cutset, out string in, cutset, out string
} }
var trimTests = []TrimTest{ var trimTests = []TrimTest{
{Trim, "abba", "a", "bb"}, {"Trim", "abba", "a", "bb"},
{Trim, "abba", "ab", ""}, {"Trim", "abba", "ab", ""},
{TrimLeft, "abba", "ab", ""}, {"TrimLeft", "abba", "ab", ""},
{TrimRight, "abba", "ab", ""}, {"TrimRight", "abba", "ab", ""},
{TrimLeft, "abba", "a", "bba"}, {"TrimLeft", "abba", "a", "bba"},
{TrimRight, "abba", "a", "abb"}, {"TrimRight", "abba", "a", "abb"},
{Trim, "<tag>", "<>", "tag"}, {"Trim", "<tag>", "<>", "tag"},
{Trim, "* listitem", " *", "listitem"}, {"Trim", "* listitem", " *", "listitem"},
{Trim, `"quote"`, `"`, "quote"}, {"Trim", `"quote"`, `"`, "quote"},
{Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"}, {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
//empty string tests //empty string tests
{Trim, "abba", "", "abba"}, {"Trim", "abba", "", "abba"},
{Trim, "", "123", ""}, {"Trim", "", "123", ""},
{Trim, "", "", ""}, {"Trim", "", "", ""},
{TrimLeft, "abba", "", "abba"}, {"TrimLeft", "abba", "", "abba"},
{TrimLeft, "", "123", ""}, {"TrimLeft", "", "123", ""},
{TrimLeft, "", "", ""}, {"TrimLeft", "", "", ""},
{TrimRight, "abba", "", "abba"}, {"TrimRight", "abba", "", "abba"},
{TrimRight, "", "123", ""}, {"TrimRight", "", "123", ""},
{TrimRight, "", "", ""}, {"TrimRight", "", "", ""},
{TrimRight, "☺\xc0", "☺", "☺\xc0"}, {"TrimRight", "☺\xc0", "☺", "☺\xc0"},
} }
func TestTrim(t *testing.T) { func TestTrim(t *testing.T) {
for _, tc := range trimTests { for _, tc := range trimTests {
actual := string(tc.f([]byte(tc.in), tc.cutset)) name := tc.f
var name string var f func([]byte, string) []byte
switch tc.f { switch name {
case Trim: case "Trim":
name = "Trim" f = Trim
case TrimLeft: case "TrimLeft":
name = "TrimLeft" f = TrimLeft
case TrimRight: case "TrimRight":
name = "TrimRight" f = TrimRight
default: default:
t.Error("Undefined trim function") t.Error("Undefined trim function %s", name)
} }
actual := string(f([]byte(tc.in), tc.cutset))
if actual != tc.out { if actual != tc.out {
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out) t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
} }
......
...@@ -48,8 +48,9 @@ const ( ...@@ -48,8 +48,9 @@ const (
type encoder struct { type encoder struct {
// w is the writer that compressed bytes are written to. // w is the writer that compressed bytes are written to.
w writer w writer
// write, bits, nBits and width are the state for converting a code stream // order, write, bits, nBits and width are the state for
// into a byte stream. // converting a code stream into a byte stream.
order Order
write func(*encoder, uint32) error write func(*encoder, uint32) error
bits uint32 bits uint32
nBits uint nBits uint
...@@ -213,7 +214,7 @@ func (e *encoder) Close() error { ...@@ -213,7 +214,7 @@ func (e *encoder) Close() error {
} }
// Write the final bits. // Write the final bits.
if e.nBits > 0 { if e.nBits > 0 {
if e.write == (*encoder).writeMSB { if e.order == MSB {
e.bits >>= 24 e.bits >>= 24
} }
if err := e.w.WriteByte(uint8(e.bits)); err != nil { if err := e.w.WriteByte(uint8(e.bits)); err != nil {
...@@ -249,6 +250,7 @@ func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser { ...@@ -249,6 +250,7 @@ func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser {
lw := uint(litWidth) lw := uint(litWidth)
return &encoder{ return &encoder{
w: bw, w: bw,
order: order,
write: write, write: write,
width: 1 + lw, width: 1 + lw,
litWidth: lw, litWidth: lw,
......
...@@ -227,7 +227,7 @@ func (d *decodeState) value(v reflect.Value) { ...@@ -227,7 +227,7 @@ func (d *decodeState) value(v reflect.Value) {
// d.scan thinks we're still at the beginning of the item. // d.scan thinks we're still at the beginning of the item.
// Feed in an empty string - the shortest, simplest value - // Feed in an empty string - the shortest, simplest value -
// so that it knows we got to the end of the value. // so that it knows we got to the end of the value.
if d.scan.step == stateRedo { if d.scan.redo {
panic("redo") panic("redo")
} }
d.scan.step(&d.scan, '"') d.scan.step(&d.scan, '"')
......
...@@ -80,6 +80,9 @@ type scanner struct { ...@@ -80,6 +80,9 @@ type scanner struct {
// on a 64-bit Mac Mini, and it's nicer to read. // on a 64-bit Mac Mini, and it's nicer to read.
step func(*scanner, int) int step func(*scanner, int) int
// Reached end of top-level value.
endTop bool
// Stack of what we're in the middle of - array values, object keys, object values. // Stack of what we're in the middle of - array values, object keys, object values.
parseState []int parseState []int
...@@ -87,6 +90,7 @@ type scanner struct { ...@@ -87,6 +90,7 @@ type scanner struct {
err error err error
// 1-byte redo (see undo method) // 1-byte redo (see undo method)
redo bool
redoCode int redoCode int
redoState func(*scanner, int) int redoState func(*scanner, int) int
...@@ -135,6 +139,8 @@ func (s *scanner) reset() { ...@@ -135,6 +139,8 @@ func (s *scanner) reset() {
s.step = stateBeginValue s.step = stateBeginValue
s.parseState = s.parseState[0:0] s.parseState = s.parseState[0:0]
s.err = nil s.err = nil
s.redo = false
s.endTop = false
} }
// eof tells the scanner that the end of input has been reached. // eof tells the scanner that the end of input has been reached.
...@@ -143,11 +149,11 @@ func (s *scanner) eof() int { ...@@ -143,11 +149,11 @@ func (s *scanner) eof() int {
if s.err != nil { if s.err != nil {
return scanError return scanError
} }
if s.step == stateEndTop { if s.endTop {
return scanEnd return scanEnd
} }
s.step(s, ' ') s.step(s, ' ')
if s.step == stateEndTop { if s.endTop {
return scanEnd return scanEnd
} }
if s.err == nil { if s.err == nil {
...@@ -166,8 +172,10 @@ func (s *scanner) pushParseState(p int) { ...@@ -166,8 +172,10 @@ func (s *scanner) pushParseState(p int) {
func (s *scanner) popParseState() { func (s *scanner) popParseState() {
n := len(s.parseState) - 1 n := len(s.parseState) - 1
s.parseState = s.parseState[0:n] s.parseState = s.parseState[0:n]
s.redo = false
if n == 0 { if n == 0 {
s.step = stateEndTop s.step = stateEndTop
s.endTop = true
} else { } else {
s.step = stateEndValue s.step = stateEndValue
} }
...@@ -269,6 +277,7 @@ func stateEndValue(s *scanner, c int) int { ...@@ -269,6 +277,7 @@ func stateEndValue(s *scanner, c int) int {
if n == 0 { if n == 0 {
// Completed top-level before the current byte. // Completed top-level before the current byte.
s.step = stateEndTop s.step = stateEndTop
s.endTop = true
return stateEndTop(s, c) return stateEndTop(s, c)
} }
if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') { if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
...@@ -606,16 +615,18 @@ func quoteChar(c int) string { ...@@ -606,16 +615,18 @@ func quoteChar(c int) string {
// undo causes the scanner to return scanCode from the next state transition. // undo causes the scanner to return scanCode from the next state transition.
// This gives callers a simple 1-byte undo mechanism. // This gives callers a simple 1-byte undo mechanism.
func (s *scanner) undo(scanCode int) { func (s *scanner) undo(scanCode int) {
if s.step == stateRedo { if s.redo {
panic("invalid use of scanner") panic("json: invalid use of scanner")
} }
s.redoCode = scanCode s.redoCode = scanCode
s.redoState = s.step s.redoState = s.step
s.step = stateRedo s.step = stateRedo
s.redo = true
} }
// stateRedo helps implement the scanner's 1-byte undo. // stateRedo helps implement the scanner's 1-byte undo.
func stateRedo(s *scanner, c int) int { func stateRedo(s *scanner, c int) int {
s.redo = false
s.step = s.redoState s.step = s.redoState
return s.redoCode return s.redoCode
} }
...@@ -24,7 +24,7 @@ func exportFilter(name string) bool { ...@@ -24,7 +24,7 @@ func exportFilter(name string) bool {
// it returns false otherwise. // it returns false otherwise.
// //
func FileExports(src *File) bool { func FileExports(src *File) bool {
return FilterFile(src, exportFilter) return filterFile(src, exportFilter, true)
} }
// PackageExports trims the AST for a Go package in place such that // PackageExports trims the AST for a Go package in place such that
...@@ -35,7 +35,7 @@ func FileExports(src *File) bool { ...@@ -35,7 +35,7 @@ func FileExports(src *File) bool {
// it returns false otherwise. // it returns false otherwise.
// //
func PackageExports(pkg *Package) bool { func PackageExports(pkg *Package) bool {
return FilterPackage(pkg, exportFilter) return filterPackage(pkg, exportFilter, true)
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -72,7 +72,7 @@ func fieldName(x Expr) *Ident { ...@@ -72,7 +72,7 @@ func fieldName(x Expr) *Ident {
return nil return nil
} }
func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) { func filterFieldList(fields *FieldList, filter Filter, export bool) (removedFields bool) {
if fields == nil { if fields == nil {
return false return false
} }
...@@ -93,8 +93,8 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) { ...@@ -93,8 +93,8 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
keepField = len(f.Names) > 0 keepField = len(f.Names) > 0
} }
if keepField { if keepField {
if filter == exportFilter { if export {
filterType(f.Type, filter) filterType(f.Type, filter, export)
} }
list[j] = f list[j] = f
j++ j++
...@@ -107,84 +107,84 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) { ...@@ -107,84 +107,84 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
return return
} }
func filterParamList(fields *FieldList, filter Filter) bool { func filterParamList(fields *FieldList, filter Filter, export bool) bool {
if fields == nil { if fields == nil {
return false return false
} }
var b bool var b bool
for _, f := range fields.List { for _, f := range fields.List {
if filterType(f.Type, filter) { if filterType(f.Type, filter, export) {
b = true b = true
} }
} }
return b return b
} }
func filterType(typ Expr, f Filter) bool { func filterType(typ Expr, f Filter, export bool) bool {
switch t := typ.(type) { switch t := typ.(type) {
case *Ident: case *Ident:
return f(t.Name) return f(t.Name)
case *ParenExpr: case *ParenExpr:
return filterType(t.X, f) return filterType(t.X, f, export)
case *ArrayType: case *ArrayType:
return filterType(t.Elt, f) return filterType(t.Elt, f, export)
case *StructType: case *StructType:
if filterFieldList(t.Fields, f) { if filterFieldList(t.Fields, f, export) {
t.Incomplete = true t.Incomplete = true
} }
return len(t.Fields.List) > 0 return len(t.Fields.List) > 0
case *FuncType: case *FuncType:
b1 := filterParamList(t.Params, f) b1 := filterParamList(t.Params, f, export)
b2 := filterParamList(t.Results, f) b2 := filterParamList(t.Results, f, export)
return b1 || b2 return b1 || b2
case *InterfaceType: case *InterfaceType:
if filterFieldList(t.Methods, f) { if filterFieldList(t.Methods, f, export) {
t.Incomplete = true t.Incomplete = true
} }
return len(t.Methods.List) > 0 return len(t.Methods.List) > 0
case *MapType: case *MapType:
b1 := filterType(t.Key, f) b1 := filterType(t.Key, f, export)
b2 := filterType(t.Value, f) b2 := filterType(t.Value, f, export)
return b1 || b2 return b1 || b2
case *ChanType: case *ChanType:
return filterType(t.Value, f) return filterType(t.Value, f, export)
} }
return false return false
} }
func filterSpec(spec Spec, f Filter) bool { func filterSpec(spec Spec, f Filter, export bool) bool {
switch s := spec.(type) { switch s := spec.(type) {
case *ValueSpec: case *ValueSpec:
s.Names = filterIdentList(s.Names, f) s.Names = filterIdentList(s.Names, f)
if len(s.Names) > 0 { if len(s.Names) > 0 {
if f == exportFilter { if export {
filterType(s.Type, f) filterType(s.Type, f, export)
} }
return true return true
} }
case *TypeSpec: case *TypeSpec:
if f(s.Name.Name) { if f(s.Name.Name) {
if f == exportFilter { if export {
filterType(s.Type, f) filterType(s.Type, f, export)
} }
return true return true
} }
if f != exportFilter { if !export {
// For general filtering (not just exports), // For general filtering (not just exports),
// filter type even if name is not filtered // filter type even if name is not filtered
// out. // out.
// If the type contains filtered elements, // If the type contains filtered elements,
// keep the declaration. // keep the declaration.
return filterType(s.Type, f) return filterType(s.Type, f, export)
} }
} }
return false return false
} }
func filterSpecList(list []Spec, f Filter) []Spec { func filterSpecList(list []Spec, f Filter, export bool) []Spec {
j := 0 j := 0
for _, s := range list { for _, s := range list {
if filterSpec(s, f) { if filterSpec(s, f, export) {
list[j] = s list[j] = s
j++ j++
} }
...@@ -200,9 +200,13 @@ func filterSpecList(list []Spec, f Filter) []Spec { ...@@ -200,9 +200,13 @@ func filterSpecList(list []Spec, f Filter) []Spec {
// filtering; it returns false otherwise. // filtering; it returns false otherwise.
// //
func FilterDecl(decl Decl, f Filter) bool { func FilterDecl(decl Decl, f Filter) bool {
return filterDecl(decl, f, false)
}
func filterDecl(decl Decl, f Filter, export bool) bool {
switch d := decl.(type) { switch d := decl.(type) {
case *GenDecl: case *GenDecl:
d.Specs = filterSpecList(d.Specs, f) d.Specs = filterSpecList(d.Specs, f, export)
return len(d.Specs) > 0 return len(d.Specs) > 0
case *FuncDecl: case *FuncDecl:
return f(d.Name.Name) return f(d.Name.Name)
...@@ -221,9 +225,13 @@ func FilterDecl(decl Decl, f Filter) bool { ...@@ -221,9 +225,13 @@ func FilterDecl(decl Decl, f Filter) bool {
// left after filtering; it returns false otherwise. // left after filtering; it returns false otherwise.
// //
func FilterFile(src *File, f Filter) bool { func FilterFile(src *File, f Filter) bool {
return filterFile(src, f, false)
}
func filterFile(src *File, f Filter, export bool) bool {
j := 0 j := 0
for _, d := range src.Decls { for _, d := range src.Decls {
if FilterDecl(d, f) { if filterDecl(d, f, export) {
src.Decls[j] = d src.Decls[j] = d
j++ j++
} }
...@@ -244,9 +252,13 @@ func FilterFile(src *File, f Filter) bool { ...@@ -244,9 +252,13 @@ func FilterFile(src *File, f Filter) bool {
// left after filtering; it returns false otherwise. // left after filtering; it returns false otherwise.
// //
func FilterPackage(pkg *Package, f Filter) bool { func FilterPackage(pkg *Package, f Filter) bool {
return filterPackage(pkg, f, false)
}
func filterPackage(pkg *Package, f Filter, export bool) bool {
hasDecls := false hasDecls := false
for _, src := range pkg.Files { for _, src := range pkg.Files {
if FilterFile(src, f) { if filterFile(src, f, export) {
hasDecls = true hasDecls = true
} }
} }
......
...@@ -9,7 +9,7 @@ package net ...@@ -9,7 +9,7 @@ package net
var supportsIPv6, supportsIPv4map = probeIPv6Stack() var supportsIPv6, supportsIPv4map = probeIPv6Stack()
func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) { func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
if filter == anyaddr { if filter == nil {
// We'll take any IP address, but since the dialing code // We'll take any IP address, but since the dialing code
// does not yet try multiple addresses, prefer to use // does not yet try multiple addresses, prefer to use
// an IPv4 address if possible. This is especially relevant // an IPv4 address if possible. This is especially relevant
...@@ -113,7 +113,7 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err error) { ...@@ -113,7 +113,7 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err error) {
// Try as an IP address. // Try as an IP address.
addr = ParseIP(host) addr = ParseIP(host)
if addr == nil { if addr == nil {
filter := anyaddr var filter func(IP) IP
if net != "" && net[len(net)-1] == '4' { if net != "" && net[len(net)-1] == '4' {
filter = ipv4only filter = ipv4only
} }
......
...@@ -489,46 +489,47 @@ func TestSpecialCase(t *testing.T) { ...@@ -489,46 +489,47 @@ func TestSpecialCase(t *testing.T) {
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) } func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
var trimTests = []struct { var trimTests = []struct {
f func(string, string) string f string
in, cutset, out string in, cutset, out string
}{ }{
{Trim, "abba", "a", "bb"}, {"Trim", "abba", "a", "bb"},
{Trim, "abba", "ab", ""}, {"Trim", "abba", "ab", ""},
{TrimLeft, "abba", "ab", ""}, {"TrimLeft", "abba", "ab", ""},
{TrimRight, "abba", "ab", ""}, {"TrimRight", "abba", "ab", ""},
{TrimLeft, "abba", "a", "bba"}, {"TrimLeft", "abba", "a", "bba"},
{TrimRight, "abba", "a", "abb"}, {"TrimRight", "abba", "a", "abb"},
{Trim, "<tag>", "<>", "tag"}, {"Trim", "<tag>", "<>", "tag"},
{Trim, "* listitem", " *", "listitem"}, {"Trim", "* listitem", " *", "listitem"},
{Trim, `"quote"`, `"`, "quote"}, {"Trim", `"quote"`, `"`, "quote"},
{Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"}, {"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
//empty string tests //empty string tests
{Trim, "abba", "", "abba"}, {"Trim", "abba", "", "abba"},
{Trim, "", "123", ""}, {"Trim", "", "123", ""},
{Trim, "", "", ""}, {"Trim", "", "", ""},
{TrimLeft, "abba", "", "abba"}, {"TrimLeft", "abba", "", "abba"},
{TrimLeft, "", "123", ""}, {"TrimLeft", "", "123", ""},
{TrimLeft, "", "", ""}, {"TrimLeft", "", "", ""},
{TrimRight, "abba", "", "abba"}, {"TrimRight", "abba", "", "abba"},
{TrimRight, "", "123", ""}, {"TrimRight", "", "123", ""},
{TrimRight, "", "", ""}, {"TrimRight", "", "", ""},
{TrimRight, "☺\xc0", "☺", "☺\xc0"}, {"TrimRight", "☺\xc0", "☺", "☺\xc0"},
} }
func TestTrim(t *testing.T) { func TestTrim(t *testing.T) {
for _, tc := range trimTests { for _, tc := range trimTests {
actual := tc.f(tc.in, tc.cutset) name := tc.f
var name string var f func(string, string) string
switch tc.f { switch name {
case Trim: case "Trim":
name = "Trim" f = Trim
case TrimLeft: case "TrimLeft":
name = "TrimLeft" f = TrimLeft
case TrimRight: case "TrimRight":
name = "TrimRight" f = TrimRight
default: default:
t.Error("Undefined trim function") t.Error("Undefined trim function %s", name)
} }
actual := f(tc.in, tc.cutset)
if actual != tc.out { if actual != tc.out {
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out) t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment