github.com/cloudwego/kitex@v0.9.0/pkg/generic/proto/json_test.go (about) 1 /* 2 * Copyright 2023 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package proto 18 19 import ( 20 "context" 21 "encoding/json" 22 "io/ioutil" 23 "testing" 24 25 "github.com/cloudwego/dynamicgo/conv" 26 "github.com/cloudwego/dynamicgo/proto" 27 "github.com/cloudwego/dynamicgo/testdata/kitex_gen/pb/example2" 28 "github.com/stretchr/testify/require" 29 goprotowire "google.golang.org/protobuf/encoding/protowire" 30 31 "github.com/cloudwego/kitex/internal/test" 32 ) 33 34 var ( 35 example2IDLPath = "../jsonpb_test/idl/example2.proto" 36 example2ProtoPath = "../jsonpb_test/data/example2_pb.bin" 37 ) 38 39 func TestRun(t *testing.T) { 40 t.Run("TestWrite", TestWrite) 41 t.Run("TestRead", TestRead) 42 } 43 44 // Check NewWriteJSON converting JSON to protobuf wire format 45 func TestWrite(t *testing.T) { 46 method := "ExampleMethod" 47 48 opts := proto.Options{} 49 svc, err := opts.NewDescriptorFromPath(context.Background(), example2IDLPath) 50 test.Assert(t, err == nil) 51 52 wm, err := NewWriteJSON(svc, method, true, &conv.Options{}) 53 test.Assert(t, err == nil) 54 55 msg := getExampleReq() 56 57 // get expected json struct 58 exp := &example2.ExampleReq{} 59 json.Unmarshal([]byte(msg), exp) 60 61 // marshal json string into protobuf wire format using Write 62 out, err := wm.Write(context.Background(), msg) 63 test.Assert(t, err == nil) 64 buf, ok := out.([]byte) 65 test.Assert(t, ok) 66 67 // read into struct using fastread 68 act := &example2.ExampleReq{} 69 l := 0 70 // fmt.Print(out) 71 dataLen := len(buf) 72 // fastRead to get target struct 73 for l < dataLen { 74 id, wtyp, tagLen := goprotowire.ConsumeTag(buf) 75 if tagLen < 0 { 76 t.Fatal("test failed") 77 } 78 l += tagLen 79 buf = buf[tagLen:] 80 offset, err := act.FastRead(buf, int8(wtyp), int32(id)) 81 require.Nil(t, err) 82 buf = buf[offset:] 83 l += offset 84 } 85 test.Assert(t, err == nil) 86 87 // compare exp and act struct 88 require.Equal(t, exp, act) 89 } 90 91 // Check NewReadJSON converting protobuf wire format to JSON 92 func TestRead(t *testing.T) { 93 // get protobuf wire format data 94 in := readExampleReqProtoBufData() 95 method := "ExampleMethod" 96 97 opts := proto.Options{} 98 svc, err := opts.NewDescriptorFromPath(context.Background(), example2IDLPath) 99 test.Assert(t, err == nil) 100 101 rm, err := NewReadJSON(svc, false, &conv.Options{}) 102 test.Assert(t, err == nil) 103 104 // unmarshal protobuf wire format into json string using Read 105 out, err := rm.Read(context.Background(), method, in) 106 test.Assert(t, err == nil) 107 108 // get expected json struct 109 exp := &example2.ExampleReq{} 110 111 l := 0 112 dataLen := len(in) 113 for l < dataLen { 114 id, wtyp, tagLen := goprotowire.ConsumeTag(in) 115 if tagLen < 0 { 116 t.Fatal("proto data error format") 117 } 118 l += tagLen 119 in = in[tagLen:] 120 offset, err := exp.FastRead(in, int8(wtyp), int32(id)) 121 require.Nil(t, err) 122 in = in[offset:] 123 l += offset 124 } 125 if len(in) != 0 { 126 t.Fatal("proto data error format") 127 } 128 test.Assert(t, err == nil) 129 130 act := &example2.ExampleReq{} 131 str, ok := out.(string) 132 test.Assert(t, ok) 133 json.Unmarshal([]byte(str), &act) 134 135 // compare exp and act struct 136 require.Equal(t, exp, act) 137 } 138 139 // helper methods 140 func getExampleReq() string { 141 return `{ 142 "Msg":"hello", 143 "A":25, 144 "InnerBase2":{ 145 "Bool":true, 146 "Uint32":123, 147 "Uint64":123, 148 "Double":22.3, 149 "String":"hello_inner", 150 "ListInt32":[12,13,14,15,16,17], 151 "MapStringString":{"m1":"aaa","m2":"bbb"}, 152 "SetInt32":[200,201,202,203,204,205], 153 "MapInt32String":{"1":"aaa","2":"bbb","3":"ccc","4":"ddd"}, 154 "Binary":"AQIDBA==", 155 "MapUint32String":{"1":"u32aa","2":"u32bb","3":"u32cc","4":"u32dd"}, 156 "MapUint64String":{"1":"u64aa","2":"u64bb","3":"u64cc","4":"u64dd"}, 157 "MapInt64String":{"1":"64aaa","2":"64bbb","3":"64ccc","4":"64ddd"}, 158 "MapInt64Base":{ 159 "1":{ 160 "LogID":"logId","Caller":"caller","Addr":"addr","Client":"client","TrafficEnv":{"Env":"env"},"Extra":{"1a":"aaa","2a":"bbb","3a":"ccc","4a":"ddd"} 161 }, 162 "2":{ 163 "LogID":"logId2","Caller":"caller2","Addr":"addr2","Client":"client2","TrafficEnv":{"Open":true,"Env":"env2"},"Extra":{"1a":"aaa2","2a":"bbb2","3a":"ccc2","4a":"ddd2"} 164 } 165 }, 166 "MapStringBase":{ 167 "1":{ 168 "LogID":"logId","Caller":"caller","Addr":"addr","Client":"client","TrafficEnv":{"Env":"env"},"Extra":{"1a":"aaa","2a":"bbb","3a":"ccc","4a":"ddd"} 169 }, 170 "2":{ 171 "LogID":"logId2","Caller":"caller2","Addr":"addr2","Client":"client2","TrafficEnv":{"Open":true,"Env":"env2"},"Extra":{"1a":"aaa2","2a":"bbb2","3a":"ccc2","4a":"ddd2"} 172 } 173 }, 174 "ListBase":[ 175 {"LogID":"logId","Caller":"caller","Addr":"addr","Client":"client","TrafficEnv":{"Env":"env"},"Extra":{"1a":"aaa","2a":"bbb","3a":"ccc","4a":"ddd"}}, 176 {"LogID":"logId2","Caller":"caller2","Addr":"addr2","Client":"client2","TrafficEnv":{"Open":true,"Env":"env2"},"Extra":{"1a":"aaa2","2a":"bbb2","3a":"ccc2","4a":"ddd2"}} 177 ], 178 "ListString":["111","222","333","44","51","6"], 179 "Base":{"LogID":"logId","Caller":"caller","Addr":"addr","Client":"client","TrafficEnv":{"Env":"env"},"Extra":{"1b":"aaa","2b":"bbb","3b":"ccc","4b":"ddd"}} 180 } 181 }` 182 } 183 184 // read ProtoBuf's data in binary format from exampleProtoPath 185 func readExampleReqProtoBufData() []byte { 186 out, err := ioutil.ReadFile(example2ProtoPath) 187 if err != nil { 188 panic(err) 189 } 190 return out 191 }