...

Source file src/github.com/evanphx/json-patch/patch_test.go

Documentation: github.com/evanphx/json-patch

     1  package jsonpatch
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"reflect"
     8  	"testing"
     9  )
    10  
    11  func reformatJSON(j string) string {
    12  	buf := new(bytes.Buffer)
    13  
    14  	json.Indent(buf, []byte(j), "", "  ")
    15  
    16  	return buf.String()
    17  }
    18  
    19  func compareJSON(a, b string) bool {
    20  	// return Equal([]byte(a), []byte(b))
    21  
    22  	var objA, objB map[string]interface{}
    23  	json.Unmarshal([]byte(a), &objA)
    24  	json.Unmarshal([]byte(b), &objB)
    25  
    26  	// fmt.Printf("Comparing %#v\nagainst %#v\n", objA, objB)
    27  	return reflect.DeepEqual(objA, objB)
    28  }
    29  
    30  func applyPatch(doc, patch string) (string, error) {
    31  	obj, err := DecodePatch([]byte(patch))
    32  
    33  	if err != nil {
    34  		panic(err)
    35  	}
    36  
    37  	out, err := obj.Apply([]byte(doc))
    38  
    39  	if err != nil {
    40  		return "", err
    41  	}
    42  
    43  	return string(out), nil
    44  }
    45  
    46  type Case struct {
    47  	doc, patch, result string
    48  }
    49  
    50  func repeatedA(r int) string {
    51  	var s string
    52  	for i := 0; i < r; i++ {
    53  		s += "A"
    54  	}
    55  	return s
    56  }
    57  
    58  var Cases = []Case{
    59  	{
    60  		``,
    61  		`[
    62           { "op": "add", "path": "/baz", "value": "qux" }
    63       ]`,
    64  		``,
    65  	},
    66  	{
    67  		`{ "foo": "bar"}`,
    68  		`[
    69           { "op": "add", "path": "/baz", "value": "qux" }
    70       ]`,
    71  		`{
    72         "baz": "qux",
    73         "foo": "bar"
    74       }`,
    75  	},
    76  	{
    77  		`{ "foo": [ "bar", "baz" ] }`,
    78  		`[
    79       { "op": "add", "path": "/foo/1", "value": "qux" }
    80      ]`,
    81  		`{ "foo": [ "bar", "qux", "baz" ] }`,
    82  	},
    83  	{
    84  		`{ "foo": [ "bar", "baz" ] }`,
    85  		`[
    86       { "op": "add", "path": "/foo/-1", "value": "qux" }
    87      ]`,
    88  		`{ "foo": [ "bar", "baz", "qux" ] }`,
    89  	},
    90  	{
    91  		`{ "baz": "qux", "foo": "bar" }`,
    92  		`[ { "op": "remove", "path": "/baz" } ]`,
    93  		`{ "foo": "bar" }`,
    94  	},
    95  	{
    96  		`{ "foo": [ "bar", "qux", "baz" ] }`,
    97  		`[ { "op": "remove", "path": "/foo/1" } ]`,
    98  		`{ "foo": [ "bar", "baz" ] }`,
    99  	},
   100  	{
   101  		`{ "baz": "qux", "foo": "bar" }`,
   102  		`[ { "op": "replace", "path": "/baz", "value": "boo" } ]`,
   103  		`{ "baz": "boo", "foo": "bar" }`,
   104  	},
   105  	{
   106  		`{
   107       "foo": {
   108         "bar": "baz",
   109         "waldo": "fred"
   110       },
   111       "qux": {
   112         "corge": "grault"
   113       }
   114     }`,
   115  		`[ { "op": "move", "from": "/foo/waldo", "path": "/qux/thud" } ]`,
   116  		`{
   117       "foo": {
   118         "bar": "baz"
   119       },
   120       "qux": {
   121         "corge": "grault",
   122         "thud": "fred"
   123       }
   124     }`,
   125  	},
   126  	{
   127  		`{ "foo": [ "all", "grass", "cows", "eat" ] }`,
   128  		`[ { "op": "move", "from": "/foo/1", "path": "/foo/3" } ]`,
   129  		`{ "foo": [ "all", "cows", "eat", "grass" ] }`,
   130  	},
   131  	{
   132  		`{ "foo": [ "all", "grass", "cows", "eat" ] }`,
   133  		`[ { "op": "move", "from": "/foo/1", "path": "/foo/2" } ]`,
   134  		`{ "foo": [ "all", "cows", "grass", "eat" ] }`,
   135  	},
   136  	{
   137  		`{ "foo": "bar" }`,
   138  		`[ { "op": "add", "path": "/child", "value": { "grandchild": { } } } ]`,
   139  		`{ "foo": "bar", "child": { "grandchild": { } } }`,
   140  	},
   141  	{
   142  		`{ "foo": ["bar"] }`,
   143  		`[ { "op": "add", "path": "/foo/-", "value": ["abc", "def"] } ]`,
   144  		`{ "foo": ["bar", ["abc", "def"]] }`,
   145  	},
   146  	{
   147  		`{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`,
   148  		`[ { "op": "remove", "path": "/qux/bar" } ]`,
   149  		`{ "foo": "bar", "qux": { "baz": 1 } }`,
   150  	},
   151  	{
   152  		`{ "foo": "bar" }`,
   153  		`[ { "op": "add", "path": "/baz", "value": null } ]`,
   154  		`{ "baz": null, "foo": "bar" }`,
   155  	},
   156  	{
   157  		`{ "foo": ["bar"]}`,
   158  		`[ { "op": "replace", "path": "/foo/0", "value": "baz"}]`,
   159  		`{ "foo": ["baz"]}`,
   160  	},
   161  	{
   162  		`{ "foo": ["bar","baz"]}`,
   163  		`[ { "op": "replace", "path": "/foo/0", "value": "bum"}]`,
   164  		`{ "foo": ["bum","baz"]}`,
   165  	},
   166  	{
   167  		`{ "foo": ["bar","qux","baz"]}`,
   168  		`[ { "op": "replace", "path": "/foo/1", "value": "bum"}]`,
   169  		`{ "foo": ["bar", "bum","baz"]}`,
   170  	},
   171  	{
   172  		`[ {"foo": ["bar","qux","baz"]}]`,
   173  		`[ { "op": "replace", "path": "/0/foo/0", "value": "bum"}]`,
   174  		`[ {"foo": ["bum","qux","baz"]}]`,
   175  	},
   176  	{
   177  		`[ {"foo": ["bar","qux","baz"], "bar": ["qux","baz"]}]`,
   178  		`[ { "op": "copy", "from": "/0/foo/0", "path": "/0/bar/0"}]`,
   179  		`[ {"foo": ["bar","qux","baz"], "bar": ["bar", "baz"]}]`,
   180  	},
   181  	{
   182  		`[ {"foo": ["bar","qux","baz"], "bar": ["qux","baz"]}]`,
   183  		`[ { "op": "copy", "from": "/0/foo/0", "path": "/0/bar"}]`,
   184  		`[ {"foo": ["bar","qux","baz"], "bar": ["bar", "qux", "baz"]}]`,
   185  	},
   186  	{
   187  		`[ { "foo": {"bar": ["qux","baz"]}, "baz": {"qux": "bum"}}]`,
   188  		`[ { "op": "copy", "from": "/0/foo/bar", "path": "/0/baz/bar"}]`,
   189  		`[ { "baz": {"bar": ["qux","baz"], "qux":"bum"}, "foo": {"bar": ["qux","baz"]}}]`,
   190  	},
   191  	{
   192  		`{ "foo": ["bar"]}`,
   193  		`[{"op": "copy", "path": "/foo/0", "from": "/foo"}]`,
   194  		`{ "foo": [["bar"], "bar"]}`,
   195  	},
   196  	{
   197  		`{ "foo": ["bar","qux","baz"]}`,
   198  		`[ { "op": "remove", "path": "/foo/-2"}]`,
   199  		`{ "foo": ["bar", "baz"]}`,
   200  	},
   201  	{
   202  		`{ "foo": []}`,
   203  		`[ { "op": "add", "path": "/foo/-1", "value": "qux"}]`,
   204  		`{ "foo": ["qux"]}`,
   205  	},
   206  	{
   207  		`{ "bar": [{"baz": null}]}`,
   208  		`[ { "op": "replace", "path": "/bar/0/baz", "value": 1 } ]`,
   209  		`{ "bar": [{"baz": 1}]}`,
   210  	},
   211  	{
   212  		`{ "bar": [{"baz": 1}]}`,
   213  		`[ { "op": "replace", "path": "/bar/0/baz", "value": null } ]`,
   214  		`{ "bar": [{"baz": null}]}`,
   215  	},
   216  	{
   217  		`{ "bar": [null]}`,
   218  		`[ { "op": "replace", "path": "/bar/0", "value": 1 } ]`,
   219  		`{ "bar": [1]}`,
   220  	},
   221  	{
   222  		`{ "bar": [1]}`,
   223  		`[ { "op": "replace", "path": "/bar/0", "value": null } ]`,
   224  		`{ "bar": [null]}`,
   225  	},
   226  	{
   227  		fmt.Sprintf(`{ "foo": ["A", %q] }`, repeatedA(48)),
   228  		// The wrapping quotes around 'A's are included in the copy
   229  		// size, so each copy operation increases the size by 50 bytes.
   230  		`[ { "op": "copy", "path": "/foo/-", "from": "/foo/1" },
   231  		   { "op": "copy", "path": "/foo/-", "from": "/foo/1" }]`,
   232  		fmt.Sprintf(`{ "foo": ["A", %q, %q, %q] }`, repeatedA(48), repeatedA(48), repeatedA(48)),
   233  	},
   234  	{
   235  		`{
   236        "id": "00000000-0000-0000-0000-000000000000",
   237        "parentID": "00000000-0000-0000-0000-000000000000"
   238  		}`,
   239  		`[
   240   {
   241     "op": "test",
   242     "path": "",
   243     "value": {
   244       "id": "00000000-0000-0000-0000-000000000000",
   245       "parentID": "00000000-0000-0000-0000-000000000000"
   246     }
   247   },
   248   {
   249     "op": "replace",
   250     "path": "",
   251     "value": {
   252       "id": "759981e8-ec68-4639-a83e-513225914ecb",
   253       "originalID": "bar",
   254       "parentID": "00000000-0000-0000-0000-000000000000"
   255     }
   256   }
   257  		]`,
   258  		`{
   259   "id" : "759981e8-ec68-4639-a83e-513225914ecb",
   260   "originalID" : "bar",
   261   "parentID" : "00000000-0000-0000-0000-000000000000"
   262  		}`,
   263  	},
   264  }
   265  
   266  type BadCase struct {
   267  	doc, patch string
   268  }
   269  
   270  var MutationTestCases = []BadCase{
   271  	{
   272  		`{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`,
   273  		`[ { "op": "remove", "path": "/qux/bar" } ]`,
   274  	},
   275  	{
   276  		`{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`,
   277  		`[ { "op": "replace", "path": "/qux/baz", "value": null } ]`,
   278  	},
   279  }
   280  
   281  var BadCases = []BadCase{
   282  	{
   283  		`{ "foo": "bar" }`,
   284  		`[ { "op": "add", "path": "/baz/bat", "value": "qux" } ]`,
   285  	},
   286  	{
   287  		`{ "a": { "b": { "d": 1 } } }`,
   288  		`[ { "op": "remove", "path": "/a/b/c" } ]`,
   289  	},
   290  	{
   291  		`{ "a": { "b": { "d": 1 } } }`,
   292  		`[ { "op": "move", "from": "/a/b/c", "path": "/a/b/e" } ]`,
   293  	},
   294  	{
   295  		`{ "a": { "b": [1] } }`,
   296  		`[ { "op": "remove", "path": "/a/b/1" } ]`,
   297  	},
   298  	{
   299  		`{ "a": { "b": [1] } }`,
   300  		`[ { "op": "move", "from": "/a/b/1", "path": "/a/b/2" } ]`,
   301  	},
   302  	{
   303  		`{ "foo": "bar" }`,
   304  		`[ { "op": "add", "pathz": "/baz", "value": "qux" } ]`,
   305  	},
   306  	{
   307  		`{ "foo": "bar" }`,
   308  		`[ { "op": "add", "path": "", "value": "qux" } ]`,
   309  	},
   310  	{
   311  		`{ "foo": ["bar","baz"]}`,
   312  		`[ { "op": "replace", "path": "/foo/2", "value": "bum"}]`,
   313  	},
   314  	{
   315  		`{ "foo": ["bar","baz"]}`,
   316  		`[ { "op": "add", "path": "/foo/-4", "value": "bum"}]`,
   317  	},
   318  	{
   319  		`{ "name":{ "foo": "bat", "qux": "bum"}}`,
   320  		`[ { "op": "replace", "path": "/foo/bar", "value":"baz"}]`,
   321  	},
   322  	{
   323  		`{ "foo": ["bar"]}`,
   324  		`[ {"op": "add", "path": "/foo/2", "value": "bum"}]`,
   325  	},
   326  	{
   327  		`{ "foo": []}`,
   328  		`[ {"op": "remove", "path": "/foo/-"}]`,
   329  	},
   330  	{
   331  		`{ "foo": []}`,
   332  		`[ {"op": "remove", "path": "/foo/-1"}]`,
   333  	},
   334  	{
   335  		`{ "foo": ["bar"]}`,
   336  		`[ {"op": "remove", "path": "/foo/-2"}]`,
   337  	},
   338  	{
   339  		`{}`,
   340  		`[ {"op":null,"path":""} ]`,
   341  	},
   342  	{
   343  		`{}`,
   344  		`[ {"op":"add","path":null} ]`,
   345  	},
   346  	{
   347  		`{}`,
   348  		`[ { "op": "copy", "from": null }]`,
   349  	},
   350  	{
   351  		`{ "foo": ["bar"]}`,
   352  		`[{"op": "copy", "path": "/foo/6666666666", "from": "/"}]`,
   353  	},
   354  	// Can't copy into an index greater than the size of the array
   355  	{
   356  		`{ "foo": ["bar"]}`,
   357  		`[{"op": "copy", "path": "/foo/2", "from": "/foo/0"}]`,
   358  	},
   359  	// Accumulated copy size cannot exceed AccumulatedCopySizeLimit.
   360  	{
   361  		fmt.Sprintf(`{ "foo": ["A", %q] }`, repeatedA(49)),
   362  		// The wrapping quotes around 'A's are included in the copy
   363  		// size, so each copy operation increases the size by 51 bytes.
   364  		`[ { "op": "copy", "path": "/foo/-", "from": "/foo/1" },
   365  		   { "op": "copy", "path": "/foo/-", "from": "/foo/1" }]`,
   366  	},
   367  	// Can't move into an index greater than or equal to the size of the array
   368  	{
   369  		`{ "foo": [ "all", "grass", "cows", "eat" ] }`,
   370  		`[ { "op": "move", "from": "/foo/1", "path": "/foo/4" } ]`,
   371  	},
   372  }
   373  
   374  // This is not thread safe, so we cannot run patch tests in parallel.
   375  func configureGlobals(accumulatedCopySizeLimit int64) func() {
   376  	oldAccumulatedCopySizeLimit := AccumulatedCopySizeLimit
   377  	AccumulatedCopySizeLimit = accumulatedCopySizeLimit
   378  	return func() {
   379  		AccumulatedCopySizeLimit = oldAccumulatedCopySizeLimit
   380  	}
   381  }
   382  
   383  func TestAllCases(t *testing.T) {
   384  	defer configureGlobals(int64(100))()
   385  	for _, c := range Cases {
   386  		out, err := applyPatch(c.doc, c.patch)
   387  
   388  		if err != nil {
   389  			t.Errorf("Unable to apply patch: %s", err)
   390  		}
   391  
   392  		if !compareJSON(out, c.result) {
   393  			t.Errorf("Patch did not apply. Expected:\n%s\n\nActual:\n%s",
   394  				reformatJSON(c.result), reformatJSON(out))
   395  		}
   396  	}
   397  
   398  	for _, c := range MutationTestCases {
   399  		out, err := applyPatch(c.doc, c.patch)
   400  
   401  		if err != nil {
   402  			t.Errorf("Unable to apply patch: %s", err)
   403  		}
   404  
   405  		if compareJSON(out, c.doc) {
   406  			t.Errorf("Patch did not apply. Original:\n%s\n\nPatched:\n%s",
   407  				reformatJSON(c.doc), reformatJSON(out))
   408  		}
   409  	}
   410  
   411  	for _, c := range BadCases {
   412  		_, err := applyPatch(c.doc, c.patch)
   413  
   414  		if err == nil {
   415  			t.Errorf("Patch %q should have failed to apply but it did not", c.patch)
   416  		}
   417  	}
   418  }
   419  
   420  type TestCase struct {
   421  	doc, patch string
   422  	result     bool
   423  	failedPath string
   424  }
   425  
   426  var TestCases = []TestCase{
   427  	{
   428  		`{
   429        "baz": "qux",
   430        "foo": [ "a", 2, "c" ]
   431      }`,
   432  		`[
   433        { "op": "test", "path": "/baz", "value": "qux" },
   434        { "op": "test", "path": "/foo/1", "value": 2 }
   435      ]`,
   436  		true,
   437  		"",
   438  	},
   439  	{
   440  		`{ "baz": "qux" }`,
   441  		`[ { "op": "test", "path": "/baz", "value": "bar" } ]`,
   442  		false,
   443  		"/baz",
   444  	},
   445  	{
   446  		`{
   447        "baz": "qux",
   448        "foo": ["a", 2, "c"]
   449      }`,
   450  		`[
   451        { "op": "test", "path": "/baz", "value": "qux" },
   452        { "op": "test", "path": "/foo/1", "value": "c" }
   453      ]`,
   454  		false,
   455  		"/foo/1",
   456  	},
   457  	{
   458  		`{ "baz": "qux" }`,
   459  		`[ { "op": "test", "path": "/foo", "value": 42 } ]`,
   460  		false,
   461  		"/foo",
   462  	},
   463  	{
   464  		`{ "baz": "qux" }`,
   465  		`[ { "op": "test", "path": "/foo", "value": null } ]`,
   466  		true,
   467  		"",
   468  	},
   469  	{
   470  		`{ "foo": null }`,
   471  		`[ { "op": "test", "path": "/foo", "value": null } ]`,
   472  		true,
   473  		"",
   474  	},
   475  	{
   476  		`{ "foo": {} }`,
   477  		`[ { "op": "test", "path": "/foo", "value": null } ]`,
   478  		false,
   479  		"/foo",
   480  	},
   481  	{
   482  		`{ "foo": [] }`,
   483  		`[ { "op": "test", "path": "/foo", "value": null } ]`,
   484  		false,
   485  		"/foo",
   486  	},
   487  	{
   488  		`{ "baz/foo": "qux" }`,
   489  		`[ { "op": "test", "path": "/baz~1foo", "value": "qux"} ]`,
   490  		true,
   491  		"",
   492  	},
   493  	{
   494  		`{ "foo": [] }`,
   495  		`[ { "op": "test", "path": "/foo"} ]`,
   496  		false,
   497  		"/foo",
   498  	},
   499  	{
   500  		`{ "baz": [] }`,
   501  		`[ { "op": "test", "path": "/foo"} ]`,
   502  		true,
   503  		"/foo",
   504  	},
   505  }
   506  
   507  func TestAllTest(t *testing.T) {
   508  	for _, c := range TestCases {
   509  		_, err := applyPatch(c.doc, c.patch)
   510  
   511  		if c.result && err != nil {
   512  			t.Errorf("Testing failed when it should have passed: %s", err)
   513  		} else if !c.result && err == nil {
   514  			t.Errorf("Testing passed when it should have faild: %s", err)
   515  		} else if !c.result {
   516  			expected := fmt.Sprintf("testing value %s failed: test failed", c.failedPath)
   517  			if err.Error() != expected {
   518  				t.Errorf("Testing failed as expected but invalid message: expected [%s], got [%s]", expected, err)
   519  			}
   520  		}
   521  	}
   522  }
   523  
   524  func TestAdd(t *testing.T) {
   525  	testCases := []struct {
   526  		name                   string
   527  		key                    string
   528  		val                    lazyNode
   529  		arr                    partialArray
   530  		rejectNegativeIndicies bool
   531  		err                    string
   532  	}{
   533  		{
   534  			name: "should work",
   535  			key:  "0",
   536  			val:  lazyNode{},
   537  			arr:  partialArray{},
   538  		},
   539  		{
   540  			name: "index too large",
   541  			key:  "1",
   542  			val:  lazyNode{},
   543  			arr:  partialArray{},
   544  			err:  "Unable to access invalid index: 1: invalid index referenced",
   545  		},
   546  		{
   547  			name: "negative should work",
   548  			key:  "-1",
   549  			val:  lazyNode{},
   550  			arr:  partialArray{},
   551  		},
   552  		{
   553  			name: "negative too small",
   554  			key:  "-2",
   555  			val:  lazyNode{},
   556  			arr:  partialArray{},
   557  			err:  "Unable to access invalid index: -2: invalid index referenced",
   558  		},
   559  		{
   560  			name: "negative but negative disabled",
   561  			key:  "-1",
   562  			val:  lazyNode{},
   563  			arr:  partialArray{},
   564  			err:  "Unable to access invalid index: -1: invalid index referenced",
   565  
   566  			rejectNegativeIndicies: true,
   567  		},
   568  	}
   569  	for _, tc := range testCases {
   570  		t.Run(tc.name, func(t *testing.T) {
   571  			SupportNegativeIndices = !tc.rejectNegativeIndicies
   572  			key := tc.key
   573  			arr := &tc.arr
   574  			val := &tc.val
   575  			err := arr.add(key, val)
   576  			if err == nil && tc.err != "" {
   577  				t.Errorf("Expected error but got none! %v", tc.err)
   578  			} else if err != nil && tc.err == "" {
   579  				t.Errorf("Did not expect error but go: %v", err)
   580  			} else if err != nil && err.Error() != tc.err {
   581  				t.Errorf("Expected error %v but got error %v", tc.err, err)
   582  			}
   583  		})
   584  	}
   585  }
   586  
   587  type EqualityCase struct {
   588  	name  string
   589  	a, b  string
   590  	equal bool
   591  }
   592  
   593  var EqualityCases = []EqualityCase{
   594  	{
   595  		"ExtraKeyFalse",
   596  		`{"foo": "bar"}`,
   597  		`{"foo": "bar", "baz": "qux"}`,
   598  		false,
   599  	},
   600  	{
   601  		"StripWhitespaceTrue",
   602  		`{
   603  			"foo": "bar",
   604  			"baz": "qux"
   605  		}`,
   606  		`{"foo": "bar", "baz": "qux"}`,
   607  		true,
   608  	},
   609  	{
   610  		"KeysOutOfOrderTrue",
   611  		`{
   612  			"baz": "qux",
   613  			"foo": "bar"
   614  		}`,
   615  		`{"foo": "bar", "baz": "qux"}`,
   616  		true,
   617  	},
   618  	{
   619  		"ComparingNullFalse",
   620  		`{"foo": null}`,
   621  		`{"foo": "bar"}`,
   622  		false,
   623  	},
   624  	{
   625  		"ComparingNullTrue",
   626  		`{"foo": null}`,
   627  		`{"foo": null}`,
   628  		true,
   629  	},
   630  	{
   631  		"ArrayOutOfOrderFalse",
   632  		`["foo", "bar", "baz"]`,
   633  		`["bar", "baz", "foo"]`,
   634  		false,
   635  	},
   636  	{
   637  		"ArrayTrue",
   638  		`["foo", "bar", "baz"]`,
   639  		`["foo", "bar", "baz"]`,
   640  		true,
   641  	},
   642  	{
   643  		"NonStringTypesTrue",
   644  		`{"int": 6, "bool": true, "float": 7.0, "string": "the_string", "null": null}`,
   645  		`{"int": 6, "bool": true, "float": 7.0, "string": "the_string", "null": null}`,
   646  		true,
   647  	},
   648  	{
   649  		"NestedNullFalse",
   650  		`{"foo": ["an", "array"], "bar": {"an": "object"}}`,
   651  		`{"foo": null, "bar": null}`,
   652  		false,
   653  	},
   654  	{
   655  		"NullCompareStringFalse",
   656  		`"foo"`,
   657  		`null`,
   658  		false,
   659  	},
   660  	{
   661  		"NullCompareIntFalse",
   662  		`6`,
   663  		`null`,
   664  		false,
   665  	},
   666  	{
   667  		"NullCompareFloatFalse",
   668  		`6.01`,
   669  		`null`,
   670  		false,
   671  	},
   672  	{
   673  		"NullCompareBoolFalse",
   674  		`false`,
   675  		`null`,
   676  		false,
   677  	},
   678  }
   679  
   680  func TestEquality(t *testing.T) {
   681  	for _, tc := range EqualityCases {
   682  		t.Run(tc.name, func(t *testing.T) {
   683  			got := Equal([]byte(tc.a), []byte(tc.b))
   684  			if got != tc.equal {
   685  				t.Errorf("Expected Equal(%s, %s) to return %t, but got %t", tc.a, tc.b, tc.equal, got)
   686  			}
   687  
   688  			got = Equal([]byte(tc.b), []byte(tc.a))
   689  			if got != tc.equal {
   690  				t.Errorf("Expected Equal(%s, %s) to return %t, but got %t", tc.b, tc.a, tc.equal, got)
   691  			}
   692  		})
   693  	}
   694  }
   695  

View as plain text