| // Copyright 2023 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| //go:build goexperiment.jsonv2 | |
| package jsonwire | |
| import ( | |
| "cmp" | |
| "slices" | |
| "testing" | |
| "unicode/utf16" | |
| "unicode/utf8" | |
| ) | |
| func TestQuoteRune(t *testing.T) { | |
| tests := []struct{ in, want string }{ | |
| {"x", `'x'`}, | |
| {"\n", `'\n'`}, | |
| {"'", `'\''`}, | |
| {"\xff", `'\xff'`}, | |
| {"💩", `'💩'`}, | |
| {"💩"[:1], `'\xf0'`}, | |
| {"\uffff", `'\uffff'`}, | |
| {"\U00101234", `'\U00101234'`}, | |
| } | |
| for _, tt := range tests { | |
| got := QuoteRune([]byte(tt.in)) | |
| if got != tt.want { | |
| t.Errorf("quoteRune(%q) = %s, want %s", tt.in, got, tt.want) | |
| } | |
| } | |
| } | |
| var compareUTF16Testdata = []string{"", "\r", "1", "f\xfe", "f\xfe\xff", "f\xff", "\u0080", "\u00f6", "\u20ac", "\U0001f600", "\ufb33"} | |
| func TestCompareUTF16(t *testing.T) { | |
| for i, si := range compareUTF16Testdata { | |
| for j, sj := range compareUTF16Testdata { | |
| got := CompareUTF16([]byte(si), []byte(sj)) | |
| want := cmp.Compare(i, j) | |
| if got != want { | |
| t.Errorf("CompareUTF16(%q, %q) = %v, want %v", si, sj, got, want) | |
| } | |
| } | |
| } | |
| } | |
| func FuzzCompareUTF16(f *testing.F) { | |
| for _, td1 := range compareUTF16Testdata { | |
| for _, td2 := range compareUTF16Testdata { | |
| f.Add([]byte(td1), []byte(td2)) | |
| } | |
| } | |
| // CompareUTF16Simple is identical to CompareUTF16, | |
| // but relies on naively converting a string to a []uint16 codepoints. | |
| // It is easy to verify as correct, but is slow. | |
| CompareUTF16Simple := func(x, y []byte) int { | |
| ux := utf16.Encode([]rune(string(x))) | |
| uy := utf16.Encode([]rune(string(y))) | |
| return slices.Compare(ux, uy) | |
| } | |
| f.Fuzz(func(t *testing.T, s1, s2 []byte) { | |
| // Compare the optimized and simplified implementations. | |
| got := CompareUTF16(s1, s2) | |
| want := CompareUTF16Simple(s1, s2) | |
| if got != want && utf8.Valid(s1) && utf8.Valid(s2) { | |
| t.Errorf("CompareUTF16(%q, %q) = %v, want %v", s1, s2, got, want) | |
| } | |
| }) | |
| } | |
| func TestTruncatePointer(t *testing.T) { | |
| tests := []struct{ in, want string }{ | |
| {"hello", "hello"}, | |
| {"/a/b/c", "/a/b/c"}, | |
| {"/a/b/c/d/e/f/g", "/a/b/…/f/g"}, | |
| {"supercalifragilisticexpialidocious", "super…cious"}, | |
| {"/supercalifragilisticexpialidocious/supercalifragilisticexpialidocious", "/supe…/…cious"}, | |
| {"/supercalifragilisticexpialidocious/supercalifragilisticexpialidocious/supercalifragilisticexpialidocious", "/supe…/…/…cious"}, | |
| {"/a/supercalifragilisticexpialidocious/supercalifragilisticexpialidocious", "/a/…/…cious"}, | |
| {"/supercalifragilisticexpialidocious/supercalifragilisticexpialidocious/b", "/supe…/…/b"}, | |
| {"/fizz/buzz/bazz", "/fizz/…/bazz"}, | |
| {"/fizz/buzz/bazz/razz", "/fizz/…/razz"}, | |
| {"/////////////////////////////", "/////…/////"}, | |
| {"/🎄❤️✨/🎁✅😊/🎅🔥⭐", "/🎄…/…/…⭐"}, | |
| } | |
| for _, tt := range tests { | |
| got := TruncatePointer(tt.in, 10) | |
| if got != tt.want { | |
| t.Errorf("TruncatePointer(%q) = %q, want %q", tt.in, got, tt.want) | |
| } | |
| } | |
| } |