github.com/sentienttechnologies/studio-go-runner@v0.0.0-20201118202441-6d21f2ced8ee/cmd/runner/json_test.go (about) 1 // Copyright 2018-2020 (c) Cognizant Digital Business, Evolutionary AI. All rights reserved. Issued under the Apache 2.0 License. 2 3 package main 4 5 import ( 6 "testing" 7 8 "github.com/go-stack/stack" 9 "github.com/jjeffery/kv" // MIT License 10 11 "github.com/leaf-ai/studio-go-runner/internal/runner" 12 13 jsonpatch "github.com/evanphx/json-patch" 14 "github.com/go-test/deep" 15 ) 16 17 type ExprJSON struct { 18 Experiment map[string]interface{} `json:"experiment"` 19 } 20 21 // TestAJSONMergePatch is used to exercise the IETF Merge patch document for 22 // https://tools.ietf.org/html/rfc7386 23 // 24 func TestAJSONMergePatch(t *testing.T) { 25 26 x1 := ExprJSON{ 27 Experiment: map[string]interface{}{ 28 "D": "d", 29 "C": "c", 30 "B": "b", 31 "A": "a", 32 }, 33 } 34 x2 := ExprJSON{ 35 Experiment: map[string]interface{}{ 36 "A": 1, 37 "E": 2, 38 }, 39 } 40 41 expected1 := `{ "experiment": { "A": "a", "B": "b", "C": "c", "D": "d", "E": 2 } }` 42 doc1, err := runner.ExtractMergeDoc(x1, x2) 43 if err != nil { 44 t.Fatal(err) 45 } 46 if diff := deep.Equal(expected1, doc1); diff != nil { 47 t.Fatal(kv.NewError("JSON Merge Patch RFC 7386 Test failed").With("diff", diff, "stack", stack.Trace().TrimRuntime())) 48 } 49 50 expected2 := `{ "experiment": { "A": 1, "B": "b", "C": "c", "D": "d", "E": 2 } }` 51 doc2, err := runner.ExtractMergeDoc(x2, x1) 52 if err != nil { 53 t.Fatal(err) 54 } 55 if diff := deep.Equal(expected2, doc2); diff != nil { 56 t.Fatal(kv.NewError("JSON Merge Patch RFC 7386 Test failed").With("diff", diff, "stack", stack.Trace().TrimRuntime())) 57 } 58 } 59 60 // TestAJSONPatch exercises a simple test case for the https://tools.ietf.org/html/rfc6902 61 // 62 func TestAJSONPatch(t *testing.T) { 63 64 original := []byte(`{"experiment": {"name": "John", "age": 24, "height": 3.21}}`) 65 patchJSON := []byte(`[ 66 {"op": "replace", "path": "/experiment/name", "value": "Jane"}, 67 {"op": "remove", "path": "/experiment/height"} 68 ]`) 69 70 patch, errGo := jsonpatch.DecodePatch(patchJSON) 71 if errGo != nil { 72 t.Fatal(kv.Wrap(errGo).With("stack", stack.Trace().TrimRuntime())) 73 } 74 75 modified, errGo := patch.Apply(original) 76 if errGo != nil { 77 t.Fatal(kv.Wrap(errGo).With("stack", stack.Trace().TrimRuntime())) 78 } 79 80 expected := `{"experiment":{"age":24,"name":"Jane"}}` 81 if diff := deep.Equal(expected, string(modified)); diff != nil { 82 t.Fatal(kv.NewError("JSON Patch RFC 6902 Test failed").With("diff", diff, "stack", stack.Trace().TrimRuntime())) 83 } 84 } 85 86 // TestAJSONEditor Will put together some merge style patches and some editor style patches and run these 87 // through the runners internal editor 88 func TestAJSONzEditor(t *testing.T) { 89 90 type testCase struct { 91 directive string 92 expected string 93 } 94 // A table driven test is used with progressive edits and merges 95 testCases := []testCase{ 96 { 97 `{"experiment": {"name": "testExpr", "max_run_length": 24, "run_length": 3.21}}`, 98 `{"experiment": {"name": "testExpr", "max_run_length": 24, "run_length": 3.21}}`, 99 }, 100 { 101 `[{"op": "replace", "path": "/experiment/name", "value": "testExpr1"}]`, 102 `{"experiment": {"name": "testExpr1", "max_run_length": 24, "run_length": 3.21}}`, 103 }, 104 { 105 `[{"op": "remove", "path": "/experiment/max_run_length"}]`, 106 `{"experiment": {"name": "testExpr1", "run_length": 3.21}}`, 107 }, 108 { 109 `[{"op": "add", "path": "/experiment/addition_1", "value": "additional data 1"}]`, 110 `{"experiment": {"name": "testExpr1", "run_length": 3.21, "addition_1":"additional data 1"}}`, 111 }, 112 { 113 `{"experiment": {"addition_2": "additional data 2"}}`, 114 `{"experiment": {"name": "testExpr1", "run_length": 3.21, "addition_1":"additional data 1", "addition_2": "additional data 2"}}`, 115 }, 116 } 117 118 doc := "{}" 119 // run one test at a time 120 for _, testCase := range testCases { 121 newDoc, err := runner.JSONEditor(doc, []string{testCase.directive}) 122 if err != nil { 123 t.Fatal(err) 124 } 125 if !jsonpatch.Equal([]byte(newDoc), []byte(testCase.expected)) { 126 t.Fatal(kv.NewError("JSON Editor Test failed").With("expected", testCase.expected, "actual", newDoc, "stack", stack.Trace().TrimRuntime())) 127 } 128 doc = newDoc 129 } 130 131 // re-run tests in incremental batches 132 for limit := 1; limit != len(testCases)-1; limit++ { 133 doc = "{}" 134 directives := []string{} 135 for _, testCase := range testCases[0:limit] { 136 directives = append(directives, testCase.directive) 137 } 138 doc, err := runner.JSONEditor(doc, directives) 139 if err != nil { 140 t.Fatal(err) 141 } 142 if !jsonpatch.Equal([]byte(doc), []byte(testCases[limit-1].expected)) { 143 t.Fatal(kv.NewError("JSON Editor Test failed").With("expected", testCases[limit-1].expected, "actual", doc, "stack", stack.Trace().TrimRuntime())) 144 } 145 } 146 }