github.com/segmentio/encoding@v0.4.0/json/parse_test.go (about)

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"strings"
     6  	"testing"
     7  )
     8  
     9  func TestParseString(t *testing.T) {
    10  	tests := []struct {
    11  		in  string
    12  		out string
    13  		ext string
    14  		err string
    15  	}{
    16  		{`""`, `""`, ``, ``},
    17  		{`"1234567890"`, `"1234567890"`, ``, ``},
    18  		{`"Hello World!"`, `"Hello World!"`, ``, ``},
    19  		{`"Hello\"World!"`, `"Hello\"World!"`, ``, ``},
    20  		{`"\\"`, `"\\"`, ``, ``},
    21  		{`"\u0061\u0062\u0063"`, `"\u0061\u0062\u0063"`, ``, ``},
    22  		{`"\u0"`, ``, ``, `json: unicode code point must have at least 4 characters: 0"`},
    23  	}
    24  
    25  	d := decoder{}
    26  	for _, test := range tests {
    27  		t.Run(test.in, func(t *testing.T) {
    28  			out, ext, _, err := d.parseString([]byte(test.in))
    29  
    30  			if test.err == "" {
    31  				if err != nil {
    32  					t.Errorf("%s => %s", test.in, err)
    33  					return
    34  				}
    35  			} else {
    36  				if s := err.Error(); s != test.err {
    37  					t.Error("invalid error")
    38  					t.Logf("expected: %s", test.err)
    39  					t.Logf("found:    %s", s)
    40  				}
    41  			}
    42  
    43  			if s := string(out); s != test.out {
    44  				t.Error("invalid output")
    45  				t.Logf("expected: %s", test.out)
    46  				t.Logf("found:    %s", s)
    47  			}
    48  
    49  			if s := string(ext); s != test.ext {
    50  				t.Error("invalid extra bytes")
    51  				t.Logf("expected: %s", test.ext)
    52  				t.Logf("found:    %s", s)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func TestParseStringUnquote(t *testing.T) {
    59  	tests := []struct {
    60  		in  string
    61  		out string
    62  		ext string
    63  	}{
    64  		{`""`, ``, ``},
    65  		{`"1234567890"`, `1234567890`, ``},
    66  		{`"Hello World!"`, `Hello World!`, ``},
    67  		{`"Hello\"World!"`, `Hello"World!`, ``},
    68  		{`"\\"`, `\`, ``},
    69  		{`"\u0061\u0062\u0063"`, `abc`, ``},
    70  	}
    71  
    72  	d := decoder{}
    73  	for _, test := range tests {
    74  		t.Run(test.in, func(t *testing.T) {
    75  			out, ext, _, err := d.parseStringUnquote([]byte(test.in), nil)
    76  
    77  			if err != nil {
    78  				t.Errorf("%s => %s", test.in, err)
    79  				return
    80  			}
    81  
    82  			if s := string(out); s != test.out {
    83  				t.Error("invalid output")
    84  				t.Logf("expected: %s", test.out)
    85  				t.Logf("found:    %s", s)
    86  			}
    87  
    88  			if s := string(ext); s != test.ext {
    89  				t.Error("invalid extra bytes")
    90  				t.Logf("expected: %s", test.ext)
    91  				t.Logf("found:    %s", s)
    92  			}
    93  		})
    94  	}
    95  }
    96  
    97  func TestAppendToLower(t *testing.T) {
    98  	tests := []string{
    99  		"",
   100  		"A",
   101  		"a",
   102  		"__segment_internal",
   103  		"someFieldWithALongBName",
   104  		"Hello World!",
   105  		"Hello\"World!",
   106  		"Hello\\World!",
   107  		"Hello\nWorld!",
   108  		"Hello\rWorld!",
   109  		"Hello\tWorld!",
   110  		"Hello\bWorld!",
   111  		"Hello\fWorld!",
   112  		"你好",
   113  		"<",
   114  		">",
   115  		"&",
   116  		"\u001944",
   117  		"\u00c2e>",
   118  		"\u00c2V?",
   119  		"\u000e=8",
   120  		"\u001944\u00c2e>\u00c2V?\u000e=8",
   121  		"ir\u001bQJ\u007f\u0007y\u0015)",
   122  	}
   123  
   124  	for _, test := range tests {
   125  		s1 := strings.ToLower(test)
   126  		s2 := string(appendToLower(nil, []byte(test)))
   127  
   128  		if s1 != s2 {
   129  			t.Error("lowercase values mismatch")
   130  			t.Log("expected:", s1)
   131  			t.Log("found:   ", s2)
   132  		}
   133  	}
   134  }
   135  
   136  func BenchmarkParseString(b *testing.B) {
   137  	s := []byte(`"__segment_internal"`)
   138  
   139  	d := decoder{}
   140  	for i := 0; i != b.N; i++ {
   141  		d.parseString(s)
   142  	}
   143  }
   144  
   145  func BenchmarkToLower(b *testing.B) {
   146  	s := []byte("someFieldWithALongName")
   147  
   148  	for i := 0; i != b.N; i++ {
   149  		bytes.ToLower(s)
   150  	}
   151  }
   152  
   153  func BenchmarkAppendToLower(b *testing.B) {
   154  	a := []byte(nil)
   155  	s := []byte("someFieldWithALongName")
   156  
   157  	for i := 0; i != b.N; i++ {
   158  		a = appendToLower(a[:0], s)
   159  	}
   160  }
   161  
   162  var benchmarkHasPrefixString = []byte("some random string")
   163  var benchmarkHasPrefixResult = false
   164  
   165  func BenchmarkHasPrefix(b *testing.B) {
   166  	for i := 0; i < b.N; i++ {
   167  		benchmarkHasPrefixResult = hasPrefix(benchmarkHasPrefixString, "null")
   168  	}
   169  }
   170  
   171  func BenchmarkHasNullPrefix(b *testing.B) {
   172  	for i := 0; i < b.N; i++ {
   173  		benchmarkHasPrefixResult = hasNullPrefix(benchmarkHasPrefixString)
   174  	}
   175  }
   176  
   177  func BenchmarkHasTruePrefix(b *testing.B) {
   178  	for i := 0; i < b.N; i++ {
   179  		benchmarkHasPrefixResult = hasTruePrefix(benchmarkHasPrefixString)
   180  	}
   181  }
   182  
   183  func BenchmarkHasFalsePrefix(b *testing.B) {
   184  	for i := 0; i < b.N; i++ {
   185  		benchmarkHasPrefixResult = hasFalsePrefix(benchmarkHasPrefixString)
   186  	}
   187  }
   188  
   189  func BenchmarkParseStringEscapeNone(b *testing.B) {
   190  	var j = []byte(`"` + strings.Repeat(`a`, 1000) + `"`)
   191  	var s string
   192  	b.SetBytes(int64(len(j)))
   193  
   194  	for i := 0; i < b.N; i++ {
   195  		if err := Unmarshal(j, &s); err != nil {
   196  			b.Fatal(err)
   197  		}
   198  		s = ""
   199  	}
   200  }
   201  
   202  func BenchmarkParseStringEscapeOne(b *testing.B) {
   203  	var j = []byte(`"` + strings.Repeat(`a`, 998) + `\n"`)
   204  	var s string
   205  	b.SetBytes(int64(len(j)))
   206  
   207  	for i := 0; i < b.N; i++ {
   208  		if err := Unmarshal(j, &s); err != nil {
   209  			b.Fatal(err)
   210  		}
   211  		s = ""
   212  	}
   213  }
   214  
   215  func BenchmarkParseStringEscapeAll(b *testing.B) {
   216  	var j = []byte(`"` + strings.Repeat(`\`, 1000) + `"`)
   217  	var s string
   218  	b.SetBytes(int64(len(j)))
   219  
   220  	for i := 0; i < b.N; i++ {
   221  		if err := Unmarshal(j, &s); err != nil {
   222  			b.Fatal(err)
   223  		}
   224  		s = ""
   225  	}
   226  }