github.com/GuanceCloud/cliutils@v1.1.21/point/json_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 "fmt" 11 "testing" 12 T "testing" 13 "time" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestJSONPointMarshal(t *T.T) { 20 cases := []struct { 21 name string 22 p *Point 23 opts []Option 24 expect string 25 }{ 26 { 27 name: "basic", 28 opts: []Option{WithTime(time.Unix(0, 123))}, 29 p: func() *Point { 30 pt, err := NewPoint("abc", 31 map[string]string{"t1": "tv1", "t2": "tv2"}, 32 map[string]interface{}{"f1": 123, "f2": false}, 33 WithTime(time.Unix(0, 123))) 34 assert.NoError(t, err) 35 36 pt.SetFlag(Ppb) // setup pb 37 38 return pt 39 }(), 40 41 expect: fmt.Sprintf(`{ 42 "name":"%s", 43 "fields":[ 44 {"key":"%s","is_tag": true, "s":"%s"}, 45 {"key":"%s","is_tag": true, "s":"%s"}, 46 {"key":"%s","i":"123"}, 47 {"key":"%s","b":false} 48 ], 49 "time":"123" 50 }`, 51 `abc`, 52 `t2`, 53 `tv2`, 54 `t1`, 55 `tv1`, 56 `f1`, 57 `f2`), 58 }, 59 } 60 61 for _, tc := range cases { 62 t.Run(tc.name, func(t *T.T) { 63 j, err := json.Marshal(tc.p) 64 assert.NoError(t, err, "marshal %s to json failed: %s, json: %v", tc.p.Pretty(), err, j) 65 66 t.Logf("json: %s", string(j)) 67 68 var pt Point 69 require.NoError(t, json.Unmarshal(j, &pt), "unmarshal %s failed", string(j)) 70 71 var pt2 Point 72 require.NoError(t, json.Unmarshal([]byte(tc.expect), &pt2)) 73 74 require.True(t, pt2.Equal(&pt), "deep-not-equal:\n%s\n%s", pt.Pretty(), pt2.Pretty()) 75 76 t.Logf("pt: %+#v, pt.pbPoint: %s", pt2, pt.Pretty()) 77 }) 78 } 79 } 80 81 func TestJSONUnmarshal(t *T.T) { 82 t.Run(`unmarshal-point-array`, func(t *T.T) { 83 j := `[ 84 {"name":"abc","fields":[{"key":"f1","i":"123"},{"key":"f2","b":false},{"key":"t1","s":"tv1","is_tag":true},{"key":"t2","s":"tv2","is_tag":true}],"time":"123"} 85 ]` 86 pts := make([]*Point, 0) 87 require.NoError(t, json.Unmarshal([]byte(j), &pts)) 88 t.Logf("pt: %s", pts[0].Pretty()) 89 }) 90 } 91 92 func TestJSONPointMarhsal(t *testing.T) { 93 var kvs KVs 94 95 EnableMixedArrayField = true 96 defer func() { 97 EnableMixedArrayField = false 98 }() 99 100 kvs = kvs.AddV2("f1", 123, false) 101 kvs = kvs.AddV2("f2", uint(123), false) 102 kvs = kvs.AddV2("f3", "hello", false) 103 kvs = kvs.AddV2("f4", []byte("world"), false) 104 kvs = kvs.AddV2("f5", false, false) 105 kvs = kvs.AddV2("f6", 3.14, false, WithKVUnit("kb"), WithKVType(GAUGE)) 106 kvs = kvs.AddV2("f7", []int{1, 2, 3, 4, 5}, false) 107 kvs = kvs.AddV2("f8", MustNewAnyArray(1.0, 2, uint(3), "hello", []byte("world"), false, 3.14), false) 108 109 kvs = kvs.AddV2("t1", "some-tag-value", false, WithKVTagSet(true)) 110 111 pt := NewPointV2("json-point", kvs) 112 113 j, err := json.MarshalIndent(pt, "", " ") 114 assert.NoError(t, err) 115 116 t.Logf("old json:\n%s", string(j)) 117 118 pt.SetFlag(Ppb) 119 120 j, err = json.MarshalIndent(pt, "", " ") 121 assert.NoError(t, err) 122 123 t.Logf("new json:\n%s", string(j)) 124 125 t.Logf("line-protocol:\n%s", pt.LineProto()) 126 } 127 128 func TestJSONPoint2Point(t *T.T) { 129 cases := []struct { 130 name string 131 p *JSONPoint 132 opts []Option 133 expect string 134 fail bool 135 }{ 136 { 137 name: "basic", 138 p: &JSONPoint{ 139 Measurement: "abc", 140 Tags: nil, 141 Fields: map[string]interface{}{"f1": 123, "f2": false}, 142 }, 143 opts: []Option{WithTime(time.Unix(0, 123))}, 144 expect: "abc f1=123i,f2=false 123", 145 }, 146 147 { 148 name: "no-fields", 149 p: &JSONPoint{ 150 Measurement: "abc", 151 Fields: nil, 152 }, 153 fail: true, 154 opts: []Option{WithTime(time.Unix(0, 123))}, 155 }, 156 157 { 158 name: "no-measurement", 159 p: &JSONPoint{ 160 Measurement: "", // not set 161 Tags: nil, 162 Fields: map[string]interface{}{"f1": 123, "f2": false}, 163 }, 164 opts: []Option{WithTime(time.Unix(0, 123))}, 165 expect: fmt.Sprintf("%s f1=123i,f2=false 123", DefaultMeasurementName), 166 }, 167 } 168 169 for _, tc := range cases { 170 t.Run(tc.name, func(t *T.T) { 171 pt, err := tc.p.Point(tc.opts...) 172 if tc.fail { 173 assert.Error(t, err) 174 t.Logf("expect err: %s", err) 175 return 176 } else { 177 assert.NoError(t, err) 178 } 179 180 assert.Equal(t, tc.expect, pt.LineProto()) 181 }) 182 } 183 184 t.Run("array-field", func(t *T.T) { 185 jp := JSONPoint{ 186 Measurement: "some", 187 Fields: map[string]any{ 188 "f_i_arr": []int{1, 2, 3}, 189 "f_d_arr": [][]byte{[]byte("hello"), []byte("world")}, 190 }, 191 } 192 193 pt := fromJSONPoint(&jp) 194 195 t.Logf("pt: %s", pt.Pretty()) 196 197 EnableMixedArrayField = true 198 defer func() { 199 EnableMixedArrayField = false 200 }() 201 202 j := `{ 203 "measurement": "some", 204 "fields": { 205 "f_i_arr": [1,2,3], 206 "f_f_arr": [1.0,2.0,3.14], 207 "f_mix_arr": [1.0, "string", false, 3] 208 } 209 }` 210 // NOTE: simple json do not support: 211 // - signed/unsigned int 212 // - []byte 213 var jp2 JSONPoint 214 assert.NoError(t, json.Unmarshal([]byte(j), &jp2)) 215 216 t.Logf("jp2 fields: %+#v", jp2.Fields) 217 218 pt, err := jp2.Point() 219 assert.NoError(t, err) 220 assert.NotNilf(t, pt.Get("f_i_arr"), "pt: %s", pt.Pretty()) 221 assert.NotNilf(t, pt.Get("f_f_arr"), "pt: %s", pt.Pretty()) 222 assert.NotNilf(t, pt.Get("f_mix_arr"), "pt: %s", pt.Pretty()) 223 224 t.Logf("pt: %s", pt.Pretty()) 225 }) 226 } 227 228 func TestFromJSONPoint(t *T.T) { 229 t.Run(`basic`, func(t *T.T) { 230 jp := JSONPoint{ 231 Measurement: "m", 232 Tags: map[string]string{ 233 "t1": "v1", 234 "t2": "v2", 235 }, 236 Fields: map[string]any{ 237 "f1": 1, 238 "f2": 3.14, 239 }, 240 Time: 123, 241 } 242 243 pt := fromJSONPoint(&jp) 244 assert.Equal(t, "m", pt.Name()) 245 assert.Equal(t, "v1", pt.Get("t1")) 246 assert.Equal(t, "v2", pt.Get("t2")) 247 assert.Equal(t, int64(1), pt.Get("f1")) 248 assert.Equal(t, 3.14, pt.Get("f2")) 249 assert.Equal(t, int64(123), pt.Time().UnixNano()) 250 }) 251 252 t.Run(`from-raw-json`, func(t *T.T) { 253 j := ` 254 { 255 "measurement": "m", 256 "tags": { 257 "t1": "v1", 258 "t2": "v2" 259 }, 260 "fields": { 261 "f1": 1, 262 "f2": 3.14 263 }, 264 265 "time": 123 266 } 267 ` 268 269 var pt Point 270 assert.NoError(t, json.Unmarshal([]byte(j), &pt)) 271 272 assert.Equal(t, "m", pt.Name()) 273 assert.Equal(t, "v1", pt.Get("t1")) 274 assert.Equal(t, "v2", pt.Get("t2")) 275 assert.Equal(t, 1.0, pt.Get("f1")) // NOTE: here 1 in json unmarshaled as float 276 assert.Equal(t, 3.14, pt.Get("f2")) 277 assert.Equal(t, int64(123), pt.Time().UnixNano()) 278 }) 279 }