podman

Форк
0
/
utils_test.go 
766 строк · 15.9 Кб
1
package util
2

3
import (
4
	"fmt"
5
	"math"
6
	"sort"
7
	"testing"
8
	"time"
9

10
	"github.com/containers/storage/pkg/idtools"
11
	stypes "github.com/containers/storage/types"
12
	ruser "github.com/moby/sys/user"
13
	"github.com/opencontainers/runtime-spec/specs-go"
14
	"github.com/stretchr/testify/assert"
15
)
16

17
func BreakInsert(mapping []idtools.IDMap, extension idtools.IDMap) (result []idtools.IDMap) {
18
	result = breakInsert(mapping, extension)
19
	result = sortAndMergeConsecutiveMappings(result)
20
	return result
21
}
22

23
//#####################
24

25
func TestBreakInsert1(t *testing.T) {
26
	// extension below mapping
27
	mapping := []idtools.IDMap{
28
		{
29
			ContainerID: 1000,
30
			HostID:      1000,
31
			Size:        1,
32
		},
33
	}
34
	extension := idtools.IDMap{
35
		ContainerID: 2,
36
		HostID:      2,
37
		Size:        1,
38
	}
39
	expectedResult := []idtools.IDMap{
40
		{
41
			ContainerID: 2,
42
			HostID:      2,
43
			Size:        1,
44
		},
45
		{
46
			ContainerID: 1000,
47
			HostID:      1000,
48
			Size:        1,
49
		},
50
	}
51
	result := BreakInsert(mapping, extension)
52
	assert.Equal(t, result, expectedResult)
53
}
54

55
func TestBreakInsert2(t *testing.T) {
56
	// extension below mapping
57
	mapping := []idtools.IDMap{
58
		{
59
			ContainerID: 1000,
60
			HostID:      1001,
61
			Size:        2,
62
		},
63
	}
64
	extension := idtools.IDMap{
65
		ContainerID: 2,
66
		HostID:      3,
67
		Size:        2,
68
	}
69
	expectedResult := []idtools.IDMap{
70
		{
71
			ContainerID: 2,
72
			HostID:      3,
73
			Size:        2,
74
		},
75
		{
76
			ContainerID: 1000,
77
			HostID:      1001,
78
			Size:        2,
79
		},
80
	}
81
	result := BreakInsert(mapping, extension)
82
	assert.Equal(t, expectedResult, result)
83
}
84

85
func TestBreakInsert3(t *testing.T) {
86
	// extension above mapping
87
	mapping := []idtools.IDMap{
88
		{
89
			ContainerID: 2,
90
			HostID:      3,
91
			Size:        2,
92
		},
93
	}
94
	extension := idtools.IDMap{
95
		ContainerID: 1000,
96
		HostID:      1001,
97
		Size:        2,
98
	}
99
	expectedResult := []idtools.IDMap{
100
		{
101
			ContainerID: 2,
102
			HostID:      3,
103
			Size:        2,
104
		},
105
		{
106
			ContainerID: 1000,
107
			HostID:      1001,
108
			Size:        2,
109
		},
110
	}
111
	result := BreakInsert(mapping, extension)
112
	assert.Equal(t, expectedResult, result)
113
}
114

115
func TestBreakInsert4(t *testing.T) {
116
	// extension right below mapping
117
	mapping := []idtools.IDMap{
118
		{
119
			ContainerID: 4,
120
			HostID:      5,
121
			Size:        4,
122
		},
123
	}
124
	extension := idtools.IDMap{
125
		ContainerID: 1,
126
		HostID:      1,
127
		Size:        3,
128
	}
129
	expectedResult := []idtools.IDMap{
130
		{
131
			ContainerID: 1,
132
			HostID:      1,
133
			Size:        3,
134
		},
135
		{
136
			ContainerID: 4,
137
			HostID:      5,
138
			Size:        4,
139
		},
140
	}
141
	result := BreakInsert(mapping, extension)
142
	assert.Equal(t, expectedResult, result)
143
}
144

145
func TestSortAndMergeConsecutiveMappings(t *testing.T) {
146
	// Extension and mapping are consecutive
147
	mapping := []idtools.IDMap{
148
		{
149
			ContainerID: 1,
150
			HostID:      1,
151
			Size:        3,
152
		},
153
		{
154
			ContainerID: 4,
155
			HostID:      4,
156
			Size:        4,
157
		},
158
	}
159
	expectedResult := []idtools.IDMap{
160
		{
161
			ContainerID: 1,
162
			HostID:      1,
163
			Size:        7,
164
		},
165
	}
166
	result := sortAndMergeConsecutiveMappings(mapping)
167
	assert.Equal(t, expectedResult, result)
168
}
169

170
//#####################
171

172
func TestParseIDMap(t *testing.T) {
173
	mapSpec := []string{"+100000:@1002:1"}
174

175
	parentMapping := []ruser.IDMap{
176
		{
177
			ID:       int64(20),
178
			ParentID: int64(1002),
179
			Count:    1,
180
		},
181
	}
182
	expectedResult := []idtools.IDMap{
183
		{
184
			ContainerID: 100000,
185
			HostID:      20,
186
			Size:        1,
187
		},
188
	}
189
	result, err := ParseIDMap(
190
		mapSpec,
191
		"UID",
192
		parentMapping,
193
	)
194
	assert.Equal(t, nil, err)
195
	assert.Equal(t, expectedResult, result)
196
}
197

198
func TestParseIDMapSizeMissing(t *testing.T) {
199
	// Size is 1 if not provided
200
	mapSpec := []string{"+100000:@1002"}
201

202
	parentMapping := []ruser.IDMap{
203
		{
204
			ID:       int64(20),
205
			ParentID: int64(1002),
206
			Count:    1,
207
		},
208
	}
209
	expectedResult := []idtools.IDMap{
210
		{
211
			ContainerID: 100000,
212
			HostID:      20,
213
			Size:        1,
214
		},
215
	}
216
	result, err := ParseIDMap(
217
		mapSpec,
218
		"UID",
219
		parentMapping,
220
	)
221
	assert.Equal(t, nil, err)
222
	assert.Equal(t, expectedResult, result)
223
}
224

225
func TestParseIDMap2(t *testing.T) {
226
	mapSpec := []string{"0:2000:100000", "+1:100:1"}
227
	parentMapping := []ruser.IDMap(nil)
228
	expectedResult := []idtools.IDMap{
229
		{
230
			ContainerID: 0,
231
			HostID:      2000,
232
			Size:        1,
233
		},
234
		{
235
			ContainerID: 1,
236
			HostID:      100,
237
			Size:        1,
238
		},
239
		{
240
			ContainerID: 2,
241
			HostID:      2002,
242
			Size:        99998,
243
		},
244
	}
245
	result, err := ParseIDMap(
246
		mapSpec,
247
		"UID",
248
		parentMapping,
249
	)
250
	assert.Equal(t, nil, err)
251
	assert.Equal(t, expectedResult, result)
252
}
253

254
func TestParseIDMap3(t *testing.T) {
255
	mapSpec := []string{"0:0:20", "24:24:6", "+7:1000:2", "+12:2000:3", "+18:3000:7"}
256
	parentMapping := []ruser.IDMap(nil)
257
	expectedResult := []idtools.IDMap{
258
		{
259
			ContainerID: 0,
260
			HostID:      0,
261
			Size:        7,
262
		},
263
		{
264
			ContainerID: 7,
265
			HostID:      1000,
266
			Size:        2,
267
		},
268
		{
269
			ContainerID: 9,
270
			HostID:      9,
271
			Size:        3,
272
		},
273
		{
274
			ContainerID: 12,
275
			HostID:      2000,
276
			Size:        3,
277
		},
278
		{
279
			ContainerID: 15,
280
			HostID:      15,
281
			Size:        3,
282
		},
283
		{
284
			ContainerID: 18,
285
			HostID:      3000,
286
			Size:        7,
287
		},
288
		{
289
			ContainerID: 25,
290
			HostID:      25,
291
			Size:        5,
292
		},
293
	}
294
	result, err := ParseIDMap(
295
		mapSpec,
296
		"UID",
297
		parentMapping,
298
	)
299
	assert.Equal(t, nil, err)
300
	assert.Equal(t, expectedResult, result)
301
}
302

303
func TestParseIDMap4(t *testing.T) {
304
	mapSpec := []string{"0:0:20", "+10:1:1"}
305
	parentMapping := []ruser.IDMap(nil)
306
	expectedResult := []idtools.IDMap{
307
		{
308
			ContainerID: 0,
309
			HostID:      0,
310
			Size:        1,
311
		},
312
		{
313
			ContainerID: 2,
314
			HostID:      2,
315
			Size:        8,
316
		},
317
		{
318
			ContainerID: 10,
319
			HostID:      1,
320
			Size:        1,
321
		},
322
		{
323
			ContainerID: 11,
324
			HostID:      11,
325
			Size:        9,
326
		},
327
	}
328
	result, err := ParseIDMap(
329
		mapSpec,
330
		"UID",
331
		parentMapping,
332
	)
333
	assert.Equal(t, nil, err)
334
	assert.Equal(t, expectedResult, result)
335
}
336

337
func TestParseIDMap5(t *testing.T) {
338
	mapSpec := []string{"0:20:10", "15:35:10", "+8:23:16"}
339
	parentMapping := []ruser.IDMap(nil)
340
	expectedResult := []idtools.IDMap{
341
		{
342
			ContainerID: 0,
343
			HostID:      20,
344
			Size:        3,
345
		},
346
		{
347
			ContainerID: 8,
348
			HostID:      23,
349
			Size:        16,
350
		},
351
		{
352
			ContainerID: 24,
353
			HostID:      44,
354
			Size:        1,
355
		},
356
	}
357
	result, err := ParseIDMap(
358
		mapSpec,
359
		"UID",
360
		parentMapping,
361
	)
362
	assert.Equal(t, nil, err)
363
	assert.Equal(t, expectedResult, result)
364
}
365

366
func TestParseIDMapUserGroupFlags(t *testing.T) {
367
	mapSpec := []string{"u1:3:1", "g2:4:2"}
368
	parentMapping := []ruser.IDMap(nil)
369
	expectedResultUser := []idtools.IDMap{
370
		{
371
			ContainerID: 1,
372
			HostID:      3,
373
			Size:        1,
374
		},
375
	}
376
	expectedResultGroup := []idtools.IDMap{
377
		{
378
			ContainerID: 2,
379
			HostID:      4,
380
			Size:        2,
381
		},
382
	}
383
	result, err := ParseIDMap(mapSpec, "UID", parentMapping)
384
	assert.Equal(t, nil, err)
385
	assert.Equal(t, expectedResultUser, result)
386
	result, err = ParseIDMap(mapSpec, "GID", parentMapping)
387
	assert.Equal(t, err, nil)
388
	assert.Equal(t, expectedResultGroup, result)
389
}
390

391
func TestParseAutoIDMap(t *testing.T) {
392
	result, err := parseAutoIDMap("3:4:5", "UID", []ruser.IDMap{})
393
	assert.Equal(t, err, nil)
394
	assert.Equal(t, result, []idtools.IDMap{
395
		{
396
			ContainerID: 3,
397
			HostID:      4,
398
			Size:        5,
399
		},
400
	})
401
}
402

403
func TestParseAutoIDMapRelative(t *testing.T) {
404
	parentMapping := []ruser.IDMap{
405
		{
406
			ID:       0,
407
			ParentID: 1000,
408
			Count:    1,
409
		},
410
		{
411
			ID:       1,
412
			ParentID: 100000,
413
			Count:    65536,
414
		},
415
	}
416
	result, err := parseAutoIDMap("100:@100000:1", "UID", parentMapping)
417
	assert.Equal(t, err, nil)
418
	assert.Equal(t, result, []idtools.IDMap{
419
		{
420
			ContainerID: 100,
421
			HostID:      1,
422
			Size:        1,
423
		},
424
	})
425
}
426

427
func TestFillIDMap(t *testing.T) {
428
	availableRanges := [][2]int{{0, 10}, {10000, 20000}}
429
	idmap := []idtools.IDMap{
430
		{
431
			ContainerID: 1,
432
			HostID:      1000,
433
			Size:        10,
434
		},
435
		{
436
			ContainerID: 30,
437
			HostID:      2000,
438
			Size:        20,
439
		},
440
	}
441
	expectedResult := []idtools.IDMap{
442
		{
443
			ContainerID: 0,
444
			HostID:      0,
445
			Size:        1,
446
		},
447
		{
448
			ContainerID: 1,
449
			HostID:      1000,
450
			Size:        10,
451
		},
452
		{
453
			ContainerID: 11,
454
			HostID:      1,
455
			Size:        9,
456
		},
457
		{
458
			ContainerID: 20,
459
			HostID:      10000,
460
			Size:        10,
461
		},
462
		{
463
			ContainerID: 30,
464
			HostID:      2000,
465
			Size:        20,
466
		},
467
		{
468
			ContainerID: 50,
469
			HostID:      10010,
470
			Size:        9990,
471
		},
472
	}
473
	result := fillIDMap(idmap, availableRanges)
474
	assert.Equal(t, expectedResult, result)
475
}
476

477
func TestGetAvailableIDRanges(t *testing.T) {
478
	all := [][2]int{{0, 30}, {50, 70}}
479
	used := [][2]int{{2, 4}, {25, 55}}
480
	expectedResult := [][2]int{{0, 2}, {4, 25}, {55, 70}}
481
	result := getAvailableIDRanges(all, used)
482
	assert.Equal(t, expectedResult, result)
483
}
484

485
func TestValidateSysctls(t *testing.T) {
486
	strSlice := []string{"net.core.test1=4", "kernel.msgmax=2"}
487
	result, _ := ValidateSysctls(strSlice)
488
	assert.Equal(t, result["net.core.test1"], "4")
489
}
490

491
func TestValidateSysctlBadSysctl(t *testing.T) {
492
	strSlice := []string{"BLAU=BLUE", "GELB^YELLOW"}
493
	_, err := ValidateSysctls(strSlice)
494
	assert.Error(t, err)
495
}
496

497
func TestValidateSysctlBadSysctlWithExtraSpaces(t *testing.T) {
498
	expectedError := "'%s' is invalid, extra spaces found"
499

500
	// should fail fast on first sysctl
501
	strSlice1 := []string{
502
		"net.ipv4.ping_group_range = 0 0",
503
		"net.ipv4.ping_group_range=0 0 ",
504
	}
505
	_, err := ValidateSysctls(strSlice1)
506
	assert.Error(t, err)
507
	assert.Equal(t, err.Error(), fmt.Sprintf(expectedError, strSlice1[0]))
508

509
	// should fail on second sysctl
510
	strSlice2 := []string{
511
		"net.ipv4.ping_group_range=0 0",
512
		"net.ipv4.ping_group_range=0 0 ",
513
	}
514
	_, err = ValidateSysctls(strSlice2)
515
	assert.Error(t, err)
516
	assert.Equal(t, err.Error(), fmt.Sprintf(expectedError, strSlice2[1]))
517
}
518

519
func TestCoresToPeriodAndQuota(t *testing.T) {
520
	cores := 1.0
521
	expectedPeriod := DefaultCPUPeriod
522
	expectedQuota := int64(DefaultCPUPeriod)
523

524
	actualPeriod, actualQuota := CoresToPeriodAndQuota(cores)
525
	assert.Equal(t, actualPeriod, expectedPeriod, "Period does not match")
526
	assert.Equal(t, actualQuota, expectedQuota, "Quota does not match")
527
}
528

529
func TestPeriodAndQuotaToCores(t *testing.T) {
530
	var (
531
		period        uint64 = 100000
532
		quota         int64  = 50000
533
		expectedCores        = 0.5
534
	)
535

536
	assert.Equal(t, PeriodAndQuotaToCores(period, quota), expectedCores)
537
}
538

539
func TestParseInputTime(t *testing.T) {
540
	tm, err := ParseInputTime("1.5", true)
541
	if err != nil {
542
		t.Errorf("expected error to be nil but was: %v", err)
543
	}
544

545
	expected, err := time.ParseInLocation(time.RFC3339Nano, "1970-01-01T00:00:01.500000000Z", time.UTC)
546
	if err != nil {
547
		t.Fatal(err)
548
	}
549

550
	assert.Equal(t, expected, tm)
551
}
552

553
func TestConvertMappings(t *testing.T) {
554
	start := []specs.LinuxIDMapping{
555
		{
556
			ContainerID: 1,
557
			HostID:      2,
558
			Size:        3,
559
		},
560
		{
561
			ContainerID: 4,
562
			HostID:      5,
563
			Size:        6,
564
		},
565
	}
566

567
	converted := RuntimeSpecToIDtools(start)
568

569
	convertedBack := IDtoolsToRuntimeSpec(converted)
570

571
	assert.Equal(t, len(start), len(convertedBack))
572

573
	for i := range start {
574
		assert.Equal(t, start[i].ContainerID, convertedBack[i].ContainerID)
575
		assert.Equal(t, start[i].HostID, convertedBack[i].HostID)
576
		assert.Equal(t, start[i].Size, convertedBack[i].Size)
577
	}
578
}
579

580
func TestConvertTimeout(t *testing.T) {
581
	timeout := ConvertTimeout(0)
582
	assert.Equal(t, uint(0), timeout)
583

584
	timeout = ConvertTimeout(100)
585
	assert.Equal(t, uint(100), timeout)
586

587
	timeout = ConvertTimeout(-1)
588
	assert.Equal(t, uint(math.MaxUint32), timeout)
589

590
	timeout = ConvertTimeout(-100)
591
	assert.Equal(t, uint(math.MaxUint32), timeout)
592
}
593

594
func TestGetRootlessKeepIDMapping(t *testing.T) {
595
	tests := []struct {
596
		uid, gid                 int
597
		uids, gids               []idtools.IDMap
598
		expectedOptions          *stypes.IDMappingOptions
599
		expectedUID, expectedGID int
600
		expectedError            error
601
	}{
602
		{
603
			uid:  1000,
604
			gid:  1000,
605
			uids: []idtools.IDMap{},
606
			gids: []idtools.IDMap{},
607
			expectedOptions: &stypes.IDMappingOptions{
608
				HostUIDMapping: false,
609
				HostGIDMapping: false,
610
				UIDMap:         []idtools.IDMap{{ContainerID: 1000, HostID: 0, Size: 1}},
611
				GIDMap:         []idtools.IDMap{{ContainerID: 1000, HostID: 0, Size: 1}},
612
			},
613
			expectedUID: 1000,
614
			expectedGID: 1000,
615
		},
616
		{
617
			uid:  0,
618
			gid:  0,
619
			uids: []idtools.IDMap{{ContainerID: 0, HostID: 100000, Size: 65536}},
620
			gids: []idtools.IDMap{{ContainerID: 0, HostID: 100000, Size: 65536}},
621
			expectedOptions: &stypes.IDMappingOptions{
622
				HostUIDMapping: false,
623
				HostGIDMapping: false,
624
				UIDMap:         []idtools.IDMap{{ContainerID: 0, HostID: 0, Size: 1}, {ContainerID: 1, HostID: 1, Size: 65536}},
625
				GIDMap:         []idtools.IDMap{{ContainerID: 0, HostID: 0, Size: 1}, {ContainerID: 1, HostID: 1, Size: 65536}},
626
			},
627
			expectedUID: 0,
628
			expectedGID: 0,
629
		},
630
	}
631

632
	for _, test := range tests {
633
		options, uid, gid, err := getRootlessKeepIDMapping(test.uid, test.gid, test.uids, test.gids)
634
		assert.Nil(t, err)
635
		assert.Equal(t, test.expectedOptions, options)
636
		assert.Equal(t, test.expectedUID, uid)
637
		assert.Equal(t, test.expectedGID, gid)
638
	}
639
}
640

641
func getDefaultMountOptionsNoStat(path string) (defaultMountOptions, error) {
642
	return defaultMountOptions{false, true, true}, nil
643
}
644

645
func TestProcessOptions(t *testing.T) {
646
	tests := []struct {
647
		name       string
648
		options    []string
649
		isTmpfs    bool
650
		sourcePath string
651
		expected   []string
652
		expectErr  bool
653
	}{
654
		{
655
			name:       "tmpfs",
656
			options:    []string{"rw", "size=512m"},
657
			isTmpfs:    true,
658
			sourcePath: "",
659
			expected:   []string{"nodev", "nosuid", "rprivate", "rw", "size=512m", "tmpcopyup"},
660
		},
661
		{
662
			name:       "duplicate idmap option",
663
			sourcePath: "/path/to/source",
664
			options:    []string{"idmap", "idmap"},
665
			expectErr:  true,
666
		},
667
		{
668
			name:       "mode allowed only with tmpfs",
669
			sourcePath: "/path/to/source",
670
			options:    []string{"rw", "rbind", "mode=0123"},
671
			expectErr:  true,
672
		},
673
		{
674
			name:       "noswap allowed only with tmpfs",
675
			sourcePath: "/path/to/source",
676
			options:    []string{"noswap"},
677
			expectErr:  true,
678
		},
679
		{
680
			name:       "tmpcopyup allowed only with tmpfs",
681
			sourcePath: "/path/to/source",
682
			options:    []string{"tmpcopyup"},
683
			expectErr:  true,
684
		},
685
		{
686
			name:       "notmpcopyup allowed only with tmpfs",
687
			sourcePath: "/path/to/source",
688
			options:    []string{"notmpcopyup"},
689
			expectErr:  true,
690
		},
691
		{
692
			name:       "z not allowed with tmpfs",
693
			isTmpfs:    true,
694
			sourcePath: "/path/to/source",
695
			options:    []string{"z"},
696
			expectErr:  true,
697
		},
698
		{
699
			name:       "size allowed only with tmpfs",
700
			sourcePath: "/path/to/source",
701
			options:    []string{"size=123456"},
702
			expectErr:  true,
703
		},
704
		{
705
			name:       "conflicting option dev/nodev",
706
			sourcePath: "/path/to/source",
707
			options:    []string{"dev", "nodev"},
708
			expectErr:  true,
709
		},
710
		{
711
			name:       "conflicting option suid/nosuid",
712
			sourcePath: "/path/to/source",
713
			options:    []string{"suid", "nosuid"},
714
			expectErr:  true,
715
		},
716
		{
717
			name:       "conflicting option exec/noexec",
718
			sourcePath: "/path/to/source",
719
			options:    []string{"noexec", "exec"},
720
			expectErr:  true,
721
		},
722
		{
723
			name:       "conflicting option ro/rw",
724
			sourcePath: "/path/to/source",
725
			options:    []string{"ro", "rw"},
726
			expectErr:  true,
727
		},
728
		{
729
			name:       "conflicting option bind/rbind",
730
			sourcePath: "/path/to/source",
731
			options:    []string{"bind", "rbind"},
732
			expectErr:  true,
733
		},
734
		{
735
			name:       "conflicting option bind/rbind",
736
			sourcePath: "/path/to/source",
737
			options:    []string{"bind", "rbind"},
738
			expectErr:  true,
739
		},
740
		{
741
			name:       "default bind mount",
742
			sourcePath: "/path/to/source",
743
			expected:   []string{"nodev", "nosuid", "rbind", "rprivate", "rw"},
744
		},
745
		{
746
			name:       "default bind mount with bind",
747
			sourcePath: "/path/to/source",
748
			options:    []string{"bind"},
749
			expected:   []string{"nodev", "nosuid", "bind", "private", "rw"},
750
		},
751
	}
752

753
	for _, tt := range tests {
754
		t.Run(tt.name, func(t *testing.T) {
755
			opts, err := processOptionsInternal(tt.options, tt.isTmpfs, tt.sourcePath, getDefaultMountOptionsNoStat)
756
			if tt.expectErr {
757
				assert.NotNil(t, err)
758
			} else {
759
				assert.Nil(t, err)
760
				sort.Strings(opts)
761
				sort.Strings(tt.expected)
762
				assert.Equal(t, opts, tt.expected)
763
			}
764
		})
765
	}
766
}
767

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

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

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

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