1// Copyright 2010 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package json 6 7import ( 8 "bytes" 9 "io/ioutil" 10 "net" 11 "reflect" 12 "strings" 13 "testing" 14) 15 16// Test values for the stream test. 17// One of each JSON kind. 18var streamTest = []interface{}{ 19 0.1, 20 "hello", 21 nil, 22 true, 23 false, 24 []interface{}{"a", "b", "c"}, 25 map[string]interface{}{"K": "Kelvin", "ß": "long s"}, 26 3.14, // another value to make sure something can follow map 27} 28 29var streamEncoded = `0.1 30"hello" 31null 32true 33false 34["a","b","c"] 35{"ß":"long s","K":"Kelvin"} 363.14 37` 38 39func TestEncoder(t *testing.T) { 40 for i := 0; i <= len(streamTest); i++ { 41 var buf bytes.Buffer 42 enc := NewEncoder(&buf) 43 for j, v := range streamTest[0:i] { 44 if err := enc.Encode(v); err != nil { 45 t.Fatalf("encode #%d: %v", j, err) 46 } 47 } 48 if have, want := buf.String(), nlines(streamEncoded, i); have != want { 49 t.Errorf("encoding %d items: mismatch", i) 50 diff(t, []byte(have), []byte(want)) 51 break 52 } 53 } 54} 55 56func TestDecoder(t *testing.T) { 57 for i := 0; i <= len(streamTest); i++ { 58 // Use stream without newlines as input, 59 // just to stress the decoder even more. 60 // Our test input does not include back-to-back numbers. 61 // Otherwise stripping the newlines would 62 // merge two adjacent JSON values. 63 var buf bytes.Buffer 64 for _, c := range nlines(streamEncoded, i) { 65 if c != '\n' { 66 buf.WriteRune(c) 67 } 68 } 69 out := make([]interface{}, i) 70 dec := NewDecoder(&buf) 71 for j := range out { 72 if err := dec.Decode(&out[j]); err != nil { 73 t.Fatalf("decode #%d/%d: %v", j, i, err) 74 } 75 } 76 if !reflect.DeepEqual(out, streamTest[0:i]) { 77 t.Errorf("decoding %d items: mismatch", i) 78 for j := range out { 79 if !reflect.DeepEqual(out[j], streamTest[j]) { 80 t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j]) 81 } 82 } 83 break 84 } 85 } 86} 87 88func TestDecoderBuffered(t *testing.T) { 89 r := strings.NewReader(`{"Name": "Gopher"} extra `) 90 var m struct { 91 Name string 92 } 93 d := NewDecoder(r) 94 err := d.Decode(&m) 95 if err != nil { 96 t.Fatal(err) 97 } 98 if m.Name != "Gopher" { 99 t.Errorf("Name = %q; want Gopher", m.Name) 100 } 101 rest, err := ioutil.ReadAll(d.Buffered()) 102 if err != nil { 103 t.Fatal(err) 104 } 105 if g, w := string(rest), " extra "; g != w { 106 t.Errorf("Remaining = %q; want %q", g, w) 107 } 108} 109 110func nlines(s string, n int) string { 111 if n <= 0 { 112 return "" 113 } 114 for i, c := range s { 115 if c == '\n' { 116 if n--; n == 0 { 117 return s[0 : i+1] 118 } 119 } 120 } 121 return s 122} 123 124func TestRawMessage(t *testing.T) { 125 // TODO(rsc): Should not need the * in *RawMessage 126 var data struct { 127 X float64 128 Id *RawMessage 129 Y float32 130 } 131 const raw = `["\u0056",null]` 132 const msg = `{"X":0.1,"Id":["\u0056",null],"Y":0.2}` 133 err := Unmarshal([]byte(msg), &data) 134 if err != nil { 135 t.Fatalf("Unmarshal: %v", err) 136 } 137 if string([]byte(*data.Id)) != raw { 138 t.Fatalf("Raw mismatch: have %#q want %#q", []byte(*data.Id), raw) 139 } 140 b, err := Marshal(&data) 141 if err != nil { 142 t.Fatalf("Marshal: %v", err) 143 } 144 if string(b) != msg { 145 t.Fatalf("Marshal: have %#q want %#q", b, msg) 146 } 147} 148 149func TestNullRawMessage(t *testing.T) { 150 // TODO(rsc): Should not need the * in *RawMessage 151 var data struct { 152 X float64 153 Id *RawMessage 154 Y float32 155 } 156 data.Id = new(RawMessage) 157 const msg = `{"X":0.1,"Id":null,"Y":0.2}` 158 err := Unmarshal([]byte(msg), &data) 159 if err != nil { 160 t.Fatalf("Unmarshal: %v", err) 161 } 162 if data.Id != nil { 163 t.Fatalf("Raw mismatch: have non-nil, want nil") 164 } 165 b, err := Marshal(&data) 166 if err != nil { 167 t.Fatalf("Marshal: %v", err) 168 } 169 if string(b) != msg { 170 t.Fatalf("Marshal: have %#q want %#q", b, msg) 171 } 172} 173 174var blockingTests = []string{ 175 `{"x": 1}`, 176 `[1, 2, 3]`, 177} 178 179func TestBlocking(t *testing.T) { 180 for _, enc := range blockingTests { 181 r, w := net.Pipe() 182 go w.Write([]byte(enc)) 183 var val interface{} 184 185 // If Decode reads beyond what w.Write writes above, 186 // it will block, and the test will deadlock. 187 if err := NewDecoder(r).Decode(&val); err != nil { 188 t.Errorf("decoding %s: %v", enc, err) 189 } 190 r.Close() 191 w.Close() 192 } 193} 194 195func BenchmarkEncoderEncode(b *testing.B) { 196 b.ReportAllocs() 197 type T struct { 198 X, Y string 199 } 200 v := &T{"foo", "bar"} 201 for i := 0; i < b.N; i++ { 202 if err := NewEncoder(ioutil.Discard).Encode(v); err != nil { 203 b.Fatal(err) 204 } 205 } 206} 207