1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package uuid
23
24 import (
25 "bytes"
26 "flag"
27 "fmt"
28 "io/ioutil"
29 "os"
30 "path/filepath"
31 "testing"
32 )
33
34
35 var codecTestData = []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
36
37
38 var codecTestUUID = UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
39
40 func TestFromBytes(t *testing.T) {
41 t.Run("Valid", func(t *testing.T) {
42 got, err := FromBytes(codecTestData)
43 if err != nil {
44 t.Fatal(err)
45 }
46 if got != codecTestUUID {
47 t.Fatalf("FromBytes(%x) = %v, want %v", codecTestData, got, codecTestUUID)
48 }
49 })
50 t.Run("Invalid", func(t *testing.T) {
51 var short [][]byte
52 for i := 0; i < len(codecTestData); i++ {
53 short = append(short, codecTestData[:i])
54 }
55 var long [][]byte
56 for i := 1; i < 17; i++ {
57 tmp := append(codecTestData, make([]byte, i)...)
58 long = append(long, tmp)
59 }
60 invalid := append(short, long...)
61 for _, b := range invalid {
62 got, err := FromBytes(b)
63 if err == nil {
64 t.Fatalf("FromBytes(%x): want err != nil, got %v", b, got)
65 }
66 }
67 })
68 }
69
70 func TestFromBytesOrNil(t *testing.T) {
71 t.Run("Invalid", func(t *testing.T) {
72 b := []byte{4, 8, 15, 16, 23, 42}
73 got := FromBytesOrNil(b)
74 if got != Nil {
75 t.Errorf("FromBytesOrNil(%x): got %v, want %v", b, got, Nil)
76 }
77 })
78 t.Run("Valid", func(t *testing.T) {
79 got := FromBytesOrNil(codecTestData)
80 if got != codecTestUUID {
81 t.Errorf("FromBytesOrNil(%x): got %v, want %v", codecTestData, got, codecTestUUID)
82 }
83 })
84
85 }
86
87 type fromStringTest struct {
88 input string
89 variant string
90 }
91
92
93 func (fst fromStringTest) Run(t *testing.T) {
94 t.Run(fst.variant, func(t *testing.T) {
95 got, err := FromString(fst.input)
96 if err != nil {
97 t.Fatalf("FromString(%q): %v", fst.input, err)
98 }
99 if want := codecTestUUID; got != want {
100 t.Fatalf("FromString(%q) = %v, want %v", fst.input, got, want)
101 }
102 })
103 }
104
105
106
107
108
109
110 var fromStringTests = []fromStringTest{
111 {
112 input: "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
113 variant: "Canonical",
114 },
115 {
116 input: "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
117 variant: "BracedCanonical",
118 },
119 {
120 input: "{6ba7b8109dad11d180b400c04fd430c8}",
121 variant: "BracedHashlike",
122 },
123 {
124 input: "6ba7b8109dad11d180b400c04fd430c8",
125 variant: "Hashlike",
126 },
127 {
128 input: "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8",
129 variant: "URNCanonical",
130 },
131 {
132 input: "urn:uuid:6ba7b8109dad11d180b400c04fd430c8",
133 variant: "URNHashlike",
134 },
135 }
136
137 var invalidFromStringInputs = []string{
138
139 "6ba7b810-9dad-11d1-80b4-00c04fd430c",
140 "6ba7b8109dad11d180b400c04fd430c",
141
142
143 "6ba7b8109dad11d180b400c04fd430q8",
144
145
146 "6ba7b810-9dad-11d1-80b4-00c04fd430c8=",
147 "6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
148 "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f",
149 "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8",
150
151
152 "ba7b8109dad11d180b400c04fd430c8}",
153 "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8",
154 "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
155 "uuid:urn:6ba7b810-9dad-11d1-80b4-00c04fd430c8",
156 "uuid:urn:6ba7b8109dad11d180b400c04fd430c8",
157 "6ba7b8109-dad-11d1-80b4-00c04fd430c8",
158 "6ba7b810-9dad1-1d1-80b4-00c04fd430c8",
159 "6ba7b810-9dad-11d18-0b4-00c04fd430c8",
160 "6ba7b810-9dad-11d1-80b40-0c04fd430c8",
161 "6ba7b810+9dad+11d1+80b4+00c04fd430c8",
162 "(6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
163 "{6ba7b810-9dad-11d1-80b4-00c04fd430c8>",
164 "zba7b810-9dad-11d1-80b4-00c04fd430c8",
165 "6ba7b810-9dad11d180b400c04fd430c8",
166 "6ba7b8109dad-11d180b400c04fd430c8",
167 "6ba7b8109dad11d1-80b400c04fd430c8",
168 "6ba7b8109dad11d180b4-00c04fd430c8",
169 }
170
171 func TestFromString(t *testing.T) {
172 t.Run("Valid", func(t *testing.T) {
173 for _, fst := range fromStringTests {
174 fst.Run(t)
175 }
176 })
177 t.Run("Invalid", func(t *testing.T) {
178 for _, s := range invalidFromStringInputs {
179 got, err := FromString(s)
180 if err == nil {
181 t.Errorf("FromString(%q): want err != nil, got %v", s, got)
182 }
183 }
184 })
185 }
186
187 func TestFromStringOrNil(t *testing.T) {
188 t.Run("Invalid", func(t *testing.T) {
189 s := "bad"
190 got := FromStringOrNil(s)
191 if got != Nil {
192 t.Errorf("FromStringOrNil(%q): got %v, want Nil", s, got)
193 }
194 })
195 t.Run("Valid", func(t *testing.T) {
196 s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
197 got := FromStringOrNil(s)
198 if got != codecTestUUID {
199 t.Errorf("FromStringOrNil(%q): got %v, want %v", s, got, codecTestUUID)
200 }
201 })
202 }
203
204 func TestMarshalBinary(t *testing.T) {
205 got, err := codecTestUUID.MarshalBinary()
206 if err != nil {
207 t.Fatal(err)
208 }
209 if !bytes.Equal(got, codecTestData) {
210 t.Fatalf("%v.MarshalBinary() = %x, want %x", codecTestUUID, got, codecTestData)
211 }
212 }
213
214 func TestMarshalText(t *testing.T) {
215 want := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
216 got, err := codecTestUUID.MarshalText()
217 if err != nil {
218 t.Fatal(err)
219 }
220 if !bytes.Equal(got, want) {
221 t.Errorf("%v.MarshalText(): got %s, want %s", codecTestUUID, got, want)
222 }
223 }
224
225 func TestDecodePlainWithWrongLength(t *testing.T) {
226 arg := []byte{'4', '2'}
227
228 u := UUID{}
229
230 if u.decodePlain(arg) == nil {
231 t.Errorf("%v.decodePlain(%q): should return error, but it did not", u, arg)
232 }
233 }
234
235 var stringBenchmarkSink string
236
237 func BenchmarkString(b *testing.B) {
238 for i := 0; i < b.N; i++ {
239 stringBenchmarkSink = codecTestUUID.String()
240 }
241 }
242
243 func BenchmarkFromBytes(b *testing.B) {
244 for i := 0; i < b.N; i++ {
245 FromBytes(codecTestData)
246 }
247 }
248
249 func BenchmarkFromString(b *testing.B) {
250 b.Run("canonical", func(b *testing.B) {
251 for i := 0; i < b.N; i++ {
252 FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
253 }
254 })
255 b.Run("urn", func(b *testing.B) {
256 for i := 0; i < b.N; i++ {
257 FromString("urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8")
258 }
259 })
260 b.Run("braced", func(b *testing.B) {
261 for i := 0; i < b.N; i++ {
262 FromString("{6ba7b810-9dad-11d1-80b4-00c04fd430c8}")
263 }
264 })
265 }
266
267 func BenchmarkMarshalBinary(b *testing.B) {
268 for i := 0; i < b.N; i++ {
269 codecTestUUID.MarshalBinary()
270 }
271 }
272
273 func BenchmarkMarshalText(b *testing.B) {
274 for i := 0; i < b.N; i++ {
275 codecTestUUID.MarshalText()
276 }
277 }
278
279 var seedFuzzCorpus = flag.Bool("seed_fuzz_corpus", false, "seed fuzz test corpus")
280
281 func TestSeedFuzzCorpus(t *testing.T) {
282
283 if !*seedFuzzCorpus {
284 t.Skip("seeding fuzz test corpus only on demand")
285 }
286 corpusDir := filepath.Join(".", "testdata", "corpus")
287 writeSeedFile := func(name, data string) error {
288 path := filepath.Join(corpusDir, name)
289 return ioutil.WriteFile(path, []byte(data), os.ModePerm)
290 }
291 for _, fst := range fromStringTests {
292 name := "seed_valid_" + fst.variant
293 if err := writeSeedFile(name, fst.input); err != nil {
294 t.Fatal(err)
295 }
296 }
297 for i, s := range invalidFromStringInputs {
298 name := fmt.Sprintf("seed_invalid_%d", i)
299 if err := writeSeedFile(name, s); err != nil {
300 t.Fatal(err)
301 }
302 }
303 }
304
View as plain text