kubelatte-ce

Форк
2
Форк от sbertech/kubelatte-ce
/
funcs_test.go 
882 строки · 19.9 Кб
1
package templates
2

3
import (
4
	"context"
5
	"github.com/gohobby/deepcopy"
6
	"github.com/stretchr/testify/assert"
7
	"github.com/stretchr/testify/require"
8
	"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
9
	"gitverse.ru/synapse/kubelatte/pkg/observability/logger/lib"
10
	"go.uber.org/zap"
11
	"reflect"
12
	"testing"
13
	"text/template"
14
)
15

16
func TestFromYAML(t *testing.T) {
17
	tests := []struct {
18
		name    string
19
		yaml    string
20
		want    interface{}
21
		wantErr bool
22
	}{
23
		{
24
			"invalid yaml",
25
			"'",
26
			nil,
27
			true,
28
		},
29
		{
30
			"empty object",
31
			"{}",
32
			map[string]interface{}{},
33
			false,
34
		},
35
		{
36
			"raw string",
37
			"hello world",
38
			"hello world",
39
			false,
40
		},
41
		{
42
			"array of strings",
43
			`["hello", "goodbye"]`,
44
			[]interface{}{"hello", "goodbye"},
45
			false,
46
		},
47
		{
48
			"array of objects",
49
			`["hello", {}]`,
50
			[]interface{}{"hello", map[string]interface{}{}},
51
			false,
52
		},
53
		{
54
			"top-level object",
55
			`age: "23"
56
hello: bar`,
57
			map[string]interface{}{"age": "23", "hello": "bar"},
58
			false,
59
		},
60
	}
61
	for _, tt := range tests {
62
		t.Run(tt.name, func(t *testing.T) {
63
			got, err := FromYAML(tt.yaml)
64
			if tt.wantErr {
65
				require.Error(t, err, "Expected error unmarshalling yaml string")
66
				return
67
			}
68

69
			require.NoError(t, err, "Unexpected error unmarshalling yaml string")
70
			require.Equal(t, tt.want, got)
71
		})
72
	}
73
}
74

75
func TestToYAML(t *testing.T) {
76
	type args struct {
77
		resource interface{}
78
	}
79
	tests := []struct {
80
		name    string
81
		args    args
82
		want    string
83
		wantErr bool
84
	}{
85
		{
86
			name: "ok",
87
			args: args{resource: map[string]interface{}{"bobob": 123, "bubu": map[string]interface{}{"lolo": "pufpuf"}}},
88
			want: `bobob: 123
89
bubu:
90
  lolo: pufpuf
91
`,
92
			wantErr: false,
93
		},
94
		{
95
			name:    "empty",
96
			args:    args{},
97
			want:    "",
98
			wantErr: false,
99
		},
100
	}
101

102
	lib.ZapLogger = zap.NewNop()
103

104
	for _, tt := range tests {
105
		t.Run(tt.name, func(t *testing.T) {
106
			got, err := ToYAML(tt.args.resource)
107
			if (err != nil) != tt.wantErr {
108
				t.Errorf("ToYAML() error = %v, wantErr %v", err, tt.wantErr)
109
				return
110
			}
111
			if got != tt.want {
112
				t.Errorf("ToYAML() got = %v, \nwant %v", []byte(got), []byte(tt.want))
113
			}
114
		})
115
	}
116
}
117

118
func TestNindent(t *testing.T) {
119
	type args struct {
120
		in        string
121
		spacesNum int
122
	}
123
	tests := []struct {
124
		name string
125
		args args
126
		want string
127
	}{
128
		{
129
			name: "simple",
130
			args: args{
131
				in: `some:
132
  yaml:
133
    simple:
134
      string`,
135
				spacesNum: 2,
136
			},
137
			want: `
138
  some:
139
    yaml:
140
      simple:
141
        string
142
`,
143
		},
144
		{
145
			name: "not-so-simple",
146
			args: args{
147
				in: `some:
148
  yaml:
149
    not-so-simple:
150
      - strings
151
      - strings`,
152
				spacesNum: 0,
153
			},
154
			want: `
155
some:
156
  yaml:
157
    not-so-simple:
158
      - strings
159
      - strings
160
`,
161
		},
162
		{
163
			name: "empty",
164
			args: args{
165
				in:        "",
166
				spacesNum: 0,
167
			},
168
			want: "\n\n",
169
		},
170
	}
171
	for _, tt := range tests {
172
		t.Run(tt.name, func(t *testing.T) {
173
			if got := Nindent(tt.args.in, tt.args.spacesNum); got != tt.want {
174
				t.Errorf("Nindent() = %v, want %v", got, tt.want)
175
			}
176
		})
177
	}
178
}
179

180
func TestIndent(t *testing.T) {
181
	type args struct {
182
		in        string
183
		spacesNum int
184
	}
185
	tests := []struct {
186
		name string
187
		args args
188
		want string
189
	}{
190
		{
191
			name: "simple",
192
			args: args{
193
				in: `some:
194
  yaml:
195
    simple:
196
      string`,
197
				spacesNum: 2,
198
			},
199
			want: `some:
200
    yaml:
201
      simple:
202
        string
203
`,
204
		},
205
		{
206
			name: "not-so-simple",
207
			args: args{
208
				in: `some:
209
  yaml:
210
    not-so-simple:
211
      - strings
212
      - strings`,
213
				spacesNum: 0,
214
			},
215
			want: `some:
216
  yaml:
217
    not-so-simple:
218
      - strings
219
      - strings
220
`,
221
		},
222
		{
223
			name: "empty",
224
			args: args{
225
				in:        "",
226
				spacesNum: 0,
227
			},
228
			want: "\n",
229
		},
230
	}
231
	for _, tt := range tests {
232
		t.Run(tt.name, func(t *testing.T) {
233
			if got := Indent(tt.args.in, tt.args.spacesNum); got != tt.want {
234
				t.Errorf("Indent() = \n%v, want \n%v", got, tt.want)
235
			}
236
		})
237
	}
238
}
239

240
func TestLoadTemplate(t *testing.T) {
241
	t.Run("test", func(t *testing.T) {
242
		expected := template.New("common").Delims("{{%", "%}}")
243
		got := LoadTemplate(context.Background(), v1alpha1.Template{})
244
		if got.Name() != expected.Name() {
245
			t.Errorf("LoadTemplate() = %+v, want %+v", got, expected)
246
		}
247
	})
248
}
249

250
func TestConfigPatchesRBACToV3(t *testing.T) { //nolint:funlen
251
	type args struct {
252
		in interface{}
253
	}
254
	tests := []struct {
255
		name    string
256
		args    args
257
		want    interface{}
258
		wantErr bool
259
	}{
260
		{
261
			name: "ok",
262
			args: args{
263
				in: map[string]interface{}{
264
					"match": map[string]interface{}{
265
						"listener": map[string]interface{}{
266
							"filterChain": map[string]interface{}{
267
								"filter": map[string]interface{}{
268
									"name": "envoy.filters.network.rbac"},
269
							},
270
						},
271
					},
272
					"patch": map[string]interface{}{
273
						"value": map[string]interface{}{
274
							"config": map[string]interface{}{
275
								"rules": map[string]interface{}{
276
									"policies": map[string]interface{}{
277
										"validate": map[string]interface{}{
278
											"permissions": map[string]interface{}{
279
												"or_rules": map[string]interface{}{
280
													"rules": []interface{}{map[string]interface{}{
281
														"header": map[string]interface{}{
282
															"name": ":method",
283
														},
284
													}},
285
												},
286
											},
287
											"principals": map[string]interface{}{
288
												"or_ids": map[string]interface{}{
289
													"ids": []interface{}{map[string]interface{}{
290
														"header": map[string]interface{}{
291
															"name": ":x-forwarded-client-cert",
292
														},
293
													},
294
													},
295
												},
296
											},
297
										},
298
									},
299
								},
300
							},
301
						},
302
					},
303
				},
304
			},
305
			want: map[string]interface{}{
306
				"match": map[string]interface{}{
307
					"listener": map[string]interface{}{
308
						"filterChain": map[string]interface{}{
309
							"filter": map[string]interface{}{
310
								"name": "envoy.filters.network.http_connection_manager",
311
							},
312
						},
313
					},
314
				},
315
				"patch": map[string]interface{}{
316
					"value": map[string]interface{}{
317
						"typed_config": map[string]interface{}{
318
							"@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC",
319
							"rules": map[string]interface{}{
320
								"policies": map[string]interface{}{
321
									"validate": map[string]interface{}{
322
										"permissions": []map[string]interface{}{
323
											{"or_rules": map[string]interface{}{
324
												"rules": []interface{}{map[string]interface{}{
325
													"header": map[string]interface{}{
326
														"name": ":method",
327
													},
328
												},
329
												},
330
											},
331
											},
332
										},
333
										"principals": []map[string]interface{}{
334
											{"or_ids": map[string]interface{}{
335
												"ids": []interface{}{map[string]interface{}{
336
													"header": map[string]interface{}{
337
														"name": ":x-forwarded-client-cert",
338
													},
339
												},
340
												},
341
											},
342
											},
343
										},
344
									},
345
								},
346
							},
347
						},
348
					},
349
				},
350
			},
351

352
			wantErr: false,
353
		},
354
		{
355
			name: "!ok",
356
			args: args{
357
				in: map[string]interface{}{
358
					"match": map[string]interface{}{},
359
				},
360
			},
361
			want: map[string]interface{}{
362
				"match": map[string]interface{}{},
363
			},
364
			wantErr: false,
365
		},
366
	}
367
	for _, tt := range tests {
368
		t.Run(tt.name, func(t *testing.T) {
369
			got, err := ConfigPatchesRBACToV3(tt.args.in)
370
			if (err != nil) != tt.wantErr {
371
				t.Errorf("ConfigPatchesRBACToV3() error = %v, wantErr %v", err, tt.wantErr)
372
				return
373
			}
374
			res, _ := ToYAML(tt.want)
375
			if !reflect.DeepEqual(got, res) {
376
				t.Errorf("ConfigPatchesRBACToV3() got = %v, want %v", got, tt.want)
377
			}
378
		})
379
	}
380
}
381

382
func TestOTTconfigPatchesToV3(t *testing.T) { //nolint:funlen
383
	type args struct {
384
		in interface{}
385
	}
386
	tests := []struct {
387
		name    string
388
		args    args
389
		want    interface{}
390
		wantErr bool
391
	}{
392
		{
393
			name: "sbt_authz",
394
			args: args{
395
				in: map[string]interface{}{
396
					"match": map[string]interface{}{
397
						"listener": map[string]interface{}{
398
							"filterChain": map[string]interface{}{
399
								"filter": map[string]interface{}{
400
									"name": "envoy.http_connection_manager"},
401
							},
402
						},
403
					},
404
					"patch": map[string]interface{}{
405
						"value": map[string]interface{}{
406
							"config": map[string]interface{}{
407
								"grpc_service": map[string]interface{}{
408
									"google_grpc": map[string]interface{}{
409
										"stat_prefix": "sbt_authz",
410
									},
411
								},
412
							},
413
						},
414
					},
415
				},
416
			},
417
			want: map[string]interface{}{
418
				"match": map[string]interface{}{
419
					"listener": map[string]interface{}{
420
						"filterChain": map[string]interface{}{
421
							"filter": map[string]interface{}{
422
								"name": "envoy.filters.network.http_connection_manager"},
423
						},
424
					},
425
				},
426
				"patch": map[string]interface{}{
427
					"value": map[string]interface{}{
428
						"typed_config": map[string]interface{}{
429
							"@type":   "type.googleapis.com/udpa.type.v1.TypedStruct",
430
							"typeUrl": "type.googleapis.com/envoy.extensions.filters.http.sbt_authz.v3.SbtAuthz",
431
							"value": map[string]interface{}{
432
								"api": "STANDART",
433
								"grpc_service": map[string]interface{}{
434
									"google_grpc": map[string]interface{}{"stat_prefix": "sbt_authz"},
435
								},
436
								"transport_api_version": "V3",
437
							},
438
						},
439
					},
440
				},
441
			},
442
			wantErr: false,
443
		},
444
		{
445
			name: "ext_authz",
446
			args: args{
447
				in: map[string]interface{}{
448
					"match": map[string]interface{}{
449
						"listener": map[string]interface{}{
450
							"filterChain": map[string]interface{}{
451
								"filter": map[string]interface{}{
452
									"name": "envoy.http_connection_manager"},
453
							},
454
						},
455
					},
456
					"patch": map[string]interface{}{
457
						"value": map[string]interface{}{
458
							"config": map[string]interface{}{
459
								"grpc_service": map[string]interface{}{
460
									"google_grpc": map[string]interface{}{
461
										"stat_prefix": "ext_authz",
462
									},
463
								},
464
							},
465
						},
466
					},
467
				},
468
			},
469
			want: map[string]interface{}{
470
				"match": map[string]interface{}{
471
					"listener": map[string]interface{}{
472
						"filterChain": map[string]interface{}{
473
							"filter": map[string]interface{}{
474
								"name": "envoy.filters.network.http_connection_manager"},
475
						},
476
					},
477
				},
478
				"patch": map[string]interface{}{
479
					"value": map[string]interface{}{
480
						"typed_config": map[string]interface{}{
481
							"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz",
482
							"grpc_service": map[string]interface{}{
483
								"google_grpc": map[string]interface{}{"stat_prefix": "ext_authz"},
484
							},
485
							"transport_api_version": "V3",
486
						},
487
					},
488
				},
489
			},
490
			wantErr: false,
491
		},
492
	}
493
	for _, tt := range tests {
494
		t.Run(tt.name, func(t *testing.T) {
495
			got, err := OTTconfigPatchesToV3(tt.args.in)
496
			if (err != nil) != tt.wantErr {
497
				t.Errorf("OTTconfigPatchesToV3() error = %v, wantErr %v", err, tt.wantErr)
498
				return
499
			}
500
			res, _ := ToYAML(tt.want)
501
			if !reflect.DeepEqual(got, res) {
502
				t.Errorf("OTTconfigPatchesToV3() got = %v, want %v", got, res)
503
			}
504
		})
505
	}
506
}
507

508
func TestReplaceLimiterTypedConfig(t *testing.T) {
509
	tests := []struct {
510
		name    string
511
		input   interface{}
512
		wantErr bool
513
	}{
514
		{
515
			name: "valid input",
516
			input: map[string]interface{}{
517
				"patch": map[string]interface{}{
518
					"value": map[string]interface{}{
519
						"config": map[string]interface{}{
520
							"rate_limit_service": map[string]interface{}{
521
								"transport_api_version": "V2",
522
							},
523
						},
524
					},
525
				},
526
			},
527
			wantErr: false,
528
		},
529
		{
530
			name:    "invalid input",
531
			input:   "invalid",
532
			wantErr: true,
533
		},
534
	}
535

536
	for _, tt := range tests {
537
		t.Run(tt.name, func(t *testing.T) {
538
			_, err := replaceLimiterTypedConfig(tt.input)
539
			if (err != nil) != tt.wantErr {
540
				t.Errorf("replaceLimiterTypedConfig() error = %v, wantErr %v", err, tt.wantErr)
541
				return
542
			}
543
		})
544
	}
545
}
546

547
func TestRateLimiterPatchesToV3(t *testing.T) {
548
	tests := []struct {
549
		name    string
550
		input   interface{}
551
		wantErr bool
552
	}{
553
		{
554
			name: "successful replacements",
555
			input: map[string]interface{}{
556
				"patch": "value",
557
			},
558
			wantErr: false,
559
		},
560
		{
561
			name:    "error in replaceFilterChainName",
562
			input:   "invalid",
563
			wantErr: false,
564
		},
565
		{
566
			name: "error in replaceLimiterTypedConfig",
567
			input: map[string]interface{}{
568
				"patch": "value",
569
			},
570
			wantErr: false,
571
		},
572
	}
573

574
	for _, tt := range tests {
575
		t.Run(tt.name, func(t *testing.T) {
576
			_, err := RateLimiterPatchesToV3(tt.input)
577
			if (err != nil) != tt.wantErr {
578
				t.Errorf("RateLimiterPatchesToV3() error = %v, wantErr %v", err, tt.wantErr)
579
				return
580
			}
581
		})
582
	}
583
}
584

585
func TestReplaceKey(t *testing.T) { //nolint:funlen
586
	type args struct {
587
		oldK string
588
		newK string
589
		in   any
590
	}
591
	tests := []struct {
592
		name string
593
		args args
594
		want any
595
	}{
596
		{
597
			name: "replace flat",
598
			args: args{
599
				oldK: "port",
600
				newK: "hostport",
601
				in: map[string]any{
602
					"port": map[string]any{"number": 8979},
603
					"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
604
					"outlierDetection": map[string]any{
605
						"baseEjectionTime":   "30s",
606
						"maxEjectionPercent": "10",
607
						"interval":           "40s"},
608
				},
609
			},
610
			want: map[string]any{
611
				"hostport": map[string]any{"number": 8979},
612
				"tls":      map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
613
				"outlierDetection": map[string]any{
614
					"baseEjectionTime":   "30s",
615
					"maxEjectionPercent": "10",
616
					"interval":           "40s"},
617
			},
618
		},
619
		{
620
			name: "replace with path",
621
			args: args{
622
				oldK: "outlierDetection.maxEjectionPercent",
623
				newK: "consecutive5xxErrors",
624
				in: map[string]any{
625
					"port": map[string]any{"number": 8979},
626
					"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
627
					"outlierDetection": map[string]any{
628
						"baseEjectionTime":   "30s",
629
						"maxEjectionPercent": "10",
630
						"interval":           "40s"},
631
				},
632
			},
633
			want: map[string]any{
634
				"port": map[string]any{"number": 8979},
635
				"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
636
				"outlierDetection": map[string]any{
637
					"baseEjectionTime":     "30s",
638
					"consecutive5xxErrors": "10",
639
					"interval":             "40s"},
640
			},
641
		},
642
		{ //nolint:dupl
643
			name: "replace with loong path",
644
			args: args{
645
				oldK: "long.long.looong.path.outlierDetection.baseEjectionTime",
646
				newK: "BamBamBum",
647
				in: map[string]any{
648
					"long": map[string]any{
649
						"long": map[string]any{
650
							"looong": map[string]any{
651
								"path": map[string]any{
652
									"port": map[string]any{"number": 8979},
653
									"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
654
									"outlierDetection": map[string]any{
655
										"baseEjectionTime":   "30s",
656
										"maxEjectionPercent": "10",
657
										"interval":           "40s"}},
658
							},
659
							"nil": nil,
660
						},
661
						"some other":   "other",
662
						"some another": "another",
663
					},
664
					"some other": "other",
665
				},
666
			},
667
			want: map[string]any{
668
				"long": map[string]any{
669
					"long": map[string]any{
670
						"looong": map[string]any{
671
							"path": map[string]any{
672
								"port": map[string]any{"number": 8979},
673
								"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
674
								"outlierDetection": map[string]any{
675
									"BamBamBum":          "30s",
676
									"maxEjectionPercent": "10",
677
									"interval":           "40s"}},
678
						},
679
						"nil": nil,
680
					},
681
					"some other":   "other",
682
					"some another": "another",
683
				},
684
				"some other": "other",
685
			},
686
		},
687
		{ //nolint:dupl
688
			name: "replace with loong path in the middle",
689
			args: args{
690
				oldK: "long.long.looong.path.outlierDetection",
691
				newK: "BamBamBum",
692
				in: map[string]any{
693
					"long": map[string]any{
694
						"long": map[string]any{
695
							"looong": map[string]any{
696
								"path": map[string]any{
697
									"port": map[string]any{"number": 8979},
698
									"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
699
									"outlierDetection": map[string]any{
700
										"baseEjectionTime":   "30s",
701
										"maxEjectionPercent": "10",
702
										"interval":           "40s"}},
703
							},
704
							"nil": nil,
705
						},
706
						"some other":   "other",
707
						"some another": "another",
708
					},
709
					"some other": "other",
710
				},
711
			},
712
			want: map[string]any{
713
				"long": map[string]any{
714
					"long": map[string]any{
715
						"looong": map[string]any{
716
							"path": map[string]any{
717
								"port": map[string]any{"number": 8979},
718
								"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
719
								"BamBamBum": map[string]any{
720
									"baseEjectionTime":   "30s",
721
									"maxEjectionPercent": "10",
722
									"interval":           "40s"}},
723
						},
724
						"nil": nil,
725
					},
726
					"some other":   "other",
727
					"some another": "another",
728
				},
729
				"some other": "other",
730
			},
731
		},
732
		{ //nolint:dupl
733
			name: "replace with loong path in the middle 2",
734
			args: args{
735
				oldK: "long.long",
736
				newK: "longlonglong",
737
				in: map[string]any{
738
					"long": map[string]any{
739
						"long": map[string]any{
740
							"looong": map[string]any{
741
								"path": map[string]any{
742
									"port": map[string]any{"number": 8979},
743
									"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
744
									"outlierDetection": map[string]any{
745
										"baseEjectionTime":   "30s",
746
										"maxEjectionPercent": "10",
747
										"interval":           "40s"}},
748
							},
749
							"nil": nil,
750
						},
751
						"some other":   "other",
752
						"some another": "another",
753
					},
754
					"some other": "other",
755
				},
756
			},
757
			want: map[string]any{
758
				"long": map[string]any{
759
					"longlonglong": map[string]any{
760
						"looong": map[string]any{
761
							"path": map[string]any{
762
								"port": map[string]any{"number": 8979},
763
								"tls":  map[string]any{"mode": "ISTIO_MUTUAL", "sni": "lallala"},
764
								"outlierDetection": map[string]any{
765
									"baseEjectionTime":   "30s",
766
									"maxEjectionPercent": "10",
767
									"interval":           "40s"}},
768
						},
769
						"nil": nil,
770
					},
771
					"some other":   "other",
772
					"some another": "another",
773
				},
774
				"some other": "other",
775
			},
776
		},
777
	}
778
	lib.ZapLogger = zap.NewNop()
779
	for _, tt := range tests {
780
		t.Run(tt.name, func(t *testing.T) {
781
			copyin := deepcopy.DeepCopy(tt.args.in)
782
			if got := ReplaceKey(tt.args.oldK, tt.args.newK, copyin); !reflect.DeepEqual(got, tt.want) {
783
				assert.Equal(t, tt.args.in, copyin)
784
				t.Errorf("ReplaceKey() = %v, want %v", got, tt.want)
785
			}
786
		})
787
	}
788
}
789

790
func TestDel(t *testing.T) {
791
	type args struct {
792
		path string
793
		obj  any
794
	}
795
	tests := []struct {
796
		name string
797
		args args
798
		want any
799
	}{
800
		{
801
			name: "simple del",
802
			args: args{
803
				path: "key2",
804
				obj: map[string]interface{}{
805
					"key1": "val1",
806
					"key2": "val2",
807
				},
808
			},
809
			want: map[string]interface{}{
810
				"key1": "val1",
811
			},
812
		},
813
		{
814
			name: "compound del",
815
			args: args{
816
				path: "key3.key3_1",
817
				obj: map[string]interface{}{
818
					"key1": "val1",
819
					"key2": "val2",
820
					"key3": map[string]interface{}{
821
						"key3_1": "val3_1",
822
						"key3_2": "val3_2",
823
					},
824
				},
825
			},
826
			want: map[string]interface{}{
827
				"key1": "val1",
828
				"key2": "val2",
829
				"key3": map[string]interface{}{
830
					"key3_2": "val3_2",
831
				},
832
			},
833
		},
834
		{
835
			name: "compound del 2 lvl",
836
			args: args{
837
				path: "key3.key3_2.key3_2_2.key3_2_2_1",
838
				obj: map[string]interface{}{
839
					"key1": "val1",
840
					"key2": "val2",
841
					"key3": map[string]interface{}{
842
						"key3_1": "val3_1",
843
						"key3_2": map[string]interface{}{
844
							"key3_2_1": "val3_2_1",
845
							"key3_2_2": map[string]interface{}{
846
								"key3_2_2_1": "val3_2_2_1",
847
								"key3_2_2_2": "val3_2_2_2",
848
							},
849
						},
850
					},
851
				},
852
			},
853
			want: map[string]interface{}{
854
				"key1": "val1",
855
				"key2": "val2",
856
				"key3": map[string]interface{}{
857
					"key3_1": "val3_1",
858
					"key3_2": map[string]interface{}{
859
						"key3_2_1": "val3_2_1",
860
						"key3_2_2": map[string]interface{}{
861
							"key3_2_2_2": "val3_2_2_2",
862
						},
863
					},
864
				},
865
			},
866
		},
867
		{
868
			name: "not a map",
869
			args: args{
870
				path: "",
871
				obj:  "shine bright like a diamond",
872
			},
873
			want: "shine bright like a diamond",
874
		},
875
	}
876
	lib.ZapLogger = zap.NewNop()
877
	for _, tt := range tests {
878
		t.Run(tt.name, func(t *testing.T) {
879
			assert.Equalf(t, tt.want, Del(tt.args.path, tt.args.obj), "Del(%v, %v)", tt.args.path, tt.args.obj)
880
		})
881
	}
882
}
883

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.