github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/json/escape_test.gno (about)

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  	"unicode/utf8"
     7  )
     8  
     9  func TestHexToInt(t *testing.T) {
    10  	tests := []struct {
    11  		name string
    12  		c    byte
    13  		want int
    14  	}{
    15  		{"Digit 0", '0', 0},
    16  		{"Digit 9", '9', 9},
    17  		{"Uppercase A", 'A', 10},
    18  		{"Uppercase F", 'F', 15},
    19  		{"Lowercase a", 'a', 10},
    20  		{"Lowercase f", 'f', 15},
    21  		{"Invalid character1", 'g', badHex},
    22  		{"Invalid character2", 'G', badHex},
    23  		{"Invalid character3", 'z', badHex},
    24  	}
    25  
    26  	for _, tt := range tests {
    27  		t.Run(tt.name, func(t *testing.T) {
    28  			if got := h2i(tt.c); got != tt.want {
    29  				t.Errorf("h2i() = %v, want %v", got, tt.want)
    30  			}
    31  		})
    32  	}
    33  }
    34  
    35  func TestIsSurrogatePair(t *testing.T) {
    36  	testCases := []struct {
    37  		name     string
    38  		r        rune
    39  		expected bool
    40  	}{
    41  		{"high surrogate start", 0xD800, true},
    42  		{"high surrogate end", 0xDBFF, true},
    43  		{"low surrogate start", 0xDC00, true},
    44  		{"low surrogate end", 0xDFFF, true},
    45  		{"Non-surrogate", 0x0000, false},
    46  		{"Non-surrogate 2", 0xE000, false},
    47  	}
    48  
    49  	for _, tc := range testCases {
    50  		t.Run(tc.name, func(t *testing.T) {
    51  			if got := isSurrogatePair(tc.r); got != tc.expected {
    52  				t.Errorf("isSurrogate() = %v, want %v", got, tc.expected)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func TestCombineSurrogates(t *testing.T) {
    59  	testCases := []struct {
    60  		high, low rune
    61  		expected  rune
    62  	}{
    63  		{0xD83D, 0xDC36, 0x1F436}, // 🐶 U+1F436 DOG FACE
    64  		{0xD83D, 0xDE00, 0x1F600}, // 😀 U+1F600 GRINNING FACE
    65  		{0xD83C, 0xDF03, 0x1F303}, // 🌃 U+1F303 NIGHT WITH STARS
    66  	}
    67  
    68  	for _, tc := range testCases {
    69  		result := combineSurrogates(tc.high, tc.low)
    70  		if result != tc.expected {
    71  			t.Errorf("combineSurrogates(%U, %U) = %U; want %U", tc.high, tc.low, result, tc.expected)
    72  		}
    73  	}
    74  }
    75  
    76  func TestDecodeSingleUnicodeEscape(t *testing.T) {
    77  	testCases := []struct {
    78  		input    []byte
    79  		expected rune
    80  		isValid  bool
    81  	}{
    82  		// valid unicode escape sequences
    83  		{[]byte(`\u0041`), 'A', true},
    84  		{[]byte(`\u03B1`), 'α', true},
    85  		{[]byte(`\u00E9`), 'é', true}, // valid non-English character
    86  		{[]byte(`\u0021`), '!', true}, // valid special character
    87  		{[]byte(`\uFF11`), '1', true},
    88  		{[]byte(`\uD83D`), 0xD83D, true},
    89  		{[]byte(`\uDE03`), 0xDE03, true},
    90  
    91  		// invalid unicode escape sequences
    92  		{[]byte(`\u004`), utf8.RuneError, false},  // too short
    93  		{[]byte(`\uXYZW`), utf8.RuneError, false}, // invalid hex
    94  		{[]byte(`\u00G1`), utf8.RuneError, false}, // non-hex character
    95  	}
    96  
    97  	for _, tc := range testCases {
    98  		result, isValid := decodeSingleUnicodeEscape(tc.input)
    99  		if result != tc.expected || isValid != tc.isValid {
   100  			t.Errorf("decodeSingleUnicodeEscape(%s) = (%U, %v); want (%U, %v)", tc.input, result, isValid, tc.expected, tc.isValid)
   101  		}
   102  	}
   103  }
   104  
   105  func TestDecodeUnicodeEscape(t *testing.T) {
   106  	testCases := []struct {
   107  		input    string
   108  		expected rune
   109  		size     int
   110  	}{
   111  		{"\\u0041", 'A', 6},
   112  		{"\\u03B1", 'α', 6},
   113  		{"\\u1F600", 0x1F60, 6},
   114  		{"\\uD830\\uDE03", 0x1C203, 12},
   115  		{"\\uD800\\uDC00", 0x00010000, 12},
   116  
   117  		{"\\u004", utf8.RuneError, -1},
   118  		{"\\uXYZW", utf8.RuneError, -1},
   119  		{"\\uD83D\\u0041", utf8.RuneError, -1},
   120  	}
   121  
   122  	for _, tc := range testCases {
   123  		r, size := decodeUnicodeEscape([]byte(tc.input))
   124  		if r != tc.expected || size != tc.size {
   125  			t.Errorf("decodeUnicodeEscape(%q) = (%U, %d); want (%U, %d)", tc.input, r, size, tc.expected, tc.size)
   126  		}
   127  	}
   128  }
   129  
   130  func TestUnescapeToUTF8(t *testing.T) {
   131  	testCases := []struct {
   132  		input       []byte
   133  		expectedIn  int
   134  		expectedOut int
   135  		isError     bool
   136  	}{
   137  		// valid escape sequences
   138  		{[]byte(`\n`), 2, 1, false},
   139  		{[]byte(`\t`), 2, 1, false},
   140  		{[]byte(`\u0041`), 6, 1, false},
   141  		{[]byte(`\u03B1`), 6, 2, false},
   142  		{[]byte(`\uD830\uDE03`), 12, 4, false},
   143  
   144  		// invalid escape sequences
   145  		{[]byte(`\`), -1, -1, true},            // incomplete escape sequence
   146  		{[]byte(`\x`), -1, -1, true},           // invalid escape character
   147  		{[]byte(`\u`), -1, -1, true},           // incomplete unicode escape sequence
   148  		{[]byte(`\u004`), -1, -1, true},        // invalid unicode escape sequence
   149  		{[]byte(`\uXYZW`), -1, -1, true},       // invalid unicode escape sequence
   150  		{[]byte(`\uD83D\u0041`), -1, -1, true}, // invalid unicode escape sequence
   151  	}
   152  
   153  	for _, tc := range testCases {
   154  		input := make([]byte, len(tc.input))
   155  		copy(input, tc.input)
   156  		output := make([]byte, utf8.UTFMax)
   157  		inLen, outLen, err := processEscapedUTF8(input, output)
   158  		if (err != nil) != tc.isError {
   159  			t.Errorf("processEscapedUTF8(%q) = %v; want %v", tc.input, err, tc.isError)
   160  		}
   161  
   162  		if inLen != tc.expectedIn || outLen != tc.expectedOut {
   163  			t.Errorf("processEscapedUTF8(%q) = (%d, %d); want (%d, %d)", tc.input, inLen, outLen, tc.expectedIn, tc.expectedOut)
   164  		}
   165  	}
   166  }
   167  
   168  func TestUnescape(t *testing.T) {
   169  	testCases := []struct {
   170  		name     string
   171  		input    []byte
   172  		expected []byte
   173  	}{
   174  		{"NoEscape", []byte("hello world"), []byte("hello world")},
   175  		{"SingleEscape", []byte("hello\\nworld"), []byte("hello\nworld")},
   176  		{"MultipleEscapes", []byte("line1\\nline2\\r\\nline3"), []byte("line1\nline2\r\nline3")},
   177  		{"UnicodeEscape", []byte("snowman:\\u2603"), []byte("snowman:\u2603")},
   178  		{"Complex", []byte("tc\\n\\u2603\\r\\nend"), []byte("tc\n\u2603\r\nend")},
   179  	}
   180  
   181  	for _, tc := range testCases {
   182  		t.Run(tc.name, func(t *testing.T) {
   183  			output, _ := Unescape(tc.input, make([]byte, len(tc.input)+10))
   184  			if !bytes.Equal(output, tc.expected) {
   185  				t.Errorf("unescape(%q) = %q; want %q", tc.input, output, tc.expected)
   186  			}
   187  		})
   188  	}
   189  }
   190  
   191  func TestUnquoteBytes(t *testing.T) {
   192  	tests := []struct {
   193  		input    []byte
   194  		border   byte
   195  		expected []byte
   196  		ok       bool
   197  	}{
   198  		{[]byte("\"hello\""), '"', []byte("hello"), true},
   199  		{[]byte("'hello'"), '\'', []byte("hello"), true},
   200  		{[]byte("\"hello"), '"', nil, false},
   201  		{[]byte("hello\""), '"', nil, false},
   202  		{[]byte("\"he\\\"llo\""), '"', []byte("he\"llo"), true},
   203  		{[]byte("\"he\\nllo\""), '"', []byte("he\nllo"), true},
   204  		{[]byte("\"\""), '"', []byte(""), true},
   205  		{[]byte("''"), '\'', []byte(""), true},
   206  		{[]byte("\"\\u0041\""), '"', []byte("A"), true},
   207  		{[]byte(`"Hello, 世界"`), '"', []byte("Hello, 世界"), true},
   208  		{[]byte(`"Hello, \x80"`), '"', nil, false},
   209  	}
   210  
   211  	for _, tc := range tests {
   212  		result, pass := unquoteBytes(tc.input, tc.border)
   213  
   214  		if pass != tc.ok {
   215  			t.Errorf("unquoteBytes(%q) = %v; want %v", tc.input, pass, tc.ok)
   216  		}
   217  
   218  		if !bytes.Equal(result, tc.expected) {
   219  			t.Errorf("unquoteBytes(%q) = %q; want %q", tc.input, result, tc.expected)
   220  		}
   221  	}
   222  }