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