mirror of
				https://github.com/containers/podman.git
				synced 2025-11-04 08:56:05 +08:00 
			
		
		
		
	when the "bind" option is used, do not use the "rprivate" propagation as it would inhibit the effect of "bind", instead default to "private". Closes: https://github.com/containers/podman/issues/22107 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
		
			
				
	
	
		
			767 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			767 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package util
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"math"
 | 
						|
	"sort"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/containers/storage/pkg/idtools"
 | 
						|
	stypes "github.com/containers/storage/types"
 | 
						|
	ruser "github.com/moby/sys/user"
 | 
						|
	"github.com/opencontainers/runtime-spec/specs-go"
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
)
 | 
						|
 | 
						|
func BreakInsert(mapping []idtools.IDMap, extension idtools.IDMap) (result []idtools.IDMap) {
 | 
						|
	result = breakInsert(mapping, extension)
 | 
						|
	result = sortAndMergeConsecutiveMappings(result)
 | 
						|
	return result
 | 
						|
}
 | 
						|
 | 
						|
//#####################
 | 
						|
 | 
						|
func TestBreakInsert1(t *testing.T) {
 | 
						|
	// extension below mapping
 | 
						|
	mapping := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 1000,
 | 
						|
			HostID:      1000,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	extension := idtools.IDMap{
 | 
						|
		ContainerID: 2,
 | 
						|
		HostID:      2,
 | 
						|
		Size:        1,
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 2,
 | 
						|
			HostID:      2,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 1000,
 | 
						|
			HostID:      1000,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result := BreakInsert(mapping, extension)
 | 
						|
	assert.Equal(t, result, expectedResult)
 | 
						|
}
 | 
						|
 | 
						|
func TestBreakInsert2(t *testing.T) {
 | 
						|
	// extension below mapping
 | 
						|
	mapping := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 1000,
 | 
						|
			HostID:      1001,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	extension := idtools.IDMap{
 | 
						|
		ContainerID: 2,
 | 
						|
		HostID:      3,
 | 
						|
		Size:        2,
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 2,
 | 
						|
			HostID:      3,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 1000,
 | 
						|
			HostID:      1001,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result := BreakInsert(mapping, extension)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestBreakInsert3(t *testing.T) {
 | 
						|
	// extension above mapping
 | 
						|
	mapping := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 2,
 | 
						|
			HostID:      3,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	extension := idtools.IDMap{
 | 
						|
		ContainerID: 1000,
 | 
						|
		HostID:      1001,
 | 
						|
		Size:        2,
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 2,
 | 
						|
			HostID:      3,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 1000,
 | 
						|
			HostID:      1001,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result := BreakInsert(mapping, extension)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestBreakInsert4(t *testing.T) {
 | 
						|
	// extension right below mapping
 | 
						|
	mapping := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 4,
 | 
						|
			HostID:      5,
 | 
						|
			Size:        4,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	extension := idtools.IDMap{
 | 
						|
		ContainerID: 1,
 | 
						|
		HostID:      1,
 | 
						|
		Size:        3,
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      1,
 | 
						|
			Size:        3,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 4,
 | 
						|
			HostID:      5,
 | 
						|
			Size:        4,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result := BreakInsert(mapping, extension)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestSortAndMergeConsecutiveMappings(t *testing.T) {
 | 
						|
	// Extension and mapping are consecutive
 | 
						|
	mapping := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      1,
 | 
						|
			Size:        3,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 4,
 | 
						|
			HostID:      4,
 | 
						|
			Size:        4,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      1,
 | 
						|
			Size:        7,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result := sortAndMergeConsecutiveMappings(mapping)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
//#####################
 | 
						|
 | 
						|
func TestParseIDMap(t *testing.T) {
 | 
						|
	mapSpec := []string{"+100000:@1002:1"}
 | 
						|
 | 
						|
	parentMapping := []ruser.IDMap{
 | 
						|
		{
 | 
						|
			ID:       int64(20),
 | 
						|
			ParentID: int64(1002),
 | 
						|
			Count:    1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 100000,
 | 
						|
			HostID:      20,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := ParseIDMap(
 | 
						|
		mapSpec,
 | 
						|
		"UID",
 | 
						|
		parentMapping,
 | 
						|
	)
 | 
						|
	assert.Equal(t, nil, err)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseIDMapSizeMissing(t *testing.T) {
 | 
						|
	// Size is 1 if not provided
 | 
						|
	mapSpec := []string{"+100000:@1002"}
 | 
						|
 | 
						|
	parentMapping := []ruser.IDMap{
 | 
						|
		{
 | 
						|
			ID:       int64(20),
 | 
						|
			ParentID: int64(1002),
 | 
						|
			Count:    1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 100000,
 | 
						|
			HostID:      20,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := ParseIDMap(
 | 
						|
		mapSpec,
 | 
						|
		"UID",
 | 
						|
		parentMapping,
 | 
						|
	)
 | 
						|
	assert.Equal(t, nil, err)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseIDMap2(t *testing.T) {
 | 
						|
	mapSpec := []string{"0:2000:100000", "+1:100:1"}
 | 
						|
	parentMapping := []ruser.IDMap(nil)
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 0,
 | 
						|
			HostID:      2000,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      100,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 2,
 | 
						|
			HostID:      2002,
 | 
						|
			Size:        99998,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := ParseIDMap(
 | 
						|
		mapSpec,
 | 
						|
		"UID",
 | 
						|
		parentMapping,
 | 
						|
	)
 | 
						|
	assert.Equal(t, nil, err)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseIDMap3(t *testing.T) {
 | 
						|
	mapSpec := []string{"0:0:20", "24:24:6", "+7:1000:2", "+12:2000:3", "+18:3000:7"}
 | 
						|
	parentMapping := []ruser.IDMap(nil)
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 0,
 | 
						|
			HostID:      0,
 | 
						|
			Size:        7,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 7,
 | 
						|
			HostID:      1000,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 9,
 | 
						|
			HostID:      9,
 | 
						|
			Size:        3,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 12,
 | 
						|
			HostID:      2000,
 | 
						|
			Size:        3,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 15,
 | 
						|
			HostID:      15,
 | 
						|
			Size:        3,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 18,
 | 
						|
			HostID:      3000,
 | 
						|
			Size:        7,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 25,
 | 
						|
			HostID:      25,
 | 
						|
			Size:        5,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := ParseIDMap(
 | 
						|
		mapSpec,
 | 
						|
		"UID",
 | 
						|
		parentMapping,
 | 
						|
	)
 | 
						|
	assert.Equal(t, nil, err)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseIDMap4(t *testing.T) {
 | 
						|
	mapSpec := []string{"0:0:20", "+10:1:1"}
 | 
						|
	parentMapping := []ruser.IDMap(nil)
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 0,
 | 
						|
			HostID:      0,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 2,
 | 
						|
			HostID:      2,
 | 
						|
			Size:        8,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 10,
 | 
						|
			HostID:      1,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 11,
 | 
						|
			HostID:      11,
 | 
						|
			Size:        9,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := ParseIDMap(
 | 
						|
		mapSpec,
 | 
						|
		"UID",
 | 
						|
		parentMapping,
 | 
						|
	)
 | 
						|
	assert.Equal(t, nil, err)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseIDMap5(t *testing.T) {
 | 
						|
	mapSpec := []string{"0:20:10", "15:35:10", "+8:23:16"}
 | 
						|
	parentMapping := []ruser.IDMap(nil)
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 0,
 | 
						|
			HostID:      20,
 | 
						|
			Size:        3,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 8,
 | 
						|
			HostID:      23,
 | 
						|
			Size:        16,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 24,
 | 
						|
			HostID:      44,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := ParseIDMap(
 | 
						|
		mapSpec,
 | 
						|
		"UID",
 | 
						|
		parentMapping,
 | 
						|
	)
 | 
						|
	assert.Equal(t, nil, err)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseIDMapUserGroupFlags(t *testing.T) {
 | 
						|
	mapSpec := []string{"u1:3:1", "g2:4:2"}
 | 
						|
	parentMapping := []ruser.IDMap(nil)
 | 
						|
	expectedResultUser := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      3,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	expectedResultGroup := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 2,
 | 
						|
			HostID:      4,
 | 
						|
			Size:        2,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := ParseIDMap(mapSpec, "UID", parentMapping)
 | 
						|
	assert.Equal(t, nil, err)
 | 
						|
	assert.Equal(t, expectedResultUser, result)
 | 
						|
	result, err = ParseIDMap(mapSpec, "GID", parentMapping)
 | 
						|
	assert.Equal(t, err, nil)
 | 
						|
	assert.Equal(t, expectedResultGroup, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseAutoIDMap(t *testing.T) {
 | 
						|
	result, err := parseAutoIDMap("3:4:5", "UID", []ruser.IDMap{})
 | 
						|
	assert.Equal(t, err, nil)
 | 
						|
	assert.Equal(t, result, []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 3,
 | 
						|
			HostID:      4,
 | 
						|
			Size:        5,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func TestParseAutoIDMapRelative(t *testing.T) {
 | 
						|
	parentMapping := []ruser.IDMap{
 | 
						|
		{
 | 
						|
			ID:       0,
 | 
						|
			ParentID: 1000,
 | 
						|
			Count:    1,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ID:       1,
 | 
						|
			ParentID: 100000,
 | 
						|
			Count:    65536,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result, err := parseAutoIDMap("100:@100000:1", "UID", parentMapping)
 | 
						|
	assert.Equal(t, err, nil)
 | 
						|
	assert.Equal(t, result, []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 100,
 | 
						|
			HostID:      1,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func TestFillIDMap(t *testing.T) {
 | 
						|
	availableRanges := [][2]int{{0, 10}, {10000, 20000}}
 | 
						|
	idmap := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      1000,
 | 
						|
			Size:        10,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 30,
 | 
						|
			HostID:      2000,
 | 
						|
			Size:        20,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	expectedResult := []idtools.IDMap{
 | 
						|
		{
 | 
						|
			ContainerID: 0,
 | 
						|
			HostID:      0,
 | 
						|
			Size:        1,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      1000,
 | 
						|
			Size:        10,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 11,
 | 
						|
			HostID:      1,
 | 
						|
			Size:        9,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 20,
 | 
						|
			HostID:      10000,
 | 
						|
			Size:        10,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 30,
 | 
						|
			HostID:      2000,
 | 
						|
			Size:        20,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 50,
 | 
						|
			HostID:      10010,
 | 
						|
			Size:        9990,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	result := fillIDMap(idmap, availableRanges)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestGetAvailableIDRanges(t *testing.T) {
 | 
						|
	all := [][2]int{{0, 30}, {50, 70}}
 | 
						|
	used := [][2]int{{2, 4}, {25, 55}}
 | 
						|
	expectedResult := [][2]int{{0, 2}, {4, 25}, {55, 70}}
 | 
						|
	result := getAvailableIDRanges(all, used)
 | 
						|
	assert.Equal(t, expectedResult, result)
 | 
						|
}
 | 
						|
 | 
						|
func TestValidateSysctls(t *testing.T) {
 | 
						|
	strSlice := []string{"net.core.test1=4", "kernel.msgmax=2"}
 | 
						|
	result, _ := ValidateSysctls(strSlice)
 | 
						|
	assert.Equal(t, result["net.core.test1"], "4")
 | 
						|
}
 | 
						|
 | 
						|
func TestValidateSysctlBadSysctl(t *testing.T) {
 | 
						|
	strSlice := []string{"BLAU=BLUE", "GELB^YELLOW"}
 | 
						|
	_, err := ValidateSysctls(strSlice)
 | 
						|
	assert.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestValidateSysctlBadSysctlWithExtraSpaces(t *testing.T) {
 | 
						|
	expectedError := "'%s' is invalid, extra spaces found"
 | 
						|
 | 
						|
	// should fail fast on first sysctl
 | 
						|
	strSlice1 := []string{
 | 
						|
		"net.ipv4.ping_group_range = 0 0",
 | 
						|
		"net.ipv4.ping_group_range=0 0 ",
 | 
						|
	}
 | 
						|
	_, err := ValidateSysctls(strSlice1)
 | 
						|
	assert.Error(t, err)
 | 
						|
	assert.Equal(t, err.Error(), fmt.Sprintf(expectedError, strSlice1[0]))
 | 
						|
 | 
						|
	// should fail on second sysctl
 | 
						|
	strSlice2 := []string{
 | 
						|
		"net.ipv4.ping_group_range=0 0",
 | 
						|
		"net.ipv4.ping_group_range=0 0 ",
 | 
						|
	}
 | 
						|
	_, err = ValidateSysctls(strSlice2)
 | 
						|
	assert.Error(t, err)
 | 
						|
	assert.Equal(t, err.Error(), fmt.Sprintf(expectedError, strSlice2[1]))
 | 
						|
}
 | 
						|
 | 
						|
func TestCoresToPeriodAndQuota(t *testing.T) {
 | 
						|
	cores := 1.0
 | 
						|
	expectedPeriod := DefaultCPUPeriod
 | 
						|
	expectedQuota := int64(DefaultCPUPeriod)
 | 
						|
 | 
						|
	actualPeriod, actualQuota := CoresToPeriodAndQuota(cores)
 | 
						|
	assert.Equal(t, actualPeriod, expectedPeriod, "Period does not match")
 | 
						|
	assert.Equal(t, actualQuota, expectedQuota, "Quota does not match")
 | 
						|
}
 | 
						|
 | 
						|
func TestPeriodAndQuotaToCores(t *testing.T) {
 | 
						|
	var (
 | 
						|
		period        uint64 = 100000
 | 
						|
		quota         int64  = 50000
 | 
						|
		expectedCores        = 0.5
 | 
						|
	)
 | 
						|
 | 
						|
	assert.Equal(t, PeriodAndQuotaToCores(period, quota), expectedCores)
 | 
						|
}
 | 
						|
 | 
						|
func TestParseInputTime(t *testing.T) {
 | 
						|
	tm, err := ParseInputTime("1.5", true)
 | 
						|
	if err != nil {
 | 
						|
		t.Errorf("expected error to be nil but was: %v", err)
 | 
						|
	}
 | 
						|
 | 
						|
	expected, err := time.ParseInLocation(time.RFC3339Nano, "1970-01-01T00:00:01.500000000Z", time.UTC)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	assert.Equal(t, expected, tm)
 | 
						|
}
 | 
						|
 | 
						|
func TestConvertMappings(t *testing.T) {
 | 
						|
	start := []specs.LinuxIDMapping{
 | 
						|
		{
 | 
						|
			ContainerID: 1,
 | 
						|
			HostID:      2,
 | 
						|
			Size:        3,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			ContainerID: 4,
 | 
						|
			HostID:      5,
 | 
						|
			Size:        6,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	converted := RuntimeSpecToIDtools(start)
 | 
						|
 | 
						|
	convertedBack := IDtoolsToRuntimeSpec(converted)
 | 
						|
 | 
						|
	assert.Equal(t, len(start), len(convertedBack))
 | 
						|
 | 
						|
	for i := range start {
 | 
						|
		assert.Equal(t, start[i].ContainerID, convertedBack[i].ContainerID)
 | 
						|
		assert.Equal(t, start[i].HostID, convertedBack[i].HostID)
 | 
						|
		assert.Equal(t, start[i].Size, convertedBack[i].Size)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestConvertTimeout(t *testing.T) {
 | 
						|
	timeout := ConvertTimeout(0)
 | 
						|
	assert.Equal(t, uint(0), timeout)
 | 
						|
 | 
						|
	timeout = ConvertTimeout(100)
 | 
						|
	assert.Equal(t, uint(100), timeout)
 | 
						|
 | 
						|
	timeout = ConvertTimeout(-1)
 | 
						|
	assert.Equal(t, uint(math.MaxUint32), timeout)
 | 
						|
 | 
						|
	timeout = ConvertTimeout(-100)
 | 
						|
	assert.Equal(t, uint(math.MaxUint32), timeout)
 | 
						|
}
 | 
						|
 | 
						|
func TestGetRootlessKeepIDMapping(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		uid, gid                 int
 | 
						|
		uids, gids               []idtools.IDMap
 | 
						|
		expectedOptions          *stypes.IDMappingOptions
 | 
						|
		expectedUID, expectedGID int
 | 
						|
		expectedError            error
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			uid:  1000,
 | 
						|
			gid:  1000,
 | 
						|
			uids: []idtools.IDMap{},
 | 
						|
			gids: []idtools.IDMap{},
 | 
						|
			expectedOptions: &stypes.IDMappingOptions{
 | 
						|
				HostUIDMapping: false,
 | 
						|
				HostGIDMapping: false,
 | 
						|
				UIDMap:         []idtools.IDMap{{ContainerID: 1000, HostID: 0, Size: 1}},
 | 
						|
				GIDMap:         []idtools.IDMap{{ContainerID: 1000, HostID: 0, Size: 1}},
 | 
						|
			},
 | 
						|
			expectedUID: 1000,
 | 
						|
			expectedGID: 1000,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			uid:  0,
 | 
						|
			gid:  0,
 | 
						|
			uids: []idtools.IDMap{{ContainerID: 0, HostID: 100000, Size: 65536}},
 | 
						|
			gids: []idtools.IDMap{{ContainerID: 0, HostID: 100000, Size: 65536}},
 | 
						|
			expectedOptions: &stypes.IDMappingOptions{
 | 
						|
				HostUIDMapping: false,
 | 
						|
				HostGIDMapping: false,
 | 
						|
				UIDMap:         []idtools.IDMap{{ContainerID: 0, HostID: 0, Size: 1}, {ContainerID: 1, HostID: 1, Size: 65536}},
 | 
						|
				GIDMap:         []idtools.IDMap{{ContainerID: 0, HostID: 0, Size: 1}, {ContainerID: 1, HostID: 1, Size: 65536}},
 | 
						|
			},
 | 
						|
			expectedUID: 0,
 | 
						|
			expectedGID: 0,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, test := range tests {
 | 
						|
		options, uid, gid, err := getRootlessKeepIDMapping(test.uid, test.gid, test.uids, test.gids)
 | 
						|
		assert.Nil(t, err)
 | 
						|
		assert.Equal(t, test.expectedOptions, options)
 | 
						|
		assert.Equal(t, test.expectedUID, uid)
 | 
						|
		assert.Equal(t, test.expectedGID, gid)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func getDefaultMountOptionsNoStat(path string) (defaultMountOptions, error) {
 | 
						|
	return defaultMountOptions{false, true, true}, nil
 | 
						|
}
 | 
						|
 | 
						|
func TestProcessOptions(t *testing.T) {
 | 
						|
	tests := []struct {
 | 
						|
		name       string
 | 
						|
		options    []string
 | 
						|
		isTmpfs    bool
 | 
						|
		sourcePath string
 | 
						|
		expected   []string
 | 
						|
		expectErr  bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name:       "tmpfs",
 | 
						|
			options:    []string{"rw", "size=512m"},
 | 
						|
			isTmpfs:    true,
 | 
						|
			sourcePath: "",
 | 
						|
			expected:   []string{"nodev", "nosuid", "rprivate", "rw", "size=512m", "tmpcopyup"},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "duplicate idmap option",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"idmap", "idmap"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "mode allowed only with tmpfs",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"rw", "rbind", "mode=0123"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "noswap allowed only with tmpfs",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"noswap"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "tmpcopyup allowed only with tmpfs",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"tmpcopyup"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "notmpcopyup allowed only with tmpfs",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"notmpcopyup"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "z not allowed with tmpfs",
 | 
						|
			isTmpfs:    true,
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"z"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "size allowed only with tmpfs",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"size=123456"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "conflicting option dev/nodev",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"dev", "nodev"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "conflicting option suid/nosuid",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"suid", "nosuid"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "conflicting option exec/noexec",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"noexec", "exec"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "conflicting option ro/rw",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"ro", "rw"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "conflicting option bind/rbind",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"bind", "rbind"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "conflicting option bind/rbind",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"bind", "rbind"},
 | 
						|
			expectErr:  true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "default bind mount",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			expected:   []string{"nodev", "nosuid", "rbind", "rprivate", "rw"},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:       "default bind mount with bind",
 | 
						|
			sourcePath: "/path/to/source",
 | 
						|
			options:    []string{"bind"},
 | 
						|
			expected:   []string{"nodev", "nosuid", "bind", "private", "rw"},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		t.Run(tt.name, func(t *testing.T) {
 | 
						|
			opts, err := processOptionsInternal(tt.options, tt.isTmpfs, tt.sourcePath, getDefaultMountOptionsNoStat)
 | 
						|
			if tt.expectErr {
 | 
						|
				assert.NotNil(t, err)
 | 
						|
			} else {
 | 
						|
				assert.Nil(t, err)
 | 
						|
				sort.Strings(opts)
 | 
						|
				sort.Strings(tt.expected)
 | 
						|
				assert.Equal(t, opts, tt.expected)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |