github.com/searKing/golang/go@v1.2.74/strings/strings_test.go (about)

     1  // Copyright 2020 The searKing Author. 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 strings_test
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  	"unicode"
    11  	"unicode/utf8"
    12  	"unsafe"
    13  
    14  	"github.com/searKing/golang/go/strings"
    15  )
    16  
    17  type SliceContainsTest struct {
    18  	inputSS []string
    19  	inputTT []string
    20  	output  bool
    21  }
    22  
    23  var (
    24  	sliceContainsAnyTests = []SliceContainsTest{
    25  		{
    26  			[]string{"A", "B", "C", "D"},
    27  			nil,
    28  			true,
    29  		},
    30  		{
    31  			[]string{},
    32  			[]string{"E"},
    33  			false,
    34  		},
    35  		{
    36  			[]string{"A", "B", "C", "D"},
    37  			[]string{"A"},
    38  			true,
    39  		},
    40  		{
    41  			[]string{"A", "B", "C", "D"},
    42  			[]string{"A", "D"},
    43  			true,
    44  		},
    45  		{
    46  			[]string{"A", "B", "C", "D"},
    47  			[]string{"A", "E"},
    48  			true,
    49  		},
    50  		{
    51  			[]string{"A", "B", "C", "D"},
    52  			[]string{"E", "A"},
    53  			true,
    54  		},
    55  		{
    56  			[]string{"A", "B", "C", "D"},
    57  			[]string{"E"},
    58  			false,
    59  		},
    60  	}
    61  )
    62  
    63  func TestSliceContainsAny(t *testing.T) {
    64  	for n, test := range sliceContainsAnyTests {
    65  		out := strings.SliceContainsAny(test.inputSS, test.inputTT...)
    66  		if out != test.output {
    67  			t.Errorf("#%d: got %v; expected %v", n, out, test.output)
    68  		}
    69  	}
    70  }
    71  
    72  var (
    73  	sliceContainsTests = []SliceContainsTest{
    74  		{
    75  			[]string{"A", "B", "C", "D"},
    76  			nil,
    77  			true,
    78  		},
    79  		{
    80  			[]string{"A", "B", "C", "D"},
    81  			[]string{"A"},
    82  			true,
    83  		},
    84  		{
    85  			[]string{"A", "B", "C", "D"},
    86  			[]string{"A", "D"},
    87  			true,
    88  		},
    89  		{
    90  			[]string{"A", "B", "C", "D"},
    91  			[]string{"A", "E"},
    92  			false,
    93  		},
    94  		{
    95  			[]string{"A", "B", "C", "D"},
    96  			[]string{"E", "A"},
    97  			false,
    98  		},
    99  		{
   100  			[]string{"A", "B", "C", "D"},
   101  			[]string{"E"},
   102  			false,
   103  		},
   104  	}
   105  )
   106  
   107  func TestSliceContains(t *testing.T) {
   108  	for n, test := range sliceContainsTests {
   109  		out := strings.SliceContains(test.inputSS, test.inputTT...)
   110  		if out != test.output {
   111  			t.Errorf("#%d: got %v; expected %v", n, out, test.output)
   112  		}
   113  	}
   114  }
   115  
   116  func tenRunes(ch rune) string {
   117  	r := make([]rune, 10)
   118  	for i := range r {
   119  		r[i] = ch
   120  	}
   121  	return string(r)
   122  }
   123  
   124  func leadingTenRunes(lead, ch rune) string {
   125  	r := make([]rune, 10)
   126  	for i := range r {
   127  		if i == 0 {
   128  			if lead < 0 {
   129  				continue
   130  			}
   131  			r[i] = lead
   132  			continue
   133  		}
   134  		if ch < 0 {
   135  			continue
   136  		}
   137  		r[i] = ch
   138  	}
   139  	return string(r)
   140  }
   141  
   142  // User-defined self-inverse mapping function
   143  func rot13(r rune) rune {
   144  	step := rune(13)
   145  	if r >= 'a' && r <= 'z' {
   146  		return ((r - 'a' + step) % 26) + 'a'
   147  	}
   148  	if r >= 'A' && r <= 'Z' {
   149  		return ((r - 'A' + step) % 26) + 'A'
   150  	}
   151  	return r
   152  }
   153  
   154  func TestMapLeading(t *testing.T) {
   155  	// Run a couple of awful growth/shrinkage tests
   156  	a := tenRunes('a')
   157  	// 1.  Grow. This triggers two reallocations in Map.
   158  	maxRune := func(rune) rune { return unicode.MaxRune }
   159  	m := strings.MapLeading(maxRune, a)
   160  	expect := leadingTenRunes(unicode.MaxRune, 'a')
   161  	if m != expect {
   162  		t.Errorf("growing: expected %q got %q", expect, m)
   163  	}
   164  
   165  	// 2. Shrink
   166  	minRune := func(rune) rune { return 'a' }
   167  	m = strings.MapLeading(minRune, leadingTenRunes(unicode.MaxRune, 'a'))
   168  	expect = a
   169  	if m != expect {
   170  		t.Errorf("shrinking: expected %q got %q", expect, m)
   171  	}
   172  
   173  	// 3. Rot13
   174  	m = strings.MapLeading(rot13, "a to zed")
   175  	expect = "n to zed"
   176  	if m != expect {
   177  		t.Errorf("rot13: expected %q got %q", expect, m)
   178  	}
   179  
   180  	// 4. Rot13^2
   181  	m = strings.MapLeading(rot13, strings.MapLeading(rot13, "a to zed"))
   182  	expect = "a to zed"
   183  	if m != expect {
   184  		t.Errorf("rot13: expected %q got %q", expect, m)
   185  	}
   186  
   187  	// 5. Drop
   188  	dropNotLatin := func(r rune) rune {
   189  		if unicode.Is(unicode.Latin, r) {
   190  			return r
   191  		}
   192  		return -1
   193  	}
   194  	m = strings.MapLeading(dropNotLatin, "세계, Hello")
   195  	expect = "계, Hello"
   196  	if m != expect {
   197  		t.Errorf("drop: expected %q got %q", expect, m)
   198  	}
   199  
   200  	// 6. Identity
   201  	identity := func(r rune) rune {
   202  		return r
   203  	}
   204  	orig := "Input string that we expect not to be copied."
   205  	m = strings.MapLeading(identity, orig)
   206  	if (*reflect.StringHeader)(unsafe.Pointer(&orig)).Data !=
   207  		(*reflect.StringHeader)(unsafe.Pointer(&m)).Data {
   208  		t.Error("unexpected copy during identity map")
   209  	}
   210  
   211  	// 7. Handle invalid UTF-8 sequence
   212  	replaceNotLatin := func(r rune) rune {
   213  		if unicode.Is(unicode.Latin, r) {
   214  			return r
   215  		}
   216  		return utf8.RuneError
   217  	}
   218  	m = strings.MapLeading(replaceNotLatin, "中 Hello\255World")
   219  	expect = "\uFFFD Hello\255World"
   220  	if m != expect {
   221  		t.Errorf("replace invalid sequence: expected %q got %q", expect, m)
   222  	}
   223  
   224  	// 8. Check utf8.RuneSelf and utf8.MaxRune encoding
   225  	encode := func(r rune) rune {
   226  		switch r {
   227  		case utf8.RuneSelf:
   228  			return unicode.MaxRune
   229  		case unicode.MaxRune:
   230  			return utf8.RuneSelf
   231  		}
   232  		return r
   233  	}
   234  	s := string(rune(utf8.RuneSelf)) + string(utf8.MaxRune)
   235  	r := string(utf8.MaxRune) + string(utf8.MaxRune) // reverse of s
   236  	m = strings.MapLeading(encode, s)
   237  	if m != r {
   238  		t.Errorf("encoding not handled correctly: expected %q got %q", r, m)
   239  	}
   240  	m = strings.MapLeading(encode, r)
   241  	if m != s {
   242  		t.Errorf("encoding not handled correctly: expected %q got %q", s, m)
   243  	}
   244  
   245  	// 9. Check mapping occurs in the front, middle and back
   246  	trimSpaces := func(r rune) rune {
   247  		if unicode.IsSpace(r) {
   248  			return -1
   249  		}
   250  		return r
   251  	}
   252  	m = strings.MapLeading(trimSpaces, "   abc    123   ")
   253  	expect = "  abc    123   "
   254  	if m != expect {
   255  		t.Errorf("trimSpaces: expected %q got %q", expect, m)
   256  	}
   257  }
   258  
   259  func TestContainsAsciiVisual(t *testing.T) {
   260  	table := []struct {
   261  		Q string
   262  		R bool
   263  	}{
   264  		{
   265  			Q: string(rune(0x00)),
   266  			R: false,
   267  		},
   268  		{
   269  			Q: " ",
   270  			R: false,
   271  		},
   272  		{
   273  			Q: "!",
   274  			R: true,
   275  		},
   276  		{
   277  			Q: `"`,
   278  			R: true,
   279  		},
   280  		{
   281  			Q: "0",
   282  			R: true,
   283  		},
   284  		{
   285  			Q: ":",
   286  			R: true,
   287  		},
   288  		{
   289  			Q: "A",
   290  			R: true,
   291  		},
   292  		{
   293  			Q: "{",
   294  			R: true,
   295  		},
   296  		{
   297  			Q: "~",
   298  			R: true,
   299  		},
   300  		{
   301  			Q: string(rune(0xFF)),
   302  			R: false,
   303  		},
   304  	}
   305  
   306  	for i, test := range table {
   307  		qr := strings.ContainsAsciiVisual(test.Q)
   308  		if qr != test.R {
   309  			t.Errorf("#%d. got %t, want %t", i, qr, test.R)
   310  		}
   311  	}
   312  }
   313  
   314  func TestContainsOnlyAsciiVisual(t *testing.T) {
   315  	table := []struct {
   316  		Q string
   317  		R bool
   318  	}{
   319  		//{
   320  		//	Q: "123qwe<>?+_{",
   321  		//	R: true,
   322  		//},
   323  		{
   324  			Q: string(rune(0x00)) + "a",
   325  			R: false,
   326  		},
   327  		{
   328  			Q: string(rune(0xFF)) + "a",
   329  			R: false,
   330  		},
   331  	}
   332  
   333  	for i, test := range table {
   334  		qr := strings.ContainsOnlyAsciiVisual(test.Q)
   335  		if qr != test.R {
   336  			t.Errorf("#%d. got %t, want %t", i, qr, test.R)
   337  		}
   338  	}
   339  }
   340  
   341  func TestJoinRepeat(t *testing.T) {
   342  	table := []struct {
   343  		Q   string
   344  		sep string
   345  		n   int
   346  		R   string
   347  	}{
   348  		{
   349  			Q:   "a",
   350  			sep: ",",
   351  			n:   -1,
   352  			R:   "",
   353  		},
   354  		{
   355  			Q:   "a",
   356  			sep: ",",
   357  			n:   0,
   358  			R:   "",
   359  		},
   360  		{
   361  			Q:   "a",
   362  			sep: ",",
   363  			n:   1,
   364  			R:   "a",
   365  		},
   366  		{
   367  			Q:   "a",
   368  			sep: ",",
   369  			n:   10,
   370  			R:   "a,a,a,a,a,a,a,a,a,a",
   371  		},
   372  	}
   373  
   374  	for i, test := range table {
   375  		qr := strings.JoinRepeat(test.Q, test.sep, test.n)
   376  		if qr != test.R {
   377  			t.Errorf("#%d. got %q, want %q", i, qr, test.R)
   378  		}
   379  	}
   380  }
   381  
   382  func TestPadLeft(t *testing.T) {
   383  	table := []struct {
   384  		Q   string
   385  		pad string
   386  		n   int
   387  		R   string
   388  	}{
   389  		{
   390  			Q:   "a",
   391  			pad: "*",
   392  			n:   -1,
   393  			R:   "a",
   394  		},
   395  		{
   396  			Q:   "a",
   397  			pad: "*",
   398  			n:   10,
   399  			R:   "*********a",
   400  		},
   401  		{
   402  			Q:   "a",
   403  			pad: "*^",
   404  			n:   5,
   405  			R:   "*^*^a",
   406  		},
   407  		{
   408  			Q:   "a",
   409  			pad: "*^",
   410  			n:   6,
   411  			R:   "*^*^ a",
   412  		},
   413  	}
   414  
   415  	for i, test := range table {
   416  		qr := strings.PadLeft(test.Q, test.pad, test.n)
   417  		if qr != test.R {
   418  			t.Errorf("#%d. got %q, want %q", i, qr, test.R)
   419  		}
   420  	}
   421  }
   422  
   423  func TestPadRight(t *testing.T) {
   424  	table := []struct {
   425  		Q   string
   426  		pad string
   427  		n   int
   428  		R   string
   429  	}{
   430  		{
   431  			Q:   "a",
   432  			pad: "*",
   433  			n:   -1,
   434  			R:   "a",
   435  		},
   436  		{
   437  			Q:   "a",
   438  			pad: "*",
   439  			n:   1,
   440  			R:   "a",
   441  		},
   442  		{
   443  			Q:   "a",
   444  			pad: "*",
   445  			n:   10,
   446  			R:   "a*********",
   447  		},
   448  		{
   449  			Q:   "a",
   450  			pad: "*^",
   451  			n:   5,
   452  			R:   "a*^*^",
   453  		},
   454  		{
   455  			Q:   "a",
   456  			pad: "*^",
   457  			n:   6,
   458  			R:   "a *^*^",
   459  		},
   460  	}
   461  
   462  	for i, test := range table {
   463  		qr := strings.PadRight(test.Q, test.pad, test.n)
   464  		if qr != test.R {
   465  			t.Errorf("#%d. got %q, want %q", i, qr, test.R)
   466  		}
   467  	}
   468  }
   469  
   470  func TestReverseByByte(t *testing.T) {
   471  	table := []struct {
   472  		Q string
   473  		R string
   474  	}{
   475  		{
   476  			Q: "abc123",
   477  			R: "321cba",
   478  		},
   479  		{
   480  			Q: "Hello, 世界",
   481  			R: "\x8c\x95疸\xe4 ,olleH",
   482  		},
   483  	}
   484  
   485  	for i, test := range table {
   486  		qr := strings.ReverseByByte(test.Q)
   487  		if qr != test.R {
   488  			t.Errorf("#%d. got %q, want %q", i, qr, test.R)
   489  		}
   490  	}
   491  }
   492  
   493  func TestReverseByRune(t *testing.T) {
   494  	table := []struct {
   495  		Q string
   496  		R string
   497  	}{
   498  		{
   499  			Q: "abc123",
   500  			R: "321cba",
   501  		},
   502  		{
   503  			Q: "Hello, 世界",
   504  			R: "界世 ,olleH",
   505  		},
   506  	}
   507  
   508  	for i, test := range table {
   509  		qr := strings.ReverseByRune(test.Q)
   510  		if qr != test.R {
   511  			t.Errorf("#%d. got %q, want %q", i, qr, test.R)
   512  		}
   513  	}
   514  }
   515  
   516  func TestCountPrefix(t *testing.T) {
   517  	table := []struct {
   518  		Q string
   519  		p string
   520  		R int
   521  	}{
   522  		{
   523  			Q: "abc123",
   524  			p: "a",
   525  			R: 1,
   526  		},
   527  		{
   528  			Q: "世界, Hello",
   529  			p: "世界",
   530  			R: 1,
   531  		},
   532  		{
   533  			Q: "aaaabc123",
   534  			p: "a",
   535  			R: 4,
   536  		},
   537  		{
   538  			Q: "aaaabc123",
   539  			p: "aa",
   540  			R: 2,
   541  		},
   542  		{
   543  			Q: "aaaabc123",
   544  			p: "aaa",
   545  			R: 1,
   546  		},
   547  		{
   548  			Q: "aaaabc123",
   549  			p: "aaaa",
   550  			R: 1,
   551  		},
   552  		{
   553  			Q: "aaaabc123",
   554  			p: "aaaaa",
   555  			R: 0,
   556  		},
   557  	}
   558  
   559  	for i, test := range table {
   560  		qr := strings.CountPrefix(test.Q, test.p)
   561  		if qr != test.R {
   562  			t.Errorf("#%d. got %d, want %d", i, qr, test.R)
   563  		}
   564  	}
   565  }
   566  
   567  func TestCountSuffix(t *testing.T) {
   568  	table := []struct {
   569  		Q string
   570  		p string
   571  		R int
   572  	}{
   573  		{
   574  			Q: "abc123",
   575  			p: "3",
   576  			R: 1,
   577  		},
   578  		{
   579  			Q: "Hello, 世界",
   580  			p: "世界",
   581  			R: 1,
   582  		},
   583  		{
   584  			Q: "abc123333",
   585  			p: "3",
   586  			R: 4,
   587  		},
   588  		{
   589  			Q: "abc123333",
   590  			p: "33",
   591  			R: 2,
   592  		},
   593  		{
   594  			Q: "abc123333",
   595  			p: "333",
   596  			R: 1,
   597  		},
   598  		{
   599  			Q: "abc123333",
   600  			p: "3333",
   601  			R: 1,
   602  		},
   603  		{
   604  			Q: "abc123333",
   605  			p: "33333",
   606  			R: 0,
   607  		},
   608  	}
   609  
   610  	for i, test := range table {
   611  		qr := strings.CountSuffix(test.Q, test.p)
   612  		if qr != test.R {
   613  			t.Errorf("#%d. got %d, want %d", i, qr, test.R)
   614  		}
   615  	}
   616  }