github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/cmn/tests/iter_fields_test.go (about) 1 // Package test provides tests for common low-level types and utilities for all aistore projects 2 /* 3 * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package tests_test 6 7 import ( 8 "github.com/NVIDIA/aistore/api/apc" 9 "github.com/NVIDIA/aistore/cmn" 10 "github.com/NVIDIA/aistore/cmn/cos" 11 "github.com/NVIDIA/aistore/cmn/feat" 12 . "github.com/onsi/ginkgo/v2" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("IterFields", func() { 17 type ( 18 Foo struct { 19 A int `list:"omit"` 20 B int `json:"b"` 21 } 22 bar struct { 23 Foo Foo `json:"foo"` 24 C string `json:"c"` 25 } 26 barInline struct { 27 Foo `json:",inline"` 28 C string `json:"c"` 29 } 30 ) 31 32 Describe("IterFields", func() { 33 DescribeTable("should successfully iterate fields in structs", 34 func(v any, expected map[string]any) { 35 got := make(map[string]any) 36 err := cmn.IterFields(v, func(tag string, field cmn.IterField) (error, bool) { 37 got[tag] = field.Value() 38 return nil, false 39 }) 40 Expect(err).NotTo(HaveOccurred()) 41 Expect(got).To(Equal(expected)) 42 }, 43 Entry("list BucketProps fields", 44 cmn.Bprops{ 45 Provider: apc.AIS, 46 BackendBck: cmn.Bck{ 47 Name: "name", 48 Provider: apc.GCP, 49 }, 50 EC: cmn.ECConf{ 51 Enabled: true, 52 ParitySlices: 1024, 53 }, 54 LRU: cmn.LRUConf{}, 55 Cksum: cmn.CksumConf{ 56 Type: cos.ChecksumXXHash, 57 }, 58 Extra: cmn.ExtraProps{ 59 AWS: cmn.ExtraPropsAWS{CloudRegion: "us-central"}, 60 }, 61 }, 62 map[string]any{ 63 "provider": apc.AIS, 64 65 "backend_bck.name": "name", 66 "backend_bck.provider": apc.GCP, 67 68 "mirror.enabled": false, 69 "mirror.copies": int64(0), 70 "mirror.burst_buffer": 0, 71 72 "ec.enabled": true, 73 "ec.parity_slices": 1024, 74 "ec.data_slices": 0, 75 "ec.objsize_limit": int64(0), 76 "ec.compression": "", 77 "ec.bundle_multiplier": 0, 78 "ec.disk_only": false, 79 80 "versioning.enabled": false, 81 "versioning.validate_warm_get": false, 82 "versioning.synchronize": false, 83 84 "checksum.type": cos.ChecksumXXHash, 85 "checksum.validate_warm_get": false, 86 "checksum.validate_cold_get": false, 87 "checksum.validate_obj_move": false, 88 "checksum.enable_read_range": false, 89 90 "lru.enabled": false, 91 "lru.dont_evict_time": cos.Duration(0), 92 "lru.capacity_upd_time": cos.Duration(0), 93 94 "extra.aws.cloud_region": "us-central", 95 "extra.aws.endpoint": "", 96 "extra.aws.profile": "", 97 "extra.aws.max_pagesize": int64(0), 98 99 "access": apc.AccessAttrs(0), 100 "features": feat.Flags(0), 101 "created": int64(0), 102 103 "write_policy.data": apc.WritePolicy(""), 104 "write_policy.md": apc.WritePolicy(""), 105 }, 106 ), 107 Entry("list BpropsToSet fields", 108 &cmn.BpropsToSet{ 109 EC: &cmn.ECConfToSet{ 110 Enabled: apc.Ptr(true), 111 ParitySlices: apc.Ptr(1024), 112 }, 113 LRU: &cmn.LRUConfToSet{}, 114 Cksum: &cmn.CksumConfToSet{ 115 Type: apc.Ptr(cos.ChecksumXXHash), 116 }, 117 Access: apc.Ptr[apc.AccessAttrs](1024), 118 Features: apc.Ptr[feat.Flags](1024), 119 WritePolicy: &cmn.WritePolicyConfToSet{ 120 MD: apc.Ptr(apc.WriteDelayed), 121 }, 122 }, 123 map[string]any{ 124 "backend_bck.name": (*string)(nil), 125 "backend_bck.provider": (*string)(nil), 126 127 "mirror.enabled": (*bool)(nil), 128 "mirror.copies": (*int64)(nil), 129 "mirror.burst_buffer": (*int)(nil), 130 131 "ec.enabled": apc.Ptr(true), 132 "ec.parity_slices": apc.Ptr(1024), 133 "ec.data_slices": (*int)(nil), 134 "ec.objsize_limit": (*int64)(nil), 135 "ec.compression": (*string)(nil), 136 "ec.bundle_multiplier": (*int)(nil), 137 "ec.disk_only": (*bool)(nil), 138 139 "versioning.enabled": (*bool)(nil), 140 "versioning.validate_warm_get": (*bool)(nil), 141 "versioning.synchronize": (*bool)(nil), 142 143 "checksum.type": apc.Ptr(cos.ChecksumXXHash), 144 "checksum.validate_warm_get": (*bool)(nil), 145 "checksum.validate_cold_get": (*bool)(nil), 146 "checksum.validate_obj_move": (*bool)(nil), 147 "checksum.enable_read_range": (*bool)(nil), 148 149 "lru.enabled": (*bool)(nil), 150 "lru.dont_evict_time": (*cos.Duration)(nil), 151 "lru.capacity_upd_time": (*cos.Duration)(nil), 152 153 "access": apc.Ptr[apc.AccessAttrs](1024), 154 "features": apc.Ptr[feat.Flags](1024), 155 156 "write_policy.data": (*apc.WritePolicy)(nil), 157 "write_policy.md": apc.Ptr(apc.WriteDelayed), 158 159 "extra.hdfs.ref_directory": (*string)(nil), 160 "extra.aws.cloud_region": (*string)(nil), 161 "extra.aws.endpoint": (*string)(nil), 162 "extra.aws.profile": (*string)(nil), 163 "extra.aws.max_pagesize": (*int64)(nil), 164 "extra.http.original_url": (*string)(nil), 165 }, 166 ), 167 Entry("check for omit tag", 168 Foo{A: 1, B: 2}, 169 map[string]any{ 170 "b": 2, 171 }, 172 ), 173 ) 174 175 It("list all the fields (not only leafs)", func() { 176 v := bar{Foo: Foo{A: 3, B: 10}, C: "string"} 177 expected := map[string]any{ 178 "foo.b": 10, 179 "foo": Foo{A: 3, B: 10}, 180 "c": "string", 181 } 182 183 got := make(map[string]any) 184 err := cmn.IterFields(v, func(tag string, field cmn.IterField) (error, bool) { 185 got[tag] = field.Value() 186 return nil, false 187 }, cmn.IterOpts{VisitAll: true}) 188 Expect(err).NotTo(HaveOccurred()) 189 Expect(got).To(Equal(expected)) 190 }) 191 192 It("list inline fields", func() { 193 v := barInline{Foo: Foo{A: 3, B: 10}, C: "string"} 194 expected := map[string]any{ 195 "b": 10, 196 "": Foo{A: 3, B: 10}, 197 "c": "string", 198 } 199 200 got := make(map[string]any) 201 err := cmn.IterFields(v, func(tag string, field cmn.IterField) (error, bool) { 202 got[tag] = field.Value() 203 return nil, false 204 }, cmn.IterOpts{VisitAll: true}) 205 Expect(err).NotTo(HaveOccurred()) 206 Expect(got).To(Equal(expected)) 207 }) 208 }) 209 210 Describe("UpdateFieldValue", func() { 211 DescribeTable("should successfully update the fields in struct", 212 func(v any, values map[string]any, expected any) { 213 for name, value := range values { 214 err := cmn.UpdateFieldValue(v, name, value) 215 Expect(err).NotTo(HaveOccurred()) 216 } 217 Expect(v).To(Equal(expected)) 218 }, 219 Entry("update some BucketProps", 220 &cmn.Bprops{ 221 Versioning: cmn.VersionConf{ 222 ValidateWarmGet: true, 223 }, 224 }, 225 map[string]any{ 226 "mirror.enabled": "true", // type == bool 227 "mirror.copies": "120", // type == int 228 "mirror.burst_buffer": "9560", // type == int64 229 230 "ec.enabled": true, 231 "ec.parity_slices": 1024, 232 "ec.objsize_limit": int64(0), 233 "ec.compression": "", 234 235 "versioning.enabled": false, 236 237 "checksum.type": cos.ChecksumXXHash, 238 239 "access": "12", // type == uint64 240 "write_policy.md": apc.WriteNever, 241 }, 242 &cmn.Bprops{ 243 Mirror: cmn.MirrorConf{ 244 Enabled: true, 245 Copies: 120, 246 Burst: 9560, 247 }, 248 EC: cmn.ECConf{ 249 Enabled: true, 250 ParitySlices: 1024, 251 }, 252 LRU: cmn.LRUConf{}, 253 Cksum: cmn.CksumConf{ 254 Type: cos.ChecksumXXHash, 255 }, 256 Versioning: cmn.VersionConf{ 257 Enabled: false, 258 ValidateWarmGet: true, 259 }, 260 Access: 12, 261 WritePolicy: cmn.WritePolicyConf{MD: apc.WriteNever}, 262 }, 263 ), 264 Entry("update some BpropsToSet", 265 &cmn.BpropsToSet{ 266 Cksum: &cmn.CksumConfToSet{ 267 ValidateWarmGet: apc.Ptr(true), 268 }, 269 }, 270 map[string]any{ 271 "mirror.enabled": "true", // type == bool 272 "mirror.copies": "120", // type == int 273 "mirror.burst_buffer": "9560", // type == int64 274 275 "ec.enabled": true, 276 "ec.parity_slices": 1024, 277 "ec.objsize_limit": int64(0), 278 "ec.compression": "", 279 280 "versioning.enabled": false, 281 282 "checksum.type": cos.ChecksumXXHash, 283 284 "access": "12", // type == uint64 285 "write_policy.md": apc.WriteNever, 286 }, 287 &cmn.BpropsToSet{ 288 Versioning: &cmn.VersionConfToSet{ 289 Enabled: apc.Ptr(false), 290 }, 291 Mirror: &cmn.MirrorConfToSet{ 292 Enabled: apc.Ptr(true), 293 Copies: apc.Ptr[int64](120), 294 Burst: apc.Ptr(9560), 295 }, 296 EC: &cmn.ECConfToSet{ 297 Enabled: apc.Ptr(true), 298 ParitySlices: apc.Ptr(1024), 299 ObjSizeLimit: apc.Ptr[int64](0), 300 Compression: apc.Ptr(""), 301 }, 302 Cksum: &cmn.CksumConfToSet{ 303 Type: apc.Ptr(cos.ChecksumXXHash), 304 ValidateWarmGet: apc.Ptr(true), 305 }, 306 Access: apc.Ptr[apc.AccessAttrs](12), 307 WritePolicy: &cmn.WritePolicyConfToSet{ 308 MD: apc.Ptr(apc.WriteNever), 309 }, 310 }, 311 ), 312 ) 313 314 DescribeTable("should error on update", 315 func(v any, values map[string]any) { 316 for name, value := range values { 317 err := cmn.UpdateFieldValue(v, name, value) 318 Expect(err).To(HaveOccurred()) 319 } 320 }, 321 Entry("non-pointer struct", cmn.Bprops{}, map[string]any{ 322 "mirror.enabled": true, 323 }), 324 Entry("readonly field", &cmn.Bprops{}, map[string]any{ 325 "provider": apc.AIS, 326 }), 327 Entry("field not found", &Foo{}, map[string]any{ 328 "foo.bar": 2, 329 }), 330 ) 331 332 DescribeTable("should error on update", 333 func(orig *cmn.ConfigToSet, merge *cmn.ConfigToSet, expected *cmn.ConfigToSet) { 334 orig.Merge(merge) 335 Expect(orig).To(Equal(expected)) 336 }, 337 Entry("override configuration", &cmn.ConfigToSet{ 338 Mirror: &cmn.MirrorConfToSet{ 339 Enabled: apc.Ptr(true), 340 Copies: apc.Ptr[int64](2), 341 }, 342 }, &cmn.ConfigToSet{ 343 Mirror: &cmn.MirrorConfToSet{ 344 Enabled: apc.Ptr(false), 345 }, 346 }, &cmn.ConfigToSet{ 347 Mirror: &cmn.MirrorConfToSet{ 348 Enabled: apc.Ptr(false), 349 Copies: apc.Ptr[int64](2), 350 }, 351 }), 352 353 Entry("add new fields", &cmn.ConfigToSet{ 354 Mirror: &cmn.MirrorConfToSet{ 355 Enabled: apc.Ptr(true), 356 Copies: apc.Ptr[int64](2), 357 }, 358 }, &cmn.ConfigToSet{ 359 Mirror: &cmn.MirrorConfToSet{ 360 Enabled: apc.Ptr(false), 361 }, 362 EC: &cmn.ECConfToSet{ 363 Enabled: apc.Ptr(true), 364 }, 365 }, &cmn.ConfigToSet{ 366 Mirror: &cmn.MirrorConfToSet{ 367 Enabled: apc.Ptr(false), 368 Copies: apc.Ptr[int64](2), 369 }, 370 EC: &cmn.ECConfToSet{ 371 Enabled: apc.Ptr(true), 372 }, 373 }), 374 375 Entry("nested fields", &cmn.ConfigToSet{ 376 Net: &cmn.NetConfToSet{ 377 HTTP: &cmn.HTTPConfToSet{ 378 Certificate: apc.Ptr("secret"), 379 }, 380 }, 381 }, &cmn.ConfigToSet{ 382 Net: &cmn.NetConfToSet{ 383 HTTP: &cmn.HTTPConfToSet{ 384 UseHTTPS: apc.Ptr(true), 385 }, 386 }, 387 }, &cmn.ConfigToSet{ 388 Net: &cmn.NetConfToSet{ 389 HTTP: &cmn.HTTPConfToSet{ 390 Certificate: apc.Ptr("secret"), 391 UseHTTPS: apc.Ptr(true), 392 }, 393 }, 394 }), 395 ) 396 }) 397 })