diff --git a/jsoniter_wrap_test.go b/any_tests/jsoniter_wrap_test.go similarity index 55% rename from jsoniter_wrap_test.go rename to any_tests/jsoniter_wrap_test.go index b300fb5..d6e5aad 100644 --- a/jsoniter_wrap_test.go +++ b/any_tests/jsoniter_wrap_test.go @@ -1,116 +1,117 @@ -package jsoniter +package any_tests import ( "testing" "github.com/stretchr/testify/require" + "github.com/json-iterator/go" ) func Test_wrap_and_valuetype_everything(t *testing.T) { should := require.New(t) var i interface{} - any := Get([]byte("123")) + any := jsoniter.Get([]byte("123")) // default of number type is float64 i = float64(123) should.Equal(i, any.GetInterface()) - any = Wrap(int8(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(int8(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) // get interface is not int8 interface // i = int8(10) // should.Equal(i, any.GetInterface()) - any = Wrap(int16(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(int16(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) //i = int16(10) //should.Equal(i, any.GetInterface()) - any = Wrap(int32(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(int32(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) i = int32(10) should.Equal(i, any.GetInterface()) - any = Wrap(int64(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(int64(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) i = int64(10) should.Equal(i, any.GetInterface()) - any = Wrap(uint(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(uint(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) // not equal //i = uint(10) //should.Equal(i, any.GetInterface()) - any = Wrap(uint8(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(uint8(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) // not equal // i = uint8(10) // should.Equal(i, any.GetInterface()) - any = Wrap(uint16(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(uint16(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) - any = Wrap(uint32(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(uint32(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) i = uint32(10) should.Equal(i, any.GetInterface()) - any = Wrap(uint64(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(uint64(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) i = uint64(10) should.Equal(i, any.GetInterface()) - any = Wrap(float32(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(float32(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) // not equal //i = float32(10) //should.Equal(i, any.GetInterface()) - any = Wrap(float64(10)) - should.Equal(any.ValueType(), NumberValue) + any = jsoniter.Wrap(float64(10)) + should.Equal(any.ValueType(), jsoniter.NumberValue) should.Equal(any.LastError(), nil) i = float64(10) should.Equal(i, any.GetInterface()) - any = Wrap(true) - should.Equal(any.ValueType(), BoolValue) + any = jsoniter.Wrap(true) + should.Equal(any.ValueType(), jsoniter.BoolValue) should.Equal(any.LastError(), nil) i = true should.Equal(i, any.GetInterface()) - any = Wrap(false) - should.Equal(any.ValueType(), BoolValue) + any = jsoniter.Wrap(false) + should.Equal(any.ValueType(), jsoniter.BoolValue) should.Equal(any.LastError(), nil) i = false should.Equal(i, any.GetInterface()) - any = Wrap(nil) - should.Equal(any.ValueType(), NilValue) + any = jsoniter.Wrap(nil) + should.Equal(any.ValueType(), jsoniter.NilValue) should.Equal(any.LastError(), nil) i = nil should.Equal(i, any.GetInterface()) - stream := NewStream(ConfigDefault, nil, 32) + stream := jsoniter.NewStream(jsoniter.ConfigDefault, nil, 32) any.WriteTo(stream) should.Equal("null", string(stream.Buffer())) should.Equal(any.LastError(), nil) - any = Wrap(struct{ age int }{age: 1}) - should.Equal(any.ValueType(), ObjectValue) + any = jsoniter.Wrap(struct{ age int }{age: 1}) + should.Equal(any.ValueType(), jsoniter.ObjectValue) should.Equal(any.LastError(), nil) i = struct{ age int }{age: 1} should.Equal(i, any.GetInterface()) - any = Wrap(map[string]interface{}{"abc": 1}) - should.Equal(any.ValueType(), ObjectValue) + any = jsoniter.Wrap(map[string]interface{}{"abc": 1}) + should.Equal(any.ValueType(), jsoniter.ObjectValue) should.Equal(any.LastError(), nil) i = map[string]interface{}{"abc": 1} should.Equal(i, any.GetInterface()) - any = Wrap("abc") + any = jsoniter.Wrap("abc") i = "abc" should.Equal(i, any.GetInterface()) should.Equal(nil, any.LastError()) diff --git a/jsoniter_sloppy_test.go b/feature_iter_skip_sloppy_test.go similarity index 99% rename from jsoniter_sloppy_test.go rename to feature_iter_skip_sloppy_test.go index 487713a..bcb491f 100644 --- a/jsoniter_sloppy_test.go +++ b/feature_iter_skip_sloppy_test.go @@ -1,4 +1,4 @@ -//+build jsoniter-sloppy +//+build jsoniter_sloppy package jsoniter diff --git a/jsoniter_stream_test.go b/feature_stream_test.go similarity index 100% rename from jsoniter_stream_test.go rename to feature_stream_test.go diff --git a/jsoniter_reader_test.go b/jsoniter_reader_test.go deleted file mode 100644 index b3b3588..0000000 --- a/jsoniter_reader_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package jsoniter - -import ( - "github.com/stretchr/testify/require" - "strings" - "testing" - "time" -) - -func Test_reader_and_load_more(t *testing.T) { - should := require.New(t) - type TestObject struct { - CreatedAt time.Time - } - reader := strings.NewReader(` -{ - "agency": null, - "candidateId": 0, - "candidate": "Blah Blah", - "bookingId": 0, - "shiftId": 1, - "shiftTypeId": 0, - "shift": "Standard", - "bonus": 0, - "bonusNI": 0, - "days": [], - "totalHours": 27, - "expenses": [], - "weekEndingDateSystem": "2016-10-09", - "weekEndingDateClient": "2016-10-09", - "submittedAt": null, - "submittedById": null, - "approvedAt": "2016-10-10T18:38:04Z", - "approvedById": 0, - "authorisedAt": "2016-10-10T18:38:04Z", - "authorisedById": 0, - "invoicedAt": "2016-10-10T20:00:00Z", - "revokedAt": null, - "revokedById": null, - "revokeReason": null, - "rejectedAt": null, - "rejectedById": null, - "rejectReasonCode": null, - "rejectReason": null, - "createdAt": "2016-10-03T00:00:00Z", - "updatedAt": "2016-11-09T10:26:13Z", - "updatedById": null, - "overrides": [], - "bookingApproverId": null, - "bookingApprover": null, - "status": "approved" -} - `) - decoder := ConfigCompatibleWithStandardLibrary.NewDecoder(reader) - obj := TestObject{} - should.Nil(decoder.Decode(&obj)) -} diff --git a/jsoniter_reflect_native_test.go b/jsoniter_reflect_native_test.go deleted file mode 100644 index 0e2d68b..0000000 --- a/jsoniter_reflect_native_test.go +++ /dev/null @@ -1,154 +0,0 @@ -package jsoniter - -import ( - "fmt" - "testing" -) - -func Test_reflect_str(t *testing.T) { - iter := ParseString(ConfigDefault, `"hello"`) - str := "" - iter.ReadVal(&str) - if str != "hello" { - fmt.Println(iter.Error) - t.Fatal(str) - } -} - -func Test_reflect_ptr_str(t *testing.T) { - iter := ParseString(ConfigDefault, `"hello"`) - var str *string - iter.ReadVal(&str) - if *str != "hello" { - t.Fatal(str) - } -} - -func Test_reflect_int(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := int(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_int8(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := int8(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_int16(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := int16(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_int32(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := int32(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_int64(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := int64(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_uint(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := uint(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_uint8(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := uint8(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_uint16(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := uint16(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_uint32(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := uint32(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_uint64(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := uint64(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_byte(t *testing.T) { - iter := ParseString(ConfigDefault, `123`) - val := byte(0) - iter.ReadVal(&val) - if val != 123 { - t.Fatal(val) - } -} - -func Test_reflect_float32(t *testing.T) { - iter := ParseString(ConfigDefault, `1.23`) - val := float32(0) - iter.ReadVal(&val) - if val != 1.23 { - fmt.Println(iter.Error) - t.Fatal(val) - } -} - -func Test_reflect_float64(t *testing.T) { - iter := ParseString(ConfigDefault, `1.23`) - val := float64(0) - iter.ReadVal(&val) - if val != 1.23 { - fmt.Println(iter.Error) - t.Fatal(val) - } -} - -func Test_reflect_bool(t *testing.T) { - iter := ParseString(ConfigDefault, `true`) - val := false - iter.ReadVal(&val) - if val != true { - fmt.Println(iter.Error) - t.Fatal(val) - } -} diff --git a/jsoniter_string_test.go b/jsoniter_string_test.go deleted file mode 100644 index 61c0f33..0000000 --- a/jsoniter_string_test.go +++ /dev/null @@ -1,261 +0,0 @@ -// +build go1.8 - -package jsoniter - -import ( - "bytes" - "encoding/json" - "fmt" - "testing" - "unicode/utf8" - - "github.com/stretchr/testify/require" -) - -func Test_read_string(t *testing.T) { - badInputs := []string{ - ``, - `"`, - `"\"`, - `"\\\"`, - "\"\n\"", - `"\U0001f64f"`, - `"\uD83D\u00"`, - } - for i := 0; i < 32; i++ { - // control characters are invalid - badInputs = append(badInputs, string([]byte{'"', byte(i), '"'})) - } - - for _, input := range badInputs { - testReadString(t, input, "", true, "json.Unmarshal", json.Unmarshal) - testReadString(t, input, "", true, "jsoniter.Unmarshal", Unmarshal) - testReadString(t, input, "", true, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal) - } - - goodInputs := []struct { - input string - expectValue string - }{ - {`""`, ""}, - {`"a"`, "a"}, - {`null`, ""}, - {`"Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"`, "Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"}, - {`"\uD83D"`, string([]byte{239, 191, 189})}, - {`"\uD83D\\"`, string([]byte{239, 191, 189, '\\'})}, - {`"\uD83D\ub000"`, string([]byte{239, 191, 189, 235, 128, 128})}, - {`"\uD83D\ude04"`, "😄"}, - {`"\uDEADBEEF"`, string([]byte{239, 191, 189, 66, 69, 69, 70})}, - } - - for _, tc := range goodInputs { - testReadString(t, tc.input, tc.expectValue, false, "json.Unmarshal", json.Unmarshal) - testReadString(t, tc.input, tc.expectValue, false, "jsoniter.Unmarshal", Unmarshal) - testReadString(t, tc.input, tc.expectValue, false, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal) - } -} - -func testReadString(t *testing.T, input string, expectValue string, expectError bool, marshalerName string, marshaler func([]byte, interface{}) error) { - var value string - err := marshaler([]byte(input), &value) - if expectError != (err != nil) { - t.Errorf("%q: %s: expected error %v, got %v", input, marshalerName, expectError, err) - return - } - if value != expectValue { - t.Errorf("%q: %s: expected %q, got %q", input, marshalerName, expectValue, value) - return - } -} - -func Test_read_normal_string(t *testing.T) { - cases := map[string]string{ - `"0123456789012345678901234567890123456789"`: `0123456789012345678901234567890123456789`, - `""`: ``, - `"hello"`: `hello`, - } - for input, output := range cases { - t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) { - should := require.New(t) - iter := ParseString(ConfigDefault, input) - should.Equal(output, iter.ReadString()) - }) - t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) { - should := require.New(t) - iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2) - should.Equal(output, iter.ReadString()) - }) - t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) { - should := require.New(t) - iter := ParseString(ConfigDefault, input) - should.Equal(output, string(iter.ReadStringAsSlice())) - }) - t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) { - should := require.New(t) - iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2) - should.Equal(output, string(iter.ReadStringAsSlice())) - }) - } -} - -func Test_read_exotic_string(t *testing.T) { - cases := map[string]string{ - `"hel\"lo"`: `hel"lo`, - `"hel\\\/lo"`: `hel\/lo`, - `"hel\\blo"`: `hel\blo`, - `"hel\\\blo"`: "hel\\\blo", - `"hel\\nlo"`: `hel\nlo`, - `"hel\\\nlo"`: "hel\\\nlo", - `"hel\\tlo"`: `hel\tlo`, - `"hel\\flo"`: `hel\flo`, - `"hel\\\flo"`: "hel\\\flo", - `"hel\\\rlo"`: "hel\\\rlo", - `"hel\\\tlo"`: "hel\\\tlo", - `"\u4e2d\u6587"`: "中文", - `"\ud83d\udc4a"`: "\xf0\x9f\x91\x8a", // surrogate - } - for input, output := range cases { - t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) { - should := require.New(t) - iter := ParseString(ConfigDefault, input) - var v string - should.Nil(json.Unmarshal([]byte(input), &v)) - should.Equal(v, iter.ReadString()) - }) - t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) { - should := require.New(t) - iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2) - should.Equal(output, iter.ReadString()) - }) - } -} - -func Test_read_string_as_interface(t *testing.T) { - should := require.New(t) - iter := ParseString(ConfigDefault, `"hello"`) - should.Equal("hello", iter.Read()) -} - -func Test_write_string(t *testing.T) { - should := require.New(t) - str, err := MarshalToString("hello") - should.Equal(`"hello"`, str) - should.Nil(err) - str, err = MarshalToString(`hel"lo`) - should.Equal(`"hel\"lo"`, str) - should.Nil(err) -} - -func Test_write_val_string(t *testing.T) { - should := require.New(t) - buf := &bytes.Buffer{} - stream := NewStream(ConfigDefault, buf, 4096) - stream.WriteVal("hello") - stream.Flush() - should.Nil(stream.Error) - should.Equal(`"hello"`, buf.String()) -} - -func Test_decode_slash(t *testing.T) { - should := require.New(t) - var obj interface{} - should.NotNil(json.Unmarshal([]byte("\\"), &obj)) - should.NotNil(UnmarshalFromString("\\", &obj)) -} - -func Test_html_escape(t *testing.T) { - should := require.New(t) - output, err := json.Marshal(`>`) - should.Nil(err) - should.Equal(`"\u003e"`, string(output)) - output, err = ConfigCompatibleWithStandardLibrary.Marshal(`>`) - should.Nil(err) - should.Equal(`"\u003e"`, string(output)) - type MyString string - output, err = ConfigCompatibleWithStandardLibrary.Marshal(MyString(`>`)) - should.Nil(err) - should.Equal(`"\u003e"`, string(output)) -} - -func Test_string_encode_with_std(t *testing.T) { - should := require.New(t) - for i := 0; i < utf8.RuneSelf; i++ { - input := string([]byte{byte(i)}) - stdOutputBytes, err := json.Marshal(input) - should.Nil(err) - stdOutput := string(stdOutputBytes) - jsoniterOutputBytes, err := ConfigCompatibleWithStandardLibrary.Marshal(input) - should.Nil(err) - jsoniterOutput := string(jsoniterOutputBytes) - should.Equal(stdOutput, jsoniterOutput) - } -} - -func Test_unicode(t *testing.T) { - should := require.New(t) - output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"}) - should.Equal(`{"a":"数字山谷"}`, output) - output, _ = Config{EscapeHTML: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"}) - should.Equal(`{"a":"数字山谷"}`, output) -} - -func Test_unicode_and_escape(t *testing.T) { - should := require.New(t) - output, err := MarshalToString(`"数字山谷"`) - should.Nil(err) - should.Equal(`"\"数字山谷\""`, output) - output, err = ConfigFastest.MarshalToString(`"数字山谷"`) - should.Nil(err) - should.Equal(`"\"数字山谷\""`, output) -} - -func Test_unsafe_unicode(t *testing.T) { - ConfigDefault.(*frozenConfig).cleanEncoders() - should := require.New(t) - output, err := ConfigDefault.MarshalToString("he\u2029\u2028he") - should.Nil(err) - should.Equal(`"he\u2029\u2028he"`, output) - output, err = ConfigFastest.MarshalToString("he\u2029\u2028he") - should.Nil(err) - should.Equal("\"he\u2029\u2028he\"", output) -} - -func Benchmark_jsoniter_unicode(b *testing.B) { - for n := 0; n < b.N; n++ { - iter := ParseString(ConfigDefault, `"\ud83d\udc4a"`) - iter.ReadString() - } -} - -func Benchmark_jsoniter_ascii(b *testing.B) { - iter := NewIterator(ConfigDefault) - input := []byte(`"hello, world! hello, world!"`) - b.ResetTimer() - for n := 0; n < b.N; n++ { - iter.ResetBytes(input) - iter.ReadString() - } -} - -func Benchmark_jsoniter_string_as_bytes(b *testing.B) { - iter := ParseString(ConfigDefault, `"hello, world!"`) - b.ResetTimer() - for n := 0; n < b.N; n++ { - iter.ResetBytes(iter.buf) - iter.ReadStringAsSlice() - } -} - -func Benchmark_json_unicode(b *testing.B) { - for n := 0; n < b.N; n++ { - result := "" - json.Unmarshal([]byte(`"\ud83d\udc4a"`), &result) - } -} - -func Benchmark_json_ascii(b *testing.B) { - for n := 0; n < b.N; n++ { - result := "" - json.Unmarshal([]byte(`"hello"`), &result) - } -} diff --git a/jsoniter_struct_decoder_test.go b/jsoniter_struct_decoder_test.go deleted file mode 100644 index 257bbdb..0000000 --- a/jsoniter_struct_decoder_test.go +++ /dev/null @@ -1,267 +0,0 @@ -package jsoniter - -import ( - "github.com/stretchr/testify/require" - "testing" -) - -func Test_decode_one_field_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"field1": "hello"}`, &obj)) - should.Equal("hello", obj.Field1) -} - -func Test_decode_two_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) -} - -func Test_decode_three_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) -} - -func Test_decode_four_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) -} - -func Test_decode_five_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - Field5 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) - should.Equal("e", obj.Field5) -} - -func Test_decode_six_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - Field5 string - Field6 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) - should.Equal("e", obj.Field5) - should.Equal("x", obj.Field6) -} - -func Test_decode_seven_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - Field5 string - Field6 string - Field7 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x", "Field7":"y"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) - should.Equal("e", obj.Field5) - should.Equal("x", obj.Field6) - should.Equal("y", obj.Field7) -} - -func Test_decode_eight_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - Field5 string - Field6 string - Field7 string - Field8 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field8":"1", "Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field6": "x", "Field7":"y"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) - should.Equal("e", obj.Field5) - should.Equal("x", obj.Field6) - should.Equal("y", obj.Field7) - should.Equal("1", obj.Field8) -} - -func Test_decode_nine_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - Field5 string - Field6 string - Field7 string - Field8 string - Field9 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field8" : "zzzzzzzzzzz", "Field7": "zz", "Field6" : "xx", "Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e", "Field9":"f"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) - should.Equal("e", obj.Field5) - should.Equal("xx", obj.Field6) - should.Equal("zz", obj.Field7) - should.Equal("zzzzzzzzzzz", obj.Field8) - should.Equal("f", obj.Field9) -} - -func Test_decode_ten_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - Field5 string - Field6 string - Field7 string - Field8 string - Field9 string - Field10 string - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"Field10":"x", "Field9": "x", "Field8":"x", "Field7":"x", "Field6":"x", "Field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) - should.Equal("e", obj.Field5) - should.Equal("x", obj.Field6) - should.Equal("x", obj.Field7) - should.Equal("x", obj.Field8) - should.Equal("x", obj.Field9) - should.Equal("x", obj.Field10) -} - -func Test_decode_more_than_ten_fields_struct(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string - Field2 string - Field3 string - Field4 string - Field5 string - Field6 string - Field7 string - Field8 string - Field9 string - Field10 string - Field11 int - } - obj := TestObject{} - should.Nil(UnmarshalFromString(`{}`, &obj)) - should.Equal("", obj.Field1) - should.Nil(UnmarshalFromString(`{"field11":1, "field1": "a", "Field2": "stream", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj)) - should.Equal("a", obj.Field1) - should.Equal("stream", obj.Field2) - should.Equal("c", obj.Field3) - should.Equal("d", obj.Field4) - should.Equal("e", obj.Field5) - should.Equal(1, obj.Field11) -} - -func Test_decode_struct_field_with_tag(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 string `json:"field-1"` - Field2 string `json:"-"` - Field3 int `json:",string"` - } - obj := TestObject{Field2: "world"} - UnmarshalFromString(`{"field-1": "hello", "field2": "", "Field3": "100"}`, &obj) - should.Equal("hello", obj.Field1) - should.Equal("world", obj.Field2) - should.Equal(100, obj.Field3) -} - -func Test_decode_struct_field_with_tag_string(t *testing.T) { - should := require.New(t) - type TestObject struct { - Field1 int `json:",string"` - } - obj := TestObject{Field1: 100} - should.Nil(UnmarshalFromString(`{"Field1": "100"}`, &obj)) - should.Equal(100, obj.Field1) -} diff --git a/jsoniter_struct_encoder_test.go b/jsoniter_struct_encoder_test.go deleted file mode 100644 index 0e3e541..0000000 --- a/jsoniter_struct_encoder_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package jsoniter - -import ( - "encoding/json" - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func Test_encode_unexported_field(t *testing.T) { - type TestData struct { - a int - b <-chan int - C int - d *time.Timer - } - - should := require.New(t) - - testChan := make(<-chan int, 10) - testTimer := time.NewTimer(10 * time.Second) - - obj := &TestData{ - a: 42, - b: testChan, - C: 21, - d: testTimer, - } - - jb, err := json.Marshal(obj) - should.NoError(err) - should.Equal([]byte(`{"C":21}`), jb) - - err = json.Unmarshal([]byte(`{"a": 444, "b":"bad", "C":55, "d":{"not": "a timer"}}`), obj) - should.NoError(err) - should.Equal(42, obj.a) - should.Equal(testChan, obj.b) - should.Equal(55, obj.C) - should.Equal(testTimer, obj.d) - - jb, err = Marshal(obj) - should.NoError(err) - should.Equal(jb, []byte(`{"C":55}`)) - - err = Unmarshal([]byte(`{"a": 444, "b":"bad", "C":256, "d":{"not":"a timer"}}`), obj) - should.NoError(err) - should.Equal(42, obj.a) - should.Equal(testChan, obj.b) - should.Equal(256, obj.C) - should.Equal(testTimer, obj.d) -} diff --git a/misc_tests/jsoniter_object_test.go b/misc_tests/jsoniter_object_test.go index 5459d79..9260d46 100644 --- a/misc_tests/jsoniter_object_test.go +++ b/misc_tests/jsoniter_object_test.go @@ -6,6 +6,8 @@ import ( "github.com/stretchr/testify/require" "github.com/json-iterator/go" + "time" + "strings" ) func Test_empty_object(t *testing.T) { @@ -78,4 +80,53 @@ func Test_write_object(t *testing.T) { stream.Flush() should.Nil(stream.Error) should.Equal("{\n \"hello\": 1,\n \"world\": 2\n}", buf.String()) +} + +func Test_reader_and_load_more(t *testing.T) { + should := require.New(t) + type TestObject struct { + CreatedAt time.Time + } + reader := strings.NewReader(` +{ + "agency": null, + "candidateId": 0, + "candidate": "Blah Blah", + "bookingId": 0, + "shiftId": 1, + "shiftTypeId": 0, + "shift": "Standard", + "bonus": 0, + "bonusNI": 0, + "days": [], + "totalHours": 27, + "expenses": [], + "weekEndingDateSystem": "2016-10-09", + "weekEndingDateClient": "2016-10-09", + "submittedAt": null, + "submittedById": null, + "approvedAt": "2016-10-10T18:38:04Z", + "approvedById": 0, + "authorisedAt": "2016-10-10T18:38:04Z", + "authorisedById": 0, + "invoicedAt": "2016-10-10T20:00:00Z", + "revokedAt": null, + "revokedById": null, + "revokeReason": null, + "rejectedAt": null, + "rejectedById": null, + "rejectReasonCode": null, + "rejectReason": null, + "createdAt": "2016-10-03T00:00:00Z", + "updatedAt": "2016-11-09T10:26:13Z", + "updatedById": null, + "overrides": [], + "bookingApproverId": null, + "bookingApprover": null, + "status": "approved" +} + `) + decoder := jsoniter.ConfigCompatibleWithStandardLibrary.NewDecoder(reader) + obj := TestObject{} + should.Nil(decoder.Decode(&obj)) } \ No newline at end of file diff --git a/jsoniter_skip_test.go b/skip_tests/jsoniter_skip_test.go similarity index 76% rename from jsoniter_skip_test.go rename to skip_tests/jsoniter_skip_test.go index cb13e50..35f97af 100644 --- a/jsoniter_skip_test.go +++ b/skip_tests/jsoniter_skip_test.go @@ -1,4 +1,4 @@ -package jsoniter +package skip_tests import ( "bytes" @@ -6,11 +6,12 @@ import ( "testing" "github.com/stretchr/testify/require" + "github.com/json-iterator/go" ) func Test_skip_number_in_array(t *testing.T) { should := require.New(t) - iter := ParseString(ConfigDefault, `[-0.12, "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[-0.12, "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -20,7 +21,7 @@ func Test_skip_number_in_array(t *testing.T) { func Test_skip_string_in_array(t *testing.T) { should := require.New(t) - iter := ParseString(ConfigDefault, `["hello", "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `["hello", "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -29,7 +30,7 @@ func Test_skip_string_in_array(t *testing.T) { } func Test_skip_null(t *testing.T) { - iter := ParseString(ConfigDefault, `[null , "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[null , "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -39,7 +40,7 @@ func Test_skip_null(t *testing.T) { } func Test_skip_true(t *testing.T) { - iter := ParseString(ConfigDefault, `[true , "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[true , "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -49,7 +50,7 @@ func Test_skip_true(t *testing.T) { } func Test_skip_false(t *testing.T) { - iter := ParseString(ConfigDefault, `[false , "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[false , "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -59,7 +60,7 @@ func Test_skip_false(t *testing.T) { } func Test_skip_array(t *testing.T) { - iter := ParseString(ConfigDefault, `[[1, [2, [3], 4]], "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[[1, [2, [3], 4]], "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -69,7 +70,7 @@ func Test_skip_array(t *testing.T) { } func Test_skip_empty_array(t *testing.T) { - iter := ParseString(ConfigDefault, `[ [ ], "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[ [ ], "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -79,7 +80,7 @@ func Test_skip_empty_array(t *testing.T) { } func Test_skip_nested(t *testing.T) { - iter := ParseString(ConfigDefault, `[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`) iter.ReadArray() iter.Skip() iter.ReadArray() @@ -90,7 +91,7 @@ func Test_skip_nested(t *testing.T) { func Test_skip_and_return_bytes(t *testing.T) { should := require.New(t) - iter := ParseString(ConfigDefault, `[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`) + iter := jsoniter.ParseString(jsoniter.ConfigDefault, `[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`) iter.ReadArray() skipped := iter.SkipAndReturnBytes() should.Equal(`{"a" : [{"stream": "c"}], "d": 102 }`, string(skipped)) @@ -98,7 +99,7 @@ func Test_skip_and_return_bytes(t *testing.T) { func Test_skip_and_return_bytes_with_reader(t *testing.T) { should := require.New(t) - iter := Parse(ConfigDefault, bytes.NewBufferString(`[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`), 4) + iter := jsoniter.Parse(jsoniter.ConfigDefault, bytes.NewBufferString(`[ {"a" : [{"stream": "c"}], "d": 102 }, "stream"]`), 4) iter.ReadArray() skipped := iter.SkipAndReturnBytes() should.Equal(`{"a" : [{"stream": "c"}], "d": 102 }`, string(skipped)) @@ -106,7 +107,7 @@ func Test_skip_and_return_bytes_with_reader(t *testing.T) { func Test_skip_empty(t *testing.T) { should := require.New(t) - should.NotNil(Get([]byte("")).LastError()) + should.NotNil(jsoniter.Get([]byte("")).LastError()) } type TestResp struct { @@ -140,7 +141,7 @@ func Benchmark_jsoniter_skip(b *testing.B) { }`) for n := 0; n < b.N; n++ { result := TestResp{} - iter := ParseBytes(ConfigDefault, input) + iter := jsoniter.ParseBytes(jsoniter.ConfigDefault, input) for field := iter.ReadObject(); field != ""; field = iter.ReadObject() { switch field { case "code": diff --git a/type_tests/struct_test.go b/type_tests/struct_test.go index 27184d2..b25fc7b 100644 --- a/type_tests/struct_test.go +++ b/type_tests/struct_test.go @@ -3,6 +3,7 @@ package test import "time" func init() { + structFields1To11() testCases = append(testCases, (*struct1Alias)(nil), (*struct { @@ -258,6 +259,99 @@ func init() { ) } +func structFields1To11() { + testCases = append(testCases, + (*struct { + Field1 string + })(nil), + (*struct { + Field1 string + Field2 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + Field8 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + Field8 string + Field9 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + Field8 string + Field9 string + Field10 string + })(nil), + (*struct { + Field1 string + Field2 string + Field3 string + Field4 string + Field5 string + Field6 string + Field7 string + Field8 string + Field9 string + Field10 string + Field11 string + })(nil), + ) +} + type struct1 struct { Byte1 byte Byte2 byte diff --git a/unmarshal_input_test.go b/unmarshal_input_test.go deleted file mode 100644 index 9d7b99c..0000000 --- a/unmarshal_input_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package jsoniter - -import ( - "encoding/json" - "reflect" - "testing" - - fuzz "github.com/google/gofuzz" -) - -func Test_NilInput(t *testing.T) { - var jb []byte // nil - var out string - err := Unmarshal(jb, &out) - if err == nil { - t.Errorf("Expected error") - } -} - -func Test_EmptyInput(t *testing.T) { - jb := []byte("") - var out string - err := Unmarshal(jb, &out) - if err == nil { - t.Errorf("Expected error") - } -} - -func Test_RandomInput_Bytes(t *testing.T) { - fz := fuzz.New().NilChance(0) - for i := 0; i < 10000; i++ { - var jb []byte - fz.Fuzz(&jb) - testRandomInput(t, jb) - } -} - -func Test_RandomInput_String(t *testing.T) { - fz := fuzz.New().NilChance(0) - for i := 0; i < 10000; i++ { - var js string - fz.Fuzz(&js) - jb := []byte(js) - testRandomInput(t, jb) - } -} - -func testRandomInput(t *testing.T, jb []byte) { - var outString string - testRandomInputTo(t, jb, &outString) - - var outInt int - testRandomInputTo(t, jb, &outInt) - - var outStruct struct{} - testRandomInputTo(t, jb, &outStruct) - - var outSlice []string - testRandomInputTo(t, jb, &outSlice) -} - -func testRandomInputTo(t *testing.T, jb []byte, out interface{}) { - err := Unmarshal(jb, out) - if err == nil { - // Cross-check stdlib to see if we just happened to fuzz a legit value. - err := json.Unmarshal(jb, out) - if err != nil { - t.Fatalf("Expected error unmarshaling as %s:\nas string: %q\nas bytes: %v", - reflect.TypeOf(out).Elem().Kind(), string(jb), jb) - } - } -} diff --git a/value_tests/invalid_test.go b/value_tests/invalid_test.go index 16d5db8..f460124 100644 --- a/value_tests/invalid_test.go +++ b/value_tests/invalid_test.go @@ -199,3 +199,28 @@ func TestDecodeErrorType(t *testing.T) { should.Nil(jsoniter.Unmarshal([]byte("null"), &err)) should.NotNil(jsoniter.Unmarshal([]byte("123"), &err)) } + +func Test_decode_slash(t *testing.T) { + should := require.New(t) + var obj interface{} + should.NotNil(json.Unmarshal([]byte("\\"), &obj)) + should.NotNil(jsoniter.UnmarshalFromString("\\", &obj)) +} + +func Test_NilInput(t *testing.T) { + var jb []byte // nil + var out string + err := jsoniter.Unmarshal(jb, &out) + if err == nil { + t.Errorf("Expected error") + } +} + +func Test_EmptyInput(t *testing.T) { + jb := []byte("") + var out string + err := jsoniter.Unmarshal(jb, &out) + if err == nil { + t.Errorf("Expected error") + } +} \ No newline at end of file diff --git a/value_tests/string_test.go b/value_tests/string_test.go new file mode 100644 index 0000000..9bf5e36 --- /dev/null +++ b/value_tests/string_test.go @@ -0,0 +1,88 @@ +package test + +import ( + "testing" + "github.com/json-iterator/go" + "encoding/json" + "unicode/utf8" +) + +func init() { + marshalCases = append(marshalCases, + `>`, + `"数字山谷"`, + "he\u2029\u2028he", + ) + for i := 0; i < utf8.RuneSelf; i++ { + marshalCases = append(marshalCases, string([]byte{byte(i)})) + } +} + +func Test_read_string(t *testing.T) { + badInputs := []string{ + ``, + `"`, + `"\"`, + `"\\\"`, + "\"\n\"", + `"\U0001f64f"`, + `"\uD83D\u00"`, + } + for i := 0; i < 32; i++ { + // control characters are invalid + badInputs = append(badInputs, string([]byte{'"', byte(i), '"'})) + } + + for _, input := range badInputs { + testReadString(t, input, "", true, "json.Unmarshal", json.Unmarshal) + testReadString(t, input, "", true, "jsoniter.Unmarshal", jsoniter.Unmarshal) + testReadString(t, input, "", true, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) + } + + goodInputs := []struct { + input string + expectValue string + }{ + {`""`, ""}, + {`"a"`, "a"}, + {`null`, ""}, + {`"Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"`, "Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"}, + {`"\uD83D"`, string([]byte{239, 191, 189})}, + {`"\uD83D\\"`, string([]byte{239, 191, 189, '\\'})}, + {`"\uD83D\ub000"`, string([]byte{239, 191, 189, 235, 128, 128})}, + {`"\uD83D\ude04"`, "😄"}, + {`"\uDEADBEEF"`, string([]byte{239, 191, 189, 66, 69, 69, 70})}, + {`"hel\"lo"`, `hel"lo`}, + {`"hel\\\/lo"`, `hel\/lo`}, + {`"hel\\blo"`, `hel\blo`}, + {`"hel\\\blo"`, "hel\\\blo"}, + {`"hel\\nlo"`, `hel\nlo`}, + {`"hel\\\nlo"`, "hel\\\nlo"}, + {`"hel\\tlo"`, `hel\tlo`}, + {`"hel\\flo"`, `hel\flo`}, + {`"hel\\\flo"`, "hel\\\flo"}, + {`"hel\\\rlo"`, "hel\\\rlo"}, + {`"hel\\\tlo"`, "hel\\\tlo"}, + {`"\u4e2d\u6587"`, "中文"}, + {`"\ud83d\udc4a"`, "\xf0\x9f\x91\x8a"}, + } + + for _, tc := range goodInputs { + testReadString(t, tc.input, tc.expectValue, false, "json.Unmarshal", json.Unmarshal) + testReadString(t, tc.input, tc.expectValue, false, "jsoniter.Unmarshal", jsoniter.Unmarshal) + testReadString(t, tc.input, tc.expectValue, false, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) + } +} + +func testReadString(t *testing.T, input string, expectValue string, expectError bool, marshalerName string, marshaler func([]byte, interface{}) error) { + var value string + err := marshaler([]byte(input), &value) + if expectError != (err != nil) { + t.Errorf("%q: %s: expected error %v, got %v", input, marshalerName, expectError, err) + return + } + if value != expectValue { + t.Errorf("%q: %s: expected %q, got %q", input, marshalerName, expectValue, value) + return + } +} diff --git a/value_tests/struct_test.go b/value_tests/struct_test.go index e3532cf..2e474c4 100644 --- a/value_tests/struct_test.go +++ b/value_tests/struct_test.go @@ -49,6 +49,14 @@ func init() { Field2 json.RawMessage })(nil), input: `{"field1": "hello", "field2":[1,2,3]}`, + }, unmarshalCase{ + ptr: (*struct { + a int + b <-chan int + C int + d *time.Timer + })(nil), + input: `{"a": 444, "b":"bad", "C":256, "d":{"not":"a timer"}}`, }) marshalCases = append(marshalCases, struct { @@ -135,6 +143,17 @@ func init() { Field1 *string Field2 *string }{Field2: pString("world")}, + struct { + a int + b <-chan int + C int + d *time.Timer + }{ + a: 42, + b: make(<-chan int, 10), + C: 21, + d: time.NewTimer(10 * time.Second), + }, ) }