272 lines
7.6 KiB
Go
272 lines
7.6 KiB
Go
package storage
|
|
|
|
import (
|
|
"errors"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/containers/storage/pkg/homedir"
|
|
"github.com/containers/storage/pkg/system"
|
|
"gotest.tools/assert"
|
|
)
|
|
|
|
type homeRuntimeData struct {
|
|
dir string
|
|
error error
|
|
}
|
|
|
|
type rootlessRuntimeDirEnvironmentTest struct {
|
|
homeRuntime homeRuntimeData
|
|
procCommandFile string
|
|
runUserDir string
|
|
tmpPerUserDir string
|
|
homeDir string
|
|
result string
|
|
}
|
|
|
|
func (env rootlessRuntimeDirEnvironmentTest) getProcCommandFile() string {
|
|
return env.procCommandFile
|
|
}
|
|
func (env rootlessRuntimeDirEnvironmentTest) getRunUserDir() string {
|
|
return env.runUserDir
|
|
}
|
|
func (env rootlessRuntimeDirEnvironmentTest) getTmpPerUserDir() string {
|
|
return env.tmpPerUserDir
|
|
}
|
|
func (env rootlessRuntimeDirEnvironmentTest) homeDirGetRuntimeDir() (string, error) {
|
|
return env.homeRuntime.dir, env.homeRuntime.error
|
|
}
|
|
func (env rootlessRuntimeDirEnvironmentTest) systemLstat(path string) (*system.StatT, error) {
|
|
return system.Lstat(path)
|
|
}
|
|
func (env rootlessRuntimeDirEnvironmentTest) homedirGet() string {
|
|
return env.homeDir
|
|
}
|
|
|
|
func TestRootlessRuntimeDir(t *testing.T) {
|
|
testDir, err := ioutil.TempDir("", "rootless-runtime-dir-test")
|
|
assert.NilError(t, err)
|
|
defer os.Remove(testDir)
|
|
|
|
homeRuntimeDir := filepath.Join(testDir, "home-rundir")
|
|
err = os.Mkdir(homeRuntimeDir, 0700)
|
|
assert.NilError(t, err)
|
|
|
|
homeRuntimeDisabled := homeRuntimeData{error: errors.New("homedirGetRuntimeDir is disabled")}
|
|
|
|
systemdCommandFile := filepath.Join(testDir, "systemd-command")
|
|
err = ioutil.WriteFile(systemdCommandFile, []byte("systemd"), 0644)
|
|
assert.NilError(t, err)
|
|
|
|
initCommandFile := filepath.Join(testDir, "init-command")
|
|
err = ioutil.WriteFile(initCommandFile, []byte("init"), 0644)
|
|
assert.NilError(t, err)
|
|
|
|
dirForOwner := filepath.Join(testDir, "dir-for-owner")
|
|
err = os.Mkdir(dirForOwner, 0700)
|
|
assert.NilError(t, err)
|
|
|
|
dirForAll := filepath.Join(testDir, "dir-for-all")
|
|
err = os.Mkdir(dirForAll, 0777)
|
|
assert.NilError(t, err)
|
|
|
|
dirToBeCreated := filepath.Join(testDir, "dir-to-be-created")
|
|
|
|
envs := []rootlessRuntimeDirEnvironmentTest{
|
|
{
|
|
homeRuntime: homeRuntimeData{dir: homeRuntimeDir},
|
|
result: homeRuntimeDir,
|
|
},
|
|
|
|
// Reading proc command file fails
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: "",
|
|
runUserDir: dirForOwner,
|
|
result: dirForOwner,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: "",
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: dirForOwner,
|
|
result: dirForOwner,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: "",
|
|
runUserDir: dirForAll,
|
|
tmpPerUserDir: dirForOwner,
|
|
result: dirForOwner,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: "",
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: dirToBeCreated,
|
|
result: dirToBeCreated,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: "",
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: "", // Accessing tmp per user dir fails
|
|
homeDir: dirForOwner,
|
|
result: filepath.Join(dirForOwner, "rundir"),
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: "",
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: dirForAll,
|
|
homeDir: dirForOwner,
|
|
result: filepath.Join(dirForOwner, "rundir"),
|
|
},
|
|
|
|
// systemd
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: systemdCommandFile,
|
|
runUserDir: dirForOwner,
|
|
result: dirForOwner,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: systemdCommandFile,
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: dirForOwner,
|
|
result: dirForOwner,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: systemdCommandFile,
|
|
runUserDir: dirForAll,
|
|
tmpPerUserDir: dirForOwner,
|
|
result: dirForOwner,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: systemdCommandFile,
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: dirToBeCreated,
|
|
result: dirToBeCreated,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: systemdCommandFile,
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: "", // Accessing tmp per user dir fails
|
|
homeDir: dirForOwner,
|
|
result: filepath.Join(dirForOwner, "rundir"),
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: systemdCommandFile,
|
|
runUserDir: "", // Accessing run user dir fails
|
|
tmpPerUserDir: dirForAll,
|
|
homeDir: dirForOwner,
|
|
result: filepath.Join(dirForOwner, "rundir"),
|
|
},
|
|
|
|
// init
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: initCommandFile,
|
|
tmpPerUserDir: dirForOwner,
|
|
result: dirForOwner,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: initCommandFile,
|
|
tmpPerUserDir: dirToBeCreated,
|
|
result: dirToBeCreated,
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: initCommandFile,
|
|
tmpPerUserDir: "", // Accessing tmp per user dir fails
|
|
homeDir: dirForOwner,
|
|
result: filepath.Join(dirForOwner, "rundir"),
|
|
},
|
|
{
|
|
homeRuntime: homeRuntimeDisabled,
|
|
procCommandFile: initCommandFile,
|
|
tmpPerUserDir: dirForAll,
|
|
homeDir: dirForOwner,
|
|
result: filepath.Join(dirForOwner, "rundir"),
|
|
},
|
|
}
|
|
|
|
for _, env := range envs {
|
|
os.Remove(dirToBeCreated)
|
|
|
|
resultDir, err := getRootlessRuntimeDirIsolated(env)
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, resultDir == env.result)
|
|
}
|
|
}
|
|
|
|
type rootlessRuntimeDirEnvironmentRace struct {
|
|
procCommandFile string
|
|
tmpPerUserDir string
|
|
}
|
|
|
|
func (env rootlessRuntimeDirEnvironmentRace) getProcCommandFile() string {
|
|
return env.procCommandFile
|
|
}
|
|
func (rootlessRuntimeDirEnvironmentRace) getRunUserDir() string {
|
|
return ""
|
|
}
|
|
func (env rootlessRuntimeDirEnvironmentRace) getTmpPerUserDir() string {
|
|
return env.tmpPerUserDir
|
|
}
|
|
func (rootlessRuntimeDirEnvironmentRace) homeDirGetRuntimeDir() (string, error) {
|
|
return "", errors.New("homedirGetRuntimeDir is disabled")
|
|
}
|
|
func (env rootlessRuntimeDirEnvironmentRace) systemLstat(path string) (*system.StatT, error) {
|
|
if path == env.tmpPerUserDir {
|
|
st, err := system.Lstat(path)
|
|
// We can simulate that race directory was created immediately after system.Lstat call.
|
|
if err := os.Mkdir(path, 0700); err != nil {
|
|
return nil, err
|
|
}
|
|
return st, err
|
|
}
|
|
return system.Lstat(path)
|
|
}
|
|
func (rootlessRuntimeDirEnvironmentRace) homedirGet() string {
|
|
return homedir.Get()
|
|
}
|
|
|
|
func TestRootlessRuntimeDirRace(t *testing.T) {
|
|
raceDir, err := ioutil.TempDir("", "rootless-runtime-dir-race-test")
|
|
assert.NilError(t, err)
|
|
defer os.Remove(raceDir)
|
|
|
|
procCommandFile := filepath.Join(raceDir, "command")
|
|
err = ioutil.WriteFile(procCommandFile, []byte("init"), 0644)
|
|
assert.NilError(t, err)
|
|
|
|
tmpPerUserDir := filepath.Join(raceDir, "tmp")
|
|
|
|
resultDir, err := getRootlessRuntimeDirIsolated(rootlessRuntimeDirEnvironmentRace{
|
|
procCommandFile,
|
|
tmpPerUserDir,
|
|
})
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, resultDir != tmpPerUserDir, "Rootless runtime dir shouldn't follow race dir.")
|
|
}
|
|
|
|
func TestDefaultStoreOpts(t *testing.T) {
|
|
storageOpts, err := defaultStoreOptionsIsolated(true, 1000, "./storage_test.conf")
|
|
|
|
expectedPath := filepath.Join(os.Getenv("NAME"), "1000", "containers/storage")
|
|
|
|
assert.NilError(t, err)
|
|
assert.Equal(t, storageOpts.RunRoot, expectedPath)
|
|
assert.Equal(t, storageOpts.GraphRoot, expectedPath)
|
|
assert.Equal(t, storageOpts.RootlessStoragePath, expectedPath)
|
|
}
|