github.com/GuanceCloud/cliutils@v1.1.21/point/pbpoint_test.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package point 7 8 import ( 9 "encoding/json" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/GuanceCloud/cliutils" 15 proto "github.com/gogo/protobuf/proto" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 var name = "abc" 20 21 func BenchmarkMarshal(b *testing.B) { 22 cases := []struct { 23 name string 24 repeat int 25 }{ 26 { 27 name: "10-points", 28 repeat: 10, 29 }, 30 31 { 32 name: "1000-points", 33 repeat: 1000, 34 }, 35 } 36 37 for _, tc := range cases { 38 b.Run(tc.name+"_pb-marshal", func(b *testing.B) { 39 pbpts := RandPBPoints(tc.repeat) 40 41 for i := 0; i < b.N; i++ { 42 if _, err := proto.Marshal(pbpts); err != nil { 43 b.Error(err) 44 } 45 } 46 }) 47 48 b.Run(tc.name+"_lp-marshal", func(b *testing.B) { 49 pts := RandPoints(tc.repeat) 50 for i := 0; i < b.N; i++ { 51 arr := []string{} 52 for i := 0; i < len(pts); i++ { 53 arr = append(arr, pts[i].LineProto()) 54 } 55 x := strings.Join(arr, "\n") 56 _ = x 57 } 58 }) 59 60 b.Logf("----------------------------------------------") 61 62 b.Run(tc.name+"_pb-unmarshal", func(b *testing.B) { 63 pbpts := RandPBPoints(tc.repeat) 64 65 pb, err := proto.Marshal(pbpts) 66 assert.NoError(b, err) 67 68 for i := 0; i < b.N; i++ { 69 var pt PBPoints 70 if err := proto.Unmarshal(pb, &pt); err != nil { 71 b.Error(err) 72 } 73 } 74 }) 75 76 b.Run(tc.name+"_lp-unmarshal", func(b *testing.B) { 77 pts := RandPoints(tc.repeat) 78 arr := []string{} 79 for i := 0; i < len(pts); i++ { 80 arr = append(arr, pts[i].LineProto()) 81 } 82 ptbytes := []byte(strings.Join(arr, "\n")) 83 84 for i := 0; i < b.N; i++ { 85 if _, err := parseLPPoints(ptbytes, nil); err != nil { 86 b.Error(err) 87 } 88 } 89 }) 90 } 91 } 92 93 func TestPBPointJSON(t *testing.T) { 94 cases := []struct { 95 name string 96 tags map[string]string 97 fields map[string]interface{} 98 time time.Time 99 warns []*Warn 100 debugs []*Debug 101 }{ 102 { 103 name: "simple", 104 tags: nil, 105 fields: map[string]interface{}{ 106 "f1": int64(123), 107 "f2": 123.4, 108 "f3": false, 109 "f4": "abc", 110 "f5": []byte("xyz"), 111 "f6": uint64(1234567890), 112 }, 113 time: time.Unix(0, 123), 114 }, 115 116 { 117 name: "simple-2", 118 tags: map[string]string{ 119 "t1": "123", 120 "t2": "xyz", 121 }, 122 fields: map[string]interface{}{ 123 "f1": int64(123), 124 "f2": 123.4, 125 "f3": false, 126 "f4": "abc", 127 "f5": []byte("xyz"), 128 "f6": uint64(1234567890), 129 }, 130 time: time.Unix(0, 123), 131 }, 132 133 { 134 name: "with-warnings", 135 tags: map[string]string{ 136 "t1": "123", 137 }, 138 fields: map[string]interface{}{ 139 "t1": "dulicated key in tags", // triger warnning 140 "f1": int64(123), 141 }, 142 time: time.Unix(0, 123), 143 }, 144 145 { 146 name: "with-debugs", 147 tags: map[string]string{ 148 "t1": "123", 149 }, 150 fields: map[string]interface{}{ 151 "t1": "dulicated key in tags", 152 "f1": int64(123), 153 }, 154 time: time.Unix(0, 123), 155 debugs: []*Debug{{Info: "some debug info"}}, 156 }, 157 } 158 159 for _, tc := range cases { 160 t.Run(tc.name, func(t *testing.T) { 161 pt, err := NewPoint(tc.name, tc.tags, tc.fields, WithEncoding(Protobuf), WithTime(tc.time), WithKeySorted(true)) 162 163 assert.NoError(t, err) 164 165 for _, d := range tc.debugs { 166 pt.AddDebug(d) 167 } 168 169 // json 170 pbjson, err := json.Marshal(pt) 171 assert.NoError(t, err) 172 173 // test if debug/warns included in json 174 if len(pt.pt.Debugs) > 0 { 175 assert.Contains(t, string(pbjson), "debugs", "%s not include `debugs'", string(pbjson)) 176 } 177 178 if len(pt.pt.Warns) > 0 { 179 assert.Contains(t, string(pbjson), "warns", "%s not include `warns'", string(pbjson)) 180 } 181 182 // unmarshal 183 var unmarshalPt Point 184 assert.NoError(t, json.Unmarshal(pbjson, &unmarshalPt)) 185 186 // json unmarshaled point should equal to origin point 187 assert.True(t, pt.Equal(&unmarshalPt)) 188 189 // encode to pb 190 enc := GetEncoder(WithEncEncoding(Protobuf)) 191 defer PutEncoder(enc) 192 193 batches, err := enc.Encode([]*Point{&unmarshalPt}) 194 assert.NoError(t, err) 195 assert.Equal(t, 1, len(batches)) 196 197 // decode the pb 198 // test equality: decoded pb point equal(json format) the point before encode 199 dec := GetDecoder(WithDecEncoding(Protobuf)) 200 201 pts, err := dec.Decode(batches[0]) 202 assert.NoError(t, err) 203 assert.Equal(t, 1, len(pts)) 204 205 // test equality on origin json 206 assert.Equal(t, string(pbjson), 207 func() string { 208 j, err := json.Marshal(pts[0]) 209 assert.NoError(t, err) 210 return string(j) 211 }()) 212 213 t.Logf("pb json after:\n%s", pts[0].Pretty()) 214 215 if len(pt.pt.Warns) > 0 { 216 assert.Contains(t, string(pbjson), "warns") 217 } 218 219 if len(tc.debugs) > 0 { 220 assert.Contains(t, string(pbjson), "debugs") 221 } 222 }) 223 } 224 } 225 226 func TestPBPointPayload(t *testing.T) { 227 cases := []struct { 228 name string 229 repeat int 230 }{ 231 { 232 name: "100-point", 233 repeat: 100, 234 }, 235 236 { 237 name: "1000-point", 238 repeat: 1000, 239 }, 240 241 { 242 name: "10000-point", 243 repeat: 10000, 244 }, 245 } 246 247 for _, tc := range cases { 248 t.Run(tc.name, func(t *testing.T) { 249 lppts := RandPoints(tc.repeat) 250 pbpts := RandPBPoints(tc.repeat) 251 252 pb, err := proto.Marshal(pbpts) 253 assert.NoError(t, err) 254 t.Logf("pb len: %d", len(pb)) 255 256 ratio, size := func() (float64, int) { 257 x, err := cliutils.GZip(pb) 258 assert.NoError(t, err) 259 return float64(len(x)) / float64(len(pb)), len(x) 260 }() 261 t.Logf("pb gz ratio: %f/%d", ratio, size) 262 263 // line-protocol 264 ptStrArr := []string{} 265 for i := 0; i < tc.repeat; i++ { 266 str := lppts[i].LineProto() 267 268 ptStrArr = append(ptStrArr, str) 269 } 270 271 ptstr := strings.Join(ptStrArr, "\n") 272 ratio, size = func() (float64, int) { 273 x, err := cliutils.GZipStr(ptstr) 274 assert.NoError(t, err) 275 return float64(len(x)) / float64(len(ptstr)), len(x) 276 }() 277 t.Logf("lp len: %d", len(ptstr)) 278 t.Logf("lp gz ratio: %f/%d", ratio, size) 279 }) 280 } 281 }