github.com/opentelekomcloud/gophertelekomcloud@v0.9.3/internal/extract/json_test.go (about) 1 package extract 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "math/rand" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 // randomString duplicates here to avoid cyclic imports 15 // TODO: this function should be moved to some other package later 16 func randomString(prefix string, n int) string { 17 const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 18 var bytes = make([]byte, n) 19 _, _ = rand.Read(bytes) 20 for i, b := range bytes { 21 bytes[i] = alphanum[b%byte(len(alphanum))] 22 } 23 return prefix + string(bytes) 24 } 25 26 type localCloser struct { 27 *bytes.Reader 28 29 closed bool 30 } 31 32 func (lc *localCloser) Close() error { 33 lc.closed = true 34 return nil 35 } 36 37 func TestInto(t *testing.T) { 38 key := "data_key" 39 value := randomString("v-", 20) 40 41 expected := map[string]string{key: value} 42 43 t.Run("io.Reader", func(t *testing.T) { 44 t.Parallel() 45 46 data := bytes.NewReader([]byte(fmt.Sprintf(`{ "data_key": "%s"}`, value))) 47 48 actual := make(map[string]string) 49 err := Into(data, &actual) 50 51 assert.NoError(t, err) // not exiting after one fail 52 assert.EqualValues(t, expected[key], actual[key]) 53 }) 54 55 t.Run("io.ReadCloser", func(t *testing.T) { 56 t.Parallel() 57 58 data := bytes.NewReader([]byte(fmt.Sprintf(`{ "data_key": "%s"}`, value))) 59 closer := &localCloser{Reader: data} 60 61 actual := make(map[string]string) 62 err := Into(closer, &actual) 63 64 assert.NoError(t, err) // not exiting after one fail 65 assert.EqualValues(t, expected[key], actual[key]) 66 assert.True(t, closer.closed) 67 }) 68 } 69 70 type TestDataType struct { 71 DataKey string `json:"data_key"` 72 } 73 74 type TestDataType2 struct { 75 TestDataType 76 77 SecondDataField string `json:"second_data_field"` 78 } 79 80 func readerFromString(src string) io.Reader { 81 return bytes.NewReader([]byte(src)) 82 } 83 84 func TestIntoStructPtr(t *testing.T) { 85 t.Run("ok", func(t *testing.T) { 86 t.Parallel() 87 88 actual := new(TestDataType) 89 value := randomString("v-", 20) 90 91 data := fmt.Sprintf(` 92 { 93 "data_key": "%s" 94 } 95 `, value) 96 97 err := IntoStructPtr(readerFromString(data), actual, "") 98 require.NoError(t, err) 99 require.Equal(t, value, actual.DataKey) 100 }) 101 102 t.Run("with label", func(t *testing.T) { 103 t.Parallel() 104 105 actual := new(TestDataType) 106 value := randomString("v-", 20) 107 108 data := fmt.Sprintf(` 109 { 110 "internal": { 111 "data_key": "%s" 112 } 113 } 114 `, value) 115 116 err := IntoStructPtr(readerFromString(data), actual, "internal") 117 require.NoError(t, err) 118 require.Equal(t, value, actual.DataKey) 119 }) 120 121 t.Run("with label and embed", func(t *testing.T) { 122 t.Parallel() 123 124 actual := new(TestDataType2) 125 value := randomString("v-", 20) 126 127 data := fmt.Sprintf(` 128 { 129 "internal": { 130 "data_key": "%s", 131 "second_data_field": "%[1]s-2" 132 } 133 } 134 `, value) 135 136 err := IntoStructPtr(readerFromString(data), actual, "internal") 137 require.NoError(t, err) 138 require.Equal(t, value, actual.DataKey) 139 require.Equal(t, value+"-2", actual.SecondDataField) 140 }) 141 142 t.Run("with label (err)", func(t *testing.T) { 143 t.Parallel() 144 145 actual := new(TestDataType) 146 value := randomString("v-", 20) 147 148 data := fmt.Sprintf(` 149 { 150 "internal": { 151 "data_key": "%s" 152 } 153 } 154 `, value) 155 156 err := IntoStructPtr(readerFromString(data), actual, "") 157 require.NoError(t, err) 158 require.Equal(t, "", actual.DataKey) 159 }) 160 161 t.Run("non pointer", func(t *testing.T) { 162 t.Parallel() 163 164 actual := TestDataType{} 165 value := randomString("v-", 20) 166 167 data := fmt.Sprintf(` 168 { 169 "data_key": "%s" 170 } 171 `, value) 172 173 err := IntoStructPtr(readerFromString(data), actual, "") 174 require.EqualError(t, err, "expected pointer, got struct") 175 }) 176 177 t.Run("non struct", func(t *testing.T) { 178 t.Parallel() 179 180 actual := make(map[string]interface{}) 181 value := randomString("v-", 20) 182 183 data := fmt.Sprintf(` 184 { 185 "data_key": "%s" 186 } 187 `, value) 188 189 err := IntoStructPtr(readerFromString(data), &actual, "") 190 require.EqualError(t, err, "expected pointer to struct, got: *map[string]interface {}") 191 }) 192 } 193 194 func TestIntoSlicePtr(t *testing.T) { 195 t.Run("ok", func(t *testing.T) { 196 t.Parallel() 197 198 actual := make([]TestDataType, 0) 199 value := randomString("v-", 20) 200 201 data := fmt.Sprintf(` 202 [{ 203 "data_key": "%s" 204 }] 205 `, value) 206 207 err := IntoSlicePtr(readerFromString(data), &actual, "") 208 require.NoError(t, err) 209 require.Len(t, actual, 1) 210 require.Equal(t, value, actual[0].DataKey) 211 }) 212 213 t.Run("with label", func(t *testing.T) { 214 t.Parallel() 215 216 actual := make([]TestDataType, 0) 217 value := randomString("v-", 20) 218 219 data := fmt.Sprintf(` 220 { 221 "data": [{ "data_key": "%s" }] 222 } 223 `, value) 224 225 err := IntoSlicePtr(readerFromString(data), &actual, "data") 226 require.NoError(t, err) 227 require.Len(t, actual, 1) 228 require.Equal(t, value, actual[0].DataKey) 229 }) 230 231 t.Run("with label and embed", func(t *testing.T) { 232 t.Parallel() 233 234 actual := make([]TestDataType2, 0) 235 value := randomString("v-", 20) 236 237 data := fmt.Sprintf(` 238 { 239 "internal": [{ 240 "data_key": "%s", 241 "second_data_field": "%[1]s" 242 }] 243 } 244 `, value) 245 246 err := IntoSlicePtr(readerFromString(data), &actual, "internal") 247 require.NoError(t, err) 248 require.Len(t, actual, 1) 249 require.Equal(t, value, actual[0].DataKey) 250 require.Equal(t, value, actual[0].SecondDataField) 251 }) 252 253 t.Run("not pointer", func(t *testing.T) { 254 t.Parallel() 255 256 actual := make([]TestDataType, 0) 257 value := randomString("v-", 20) 258 259 data := fmt.Sprintf(` 260 [{ 261 "data_key": "%s" 262 }] 263 `, value) 264 265 err := IntoSlicePtr(readerFromString(data), actual, "") 266 require.EqualError(t, err, "expected pointer, got slice") 267 }) 268 269 t.Run("not slice", func(t *testing.T) { 270 t.Parallel() 271 272 actual := new(TestDataType) 273 value := randomString("v-", 20) 274 275 data := fmt.Sprintf(` 276 { 277 "data_key": "%s" 278 } 279 `, value) 280 281 err := IntoSlicePtr(readerFromString(data), actual, "") 282 require.EqualError(t, err, "expected pointer to slice, got: *extract.TestDataType") 283 }) 284 }