...

Source file src/google.golang.org/protobuf/internal/encoding/json/encode_test.go

Documentation: google.golang.org/protobuf/internal/encoding/json

     1  // Copyright 2019 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  
     5  package json_test
     6  
     7  import (
     8  	"math"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"github.com/google/go-cmp/cmp/cmpopts"
    14  
    15  	"google.golang.org/protobuf/internal/detrand"
    16  	"google.golang.org/protobuf/internal/encoding/json"
    17  )
    18  
    19  // Disable detrand to enable direct comparisons on outputs.
    20  func init() { detrand.Disable() }
    21  
    22  // splitLines is a cmpopts.Option for comparing strings with line breaks.
    23  var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
    24  	return strings.Split(s, "\n")
    25  })
    26  
    27  func TestEncoder(t *testing.T) {
    28  	tests := []struct {
    29  		desc          string
    30  		write         func(*json.Encoder)
    31  		wantOut       string
    32  		wantOutIndent string
    33  	}{
    34  		{
    35  			desc: "null",
    36  			write: func(e *json.Encoder) {
    37  				e.WriteNull()
    38  			},
    39  			wantOut: `null`,
    40  		},
    41  		{
    42  			desc: "true",
    43  			write: func(e *json.Encoder) {
    44  				e.WriteBool(true)
    45  			},
    46  			wantOut: `true`,
    47  		},
    48  		{
    49  			desc: "false",
    50  			write: func(e *json.Encoder) {
    51  				e.WriteBool(false)
    52  			},
    53  			wantOut: `false`,
    54  		},
    55  		{
    56  			desc: "string",
    57  			write: func(e *json.Encoder) {
    58  				e.WriteString("hello world")
    59  			},
    60  			wantOut: `"hello world"`,
    61  		},
    62  		{
    63  			desc: "string contains escaped characters",
    64  			write: func(e *json.Encoder) {
    65  				e.WriteString("\u0000\"\\/\b\f\n\r\t")
    66  			},
    67  			wantOut: `"\u0000\"\\/\b\f\n\r\t"`,
    68  		},
    69  		{
    70  			desc: "float64",
    71  			write: func(e *json.Encoder) {
    72  				e.WriteFloat(1.0199999809265137, 64)
    73  			},
    74  			wantOut: `1.0199999809265137`,
    75  		},
    76  		{
    77  			desc: "float64 max value",
    78  			write: func(e *json.Encoder) {
    79  				e.WriteFloat(math.MaxFloat64, 64)
    80  			},
    81  			wantOut: `1.7976931348623157e+308`,
    82  		},
    83  		{
    84  			desc: "float64 min value",
    85  			write: func(e *json.Encoder) {
    86  				e.WriteFloat(-math.MaxFloat64, 64)
    87  			},
    88  			wantOut: `-1.7976931348623157e+308`,
    89  		},
    90  		{
    91  			desc: "float64 NaN",
    92  			write: func(e *json.Encoder) {
    93  				e.WriteFloat(math.NaN(), 64)
    94  			},
    95  			wantOut: `"NaN"`,
    96  		},
    97  		{
    98  			desc: "float64 Infinity",
    99  			write: func(e *json.Encoder) {
   100  				e.WriteFloat(math.Inf(+1), 64)
   101  			},
   102  			wantOut: `"Infinity"`,
   103  		},
   104  		{
   105  			desc: "float64 -Infinity",
   106  			write: func(e *json.Encoder) {
   107  				e.WriteFloat(math.Inf(-1), 64)
   108  			},
   109  			wantOut: `"-Infinity"`,
   110  		},
   111  		{
   112  			desc: "float64 negative zero",
   113  			write: func(e *json.Encoder) {
   114  				e.WriteFloat(math.Copysign(0, -1), 64)
   115  			},
   116  			wantOut: `-0`,
   117  		},
   118  		{
   119  			desc: "float32",
   120  			write: func(e *json.Encoder) {
   121  				e.WriteFloat(1.02, 32)
   122  			},
   123  			wantOut: `1.02`,
   124  		},
   125  		{
   126  			desc: "float32 max value",
   127  			write: func(e *json.Encoder) {
   128  				e.WriteFloat(math.MaxFloat32, 32)
   129  			},
   130  			wantOut: `3.4028235e+38`,
   131  		},
   132  		{
   133  			desc: "float32 min value",
   134  			write: func(e *json.Encoder) {
   135  				e.WriteFloat(-math.MaxFloat32, 32)
   136  			},
   137  			wantOut: `-3.4028235e+38`,
   138  		},
   139  		{
   140  			desc: "float32 negative zero",
   141  			write: func(e *json.Encoder) {
   142  				e.WriteFloat(math.Copysign(0, -1), 32)
   143  			},
   144  			wantOut: `-0`,
   145  		},
   146  		{
   147  			desc: "int",
   148  			write: func(e *json.Encoder) {
   149  				e.WriteInt(-math.MaxInt64)
   150  			},
   151  			wantOut: `-9223372036854775807`,
   152  		},
   153  		{
   154  			desc: "uint",
   155  			write: func(e *json.Encoder) {
   156  				e.WriteUint(math.MaxUint64)
   157  			},
   158  			wantOut: `18446744073709551615`,
   159  		},
   160  		{
   161  			desc: "empty object",
   162  			write: func(e *json.Encoder) {
   163  				e.StartObject()
   164  				e.EndObject()
   165  			},
   166  			wantOut: `{}`,
   167  		},
   168  		{
   169  			desc: "empty array",
   170  			write: func(e *json.Encoder) {
   171  				e.StartArray()
   172  				e.EndArray()
   173  			},
   174  			wantOut: `[]`,
   175  		},
   176  		{
   177  			desc: "object with one member",
   178  			write: func(e *json.Encoder) {
   179  				e.StartObject()
   180  				e.WriteName("hello")
   181  				e.WriteString("world")
   182  				e.EndObject()
   183  			},
   184  			wantOut: `{"hello":"world"}`,
   185  			wantOutIndent: `{
   186  	"hello": "world"
   187  }`,
   188  		},
   189  		{
   190  			desc: "array with one member",
   191  			write: func(e *json.Encoder) {
   192  				e.StartArray()
   193  				e.WriteNull()
   194  				e.EndArray()
   195  			},
   196  			wantOut: `[null]`,
   197  			wantOutIndent: `[
   198  	null
   199  ]`,
   200  		},
   201  		{
   202  			desc: "simple object",
   203  			write: func(e *json.Encoder) {
   204  				e.StartObject()
   205  				{
   206  					e.WriteName("null")
   207  					e.WriteNull()
   208  				}
   209  				{
   210  					e.WriteName("bool")
   211  					e.WriteBool(true)
   212  				}
   213  				{
   214  					e.WriteName("string")
   215  					e.WriteString("hello")
   216  				}
   217  				{
   218  					e.WriteName("float")
   219  					e.WriteFloat(6.28318, 64)
   220  				}
   221  				{
   222  					e.WriteName("int")
   223  					e.WriteInt(42)
   224  				}
   225  				{
   226  					e.WriteName("uint")
   227  					e.WriteUint(47)
   228  				}
   229  				e.EndObject()
   230  			},
   231  			wantOut: `{"null":null,"bool":true,"string":"hello","float":6.28318,"int":42,"uint":47}`,
   232  			wantOutIndent: `{
   233  	"null": null,
   234  	"bool": true,
   235  	"string": "hello",
   236  	"float": 6.28318,
   237  	"int": 42,
   238  	"uint": 47
   239  }`,
   240  		},
   241  		{
   242  			desc: "simple array",
   243  			write: func(e *json.Encoder) {
   244  				e.StartArray()
   245  				{
   246  					e.WriteString("hello")
   247  					e.WriteFloat(6.28318, 32)
   248  					e.WriteInt(42)
   249  					e.WriteUint(47)
   250  					e.WriteBool(true)
   251  					e.WriteNull()
   252  				}
   253  				e.EndArray()
   254  			},
   255  			wantOut: `["hello",6.28318,42,47,true,null]`,
   256  			wantOutIndent: `[
   257  	"hello",
   258  	6.28318,
   259  	42,
   260  	47,
   261  	true,
   262  	null
   263  ]`,
   264  		},
   265  		{
   266  			desc: "fancy object",
   267  			write: func(e *json.Encoder) {
   268  				e.StartObject()
   269  				{
   270  					e.WriteName("object0")
   271  					e.StartObject()
   272  					e.EndObject()
   273  				}
   274  				{
   275  					e.WriteName("array0")
   276  					e.StartArray()
   277  					e.EndArray()
   278  				}
   279  				{
   280  					e.WriteName("object1")
   281  					e.StartObject()
   282  					{
   283  						e.WriteName("null")
   284  						e.WriteNull()
   285  					}
   286  					{
   287  						e.WriteName("object1-1")
   288  						e.StartObject()
   289  						{
   290  							e.WriteName("bool")
   291  							e.WriteBool(false)
   292  						}
   293  						{
   294  							e.WriteName("float")
   295  							e.WriteFloat(3.14159, 32)
   296  						}
   297  						e.EndObject()
   298  					}
   299  					e.EndObject()
   300  				}
   301  				{
   302  					e.WriteName("array1")
   303  					e.StartArray()
   304  					{
   305  						e.WriteNull()
   306  						e.StartObject()
   307  						e.EndObject()
   308  						e.StartObject()
   309  						{
   310  							e.WriteName("hello")
   311  							e.WriteString("world")
   312  						}
   313  						{
   314  							e.WriteName("hola")
   315  							e.WriteString("mundo")
   316  						}
   317  						e.EndObject()
   318  						e.StartArray()
   319  						{
   320  							e.WriteUint(1)
   321  							e.WriteUint(0)
   322  							e.WriteUint(1)
   323  						}
   324  						e.EndArray()
   325  					}
   326  					e.EndArray()
   327  				}
   328  				e.EndObject()
   329  			},
   330  			wantOutIndent: `{
   331  	"object0": {},
   332  	"array0": [],
   333  	"object1": {
   334  		"null": null,
   335  		"object1-1": {
   336  			"bool": false,
   337  			"float": 3.14159
   338  		}
   339  	},
   340  	"array1": [
   341  		null,
   342  		{},
   343  		{
   344  			"hello": "world",
   345  			"hola": "mundo"
   346  		},
   347  		[
   348  			1,
   349  			0,
   350  			1
   351  		]
   352  	]
   353  }`,
   354  		}}
   355  
   356  	for _, tc := range tests {
   357  		t.Run(tc.desc, func(t *testing.T) {
   358  			if tc.wantOut != "" {
   359  				enc, err := json.NewEncoder(nil, "")
   360  				if err != nil {
   361  					t.Fatalf("NewEncoder() returned error: %v", err)
   362  				}
   363  				tc.write(enc)
   364  				got := string(enc.Bytes())
   365  				if got != tc.wantOut {
   366  					t.Errorf("%s:\n<got>:\n%v\n<want>\n%v\n", tc.desc, got, tc.wantOut)
   367  				}
   368  			}
   369  			if tc.wantOutIndent != "" {
   370  				enc, err := json.NewEncoder(nil, "\t")
   371  				if err != nil {
   372  					t.Fatalf("NewEncoder() returned error: %v", err)
   373  				}
   374  				tc.write(enc)
   375  				got, want := string(enc.Bytes()), tc.wantOutIndent
   376  				if got != want {
   377  					t.Errorf("%s(indent):\n<got>:\n%v\n<want>\n%v\n<diff -want +got>\n%v\n",
   378  						tc.desc, got, want, cmp.Diff(want, got, splitLines))
   379  				}
   380  			}
   381  		})
   382  	}
   383  }
   384  
   385  func TestWriteStringError(t *testing.T) {
   386  	tests := []string{"abc\xff"}
   387  
   388  	for _, in := range tests {
   389  		t.Run(in, func(t *testing.T) {
   390  			enc, err := json.NewEncoder(nil, "")
   391  			if err != nil {
   392  				t.Fatalf("NewEncoder() returned error: %v", err)
   393  			}
   394  			if err := enc.WriteString(in); err == nil {
   395  				t.Errorf("WriteString(%v): got nil error, want error", in)
   396  			}
   397  		})
   398  	}
   399  }
   400  

View as plain text