1// Copyright 2009 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
5package utf8string
6
7import (
8	"math/rand"
9	"testing"
10	"unicode/utf8"
11)
12
13var testStrings = []string{
14	"",
15	"abcd",
16	"☺☻☹",
17	"日a本b語ç日ð本Ê語þ日¥本¼語i日©",
18	"日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©",
19	"\x80\x80\x80\x80",
20}
21
22func TestScanForwards(t *testing.T) {
23	for _, s := range testStrings {
24		runes := []rune(s)
25		str := NewString(s)
26		if str.RuneCount() != len(runes) {
27			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
28			break
29		}
30		for i, expect := range runes {
31			got := str.At(i)
32			if got != expect {
33				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
34			}
35		}
36	}
37}
38
39func TestScanBackwards(t *testing.T) {
40	for _, s := range testStrings {
41		runes := []rune(s)
42		str := NewString(s)
43		if str.RuneCount() != len(runes) {
44			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
45			break
46		}
47		for i := len(runes) - 1; i >= 0; i-- {
48			expect := runes[i]
49			got := str.At(i)
50			if got != expect {
51				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
52			}
53		}
54	}
55}
56
57func randCount() int {
58	if testing.Short() {
59		return 100
60	}
61	return 100000
62}
63
64func TestRandomAccess(t *testing.T) {
65	for _, s := range testStrings {
66		if len(s) == 0 {
67			continue
68		}
69		runes := []rune(s)
70		str := NewString(s)
71		if str.RuneCount() != len(runes) {
72			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
73			break
74		}
75		for j := 0; j < randCount(); j++ {
76			i := rand.Intn(len(runes))
77			expect := runes[i]
78			got := str.At(i)
79			if got != expect {
80				t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got)
81			}
82		}
83	}
84}
85
86func TestRandomSliceAccess(t *testing.T) {
87	for _, s := range testStrings {
88		if len(s) == 0 || s[0] == '\x80' { // the bad-UTF-8 string fools this simple test
89			continue
90		}
91		runes := []rune(s)
92		str := NewString(s)
93		if str.RuneCount() != len(runes) {
94			t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount())
95			break
96		}
97		for k := 0; k < randCount(); k++ {
98			i := rand.Intn(len(runes))
99			j := rand.Intn(len(runes) + 1)
100			if i > j { // include empty strings
101				continue
102			}
103			expect := string(runes[i:j])
104			got := str.Slice(i, j)
105			if got != expect {
106				t.Errorf("%s[%d:%d]: expected %q got %q", s, i, j, expect, got)
107			}
108		}
109	}
110}
111
112func TestLimitSliceAccess(t *testing.T) {
113	for _, s := range testStrings {
114		str := NewString(s)
115		if str.Slice(0, 0) != "" {
116			t.Error("failure with empty slice at beginning")
117		}
118		nr := utf8.RuneCountInString(s)
119		if str.Slice(nr, nr) != "" {
120			t.Error("failure with empty slice at end")
121		}
122	}
123}
124