| // 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) |
| } |
| } |
| |
| } |