github.com/go-enjin/golang-org-x-text@v0.12.1-enjin.2/runes/cond_test.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runes
     6  
     7  import (
     8  	"strings"
     9  	"testing"
    10  	"unicode"
    11  
    12  	"github.com/go-enjin/golang-org-x-text/cases"
    13  	"github.com/go-enjin/golang-org-x-text/language"
    14  	"github.com/go-enjin/golang-org-x-text/transform"
    15  )
    16  
    17  var (
    18  	toUpper = cases.Upper(language.Und)
    19  	toLower = cases.Lower(language.Und)
    20  )
    21  
    22  type spanformer interface {
    23  	transform.SpanningTransformer
    24  }
    25  
    26  func TestPredicate(t *testing.T) {
    27  	testConditional(t, func(rt *unicode.RangeTable, t, f spanformer) spanformer {
    28  		return If(Predicate(func(r rune) bool {
    29  			return unicode.Is(rt, r)
    30  		}), t, f)
    31  	})
    32  }
    33  
    34  func TestIn(t *testing.T) {
    35  	testConditional(t, func(rt *unicode.RangeTable, t, f spanformer) spanformer {
    36  		return If(In(rt), t, f)
    37  	})
    38  }
    39  
    40  func TestNotIn(t *testing.T) {
    41  	testConditional(t, func(rt *unicode.RangeTable, t, f spanformer) spanformer {
    42  		return If(NotIn(rt), f, t)
    43  	})
    44  }
    45  
    46  func testConditional(t *testing.T, f func(rt *unicode.RangeTable, t, f spanformer) spanformer) {
    47  	lower := f(unicode.Latin, toLower, toLower)
    48  
    49  	for i, tt := range []transformTest{{
    50  		desc:    "empty",
    51  		szDst:   large,
    52  		atEOF:   true,
    53  		in:      "",
    54  		out:     "",
    55  		outFull: "",
    56  		t:       lower,
    57  	}, {
    58  		desc:    "small",
    59  		szDst:   1,
    60  		atEOF:   true,
    61  		in:      "B",
    62  		out:     "b",
    63  		outFull: "b",
    64  		errSpan: transform.ErrEndOfSpan,
    65  		t:       lower,
    66  	}, {
    67  		desc:    "short dst",
    68  		szDst:   2,
    69  		atEOF:   true,
    70  		in:      "AAA",
    71  		out:     "aa",
    72  		outFull: "aaa",
    73  		err:     transform.ErrShortDst,
    74  		errSpan: transform.ErrEndOfSpan,
    75  		t:       lower,
    76  	}, {
    77  		desc:    "short dst writing error",
    78  		szDst:   1,
    79  		atEOF:   false,
    80  		in:      "A\x80",
    81  		out:     "a",
    82  		outFull: "a\x80",
    83  		err:     transform.ErrShortDst,
    84  		errSpan: transform.ErrEndOfSpan,
    85  		t:       lower,
    86  	}, {
    87  		desc:    "short dst writing incomplete rune",
    88  		szDst:   2,
    89  		atEOF:   true,
    90  		in:      "Σ\xc2",
    91  		out:     "Σ",
    92  		outFull: "Σ\xc2",
    93  		err:     transform.ErrShortDst,
    94  		t:       f(unicode.Latin, toLower, nil),
    95  	}, {
    96  		desc:    "short dst, longer",
    97  		szDst:   5,
    98  		atEOF:   true,
    99  		in:      "Hellø",
   100  		out:     "Hell",
   101  		outFull: "Hellø",
   102  		err:     transform.ErrShortDst,
   103  		// idem is used to test short buffers by forcing processing of full-rune increments.
   104  		t: f(unicode.Latin, Map(idem), nil),
   105  	}, {
   106  		desc:    "short dst, longer, writing error",
   107  		szDst:   6,
   108  		atEOF:   false,
   109  		in:      "\x80Hello\x80",
   110  		out:     "\x80Hello",
   111  		outFull: "\x80Hello\x80",
   112  		err:     transform.ErrShortDst,
   113  		t:       f(unicode.Latin, Map(idem), nil),
   114  	}, {
   115  		desc:    "short src",
   116  		szDst:   2,
   117  		atEOF:   false,
   118  		in:      "A\xc2",
   119  		out:     "a",
   120  		outFull: "a\xc2",
   121  		err:     transform.ErrShortSrc,
   122  		errSpan: transform.ErrEndOfSpan,
   123  		t:       lower,
   124  	}, {
   125  		desc:    "short src no change",
   126  		szDst:   2,
   127  		atEOF:   false,
   128  		in:      "a\xc2",
   129  		out:     "a",
   130  		outFull: "a\xc2",
   131  		err:     transform.ErrShortSrc,
   132  		errSpan: transform.ErrShortSrc,
   133  		nSpan:   1,
   134  		t:       lower,
   135  	}, {
   136  		desc:    "invalid input, atEOF",
   137  		szDst:   large,
   138  		atEOF:   true,
   139  		in:      "\x80",
   140  		out:     "\x80",
   141  		outFull: "\x80",
   142  		t:       lower,
   143  	}, {
   144  		desc:    "invalid input, !atEOF",
   145  		szDst:   large,
   146  		atEOF:   false,
   147  		in:      "\x80",
   148  		out:     "\x80",
   149  		outFull: "\x80",
   150  		t:       lower,
   151  	}, {
   152  		desc:    "invalid input, incomplete rune atEOF",
   153  		szDst:   large,
   154  		atEOF:   true,
   155  		in:      "\xc2",
   156  		out:     "\xc2",
   157  		outFull: "\xc2",
   158  		t:       lower,
   159  	}, {
   160  		desc:    "nop",
   161  		szDst:   large,
   162  		atEOF:   true,
   163  		in:      "Hello World!",
   164  		out:     "Hello World!",
   165  		outFull: "Hello World!",
   166  		t:       f(unicode.Latin, nil, nil),
   167  	}, {
   168  		desc:    "nop in",
   169  		szDst:   large,
   170  		atEOF:   true,
   171  		in:      "THIS IS α ΤΕΣΤ",
   172  		out:     "this is α ΤΕΣΤ",
   173  		outFull: "this is α ΤΕΣΤ",
   174  		errSpan: transform.ErrEndOfSpan,
   175  		t:       f(unicode.Greek, nil, toLower),
   176  	}, {
   177  		desc:    "nop in latin",
   178  		szDst:   large,
   179  		atEOF:   true,
   180  		in:      "THIS IS α ΤΕΣΤ",
   181  		out:     "THIS IS α τεστ",
   182  		outFull: "THIS IS α τεστ",
   183  		errSpan: transform.ErrEndOfSpan,
   184  		t:       f(unicode.Latin, nil, toLower),
   185  	}, {
   186  		desc:    "nop not in",
   187  		szDst:   large,
   188  		atEOF:   true,
   189  		in:      "THIS IS α ΤΕΣΤ",
   190  		out:     "this is α ΤΕΣΤ",
   191  		outFull: "this is α ΤΕΣΤ",
   192  		errSpan: transform.ErrEndOfSpan,
   193  		t:       f(unicode.Latin, toLower, nil),
   194  	}, {
   195  		desc:    "pass atEOF is true when at end",
   196  		szDst:   large,
   197  		atEOF:   true,
   198  		in:      "hello",
   199  		out:     "HELLO",
   200  		outFull: "HELLO",
   201  		errSpan: transform.ErrEndOfSpan,
   202  		t:       f(unicode.Latin, upperAtEOF{}, nil),
   203  	}, {
   204  		desc:    "pass atEOF is true when at end of segment",
   205  		szDst:   large,
   206  		atEOF:   true,
   207  		in:      "hello ",
   208  		out:     "HELLO ",
   209  		outFull: "HELLO ",
   210  		errSpan: transform.ErrEndOfSpan,
   211  		t:       f(unicode.Latin, upperAtEOF{}, nil),
   212  	}, {
   213  		desc:    "don't pass atEOF is true when atEOF is false",
   214  		szDst:   large,
   215  		atEOF:   false,
   216  		in:      "hello",
   217  		out:     "",
   218  		outFull: "HELLO",
   219  		err:     transform.ErrShortSrc,
   220  		errSpan: transform.ErrShortSrc,
   221  		t:       f(unicode.Latin, upperAtEOF{}, nil),
   222  	}, {
   223  		desc:    "pass atEOF is true when at end, no change",
   224  		szDst:   large,
   225  		atEOF:   true,
   226  		in:      "HELLO",
   227  		out:     "HELLO",
   228  		outFull: "HELLO",
   229  		t:       f(unicode.Latin, upperAtEOF{}, nil),
   230  	}, {
   231  		desc:    "pass atEOF is true when at end of segment, no change",
   232  		szDst:   large,
   233  		atEOF:   true,
   234  		in:      "HELLO ",
   235  		out:     "HELLO ",
   236  		outFull: "HELLO ",
   237  		t:       f(unicode.Latin, upperAtEOF{}, nil),
   238  	}, {
   239  		desc:    "large input ASCII",
   240  		szDst:   12000,
   241  		atEOF:   false,
   242  		in:      strings.Repeat("HELLO", 2000),
   243  		out:     strings.Repeat("hello", 2000),
   244  		outFull: strings.Repeat("hello", 2000),
   245  		errSpan: transform.ErrEndOfSpan,
   246  		err:     nil,
   247  		t:       lower,
   248  	}, {
   249  		desc:    "large input non-ASCII",
   250  		szDst:   12000,
   251  		atEOF:   false,
   252  		in:      strings.Repeat("\u3333", 2000),
   253  		out:     strings.Repeat("\u3333", 2000),
   254  		outFull: strings.Repeat("\u3333", 2000),
   255  		err:     nil,
   256  		t:       lower,
   257  	}} {
   258  		tt.check(t, i)
   259  	}
   260  }
   261  
   262  // upperAtEOF is a strange Transformer that converts text to uppercase, but only
   263  // if atEOF is true.
   264  type upperAtEOF struct{ transform.NopResetter }
   265  
   266  func (upperAtEOF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
   267  	if !atEOF {
   268  		return 0, 0, transform.ErrShortSrc
   269  	}
   270  	return toUpper.Transform(dst, src, atEOF)
   271  }
   272  
   273  func (upperAtEOF) Span(src []byte, atEOF bool) (n int, err error) {
   274  	if !atEOF {
   275  		return 0, transform.ErrShortSrc
   276  	}
   277  	return toUpper.Span(src, atEOF)
   278  }
   279  
   280  func BenchmarkConditional(b *testing.B) {
   281  	doBench(b, If(In(unicode.Hangul), transform.Nop, transform.Nop))
   282  }