152 lines
4.1 KiB
Go
152 lines
4.1 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package filesystem
|
|
|
|
import (
|
|
"context"
|
|
"os/exec"
|
|
osuser "os/user"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
fsmodel "git.omukk.dev/wrenn/sandbox/envd/internal/shared/filesystem"
|
|
)
|
|
|
|
func TestIsPathOnNetworkMount(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Test with a regular directory (should not be on network mount)
|
|
tempDir := t.TempDir()
|
|
isNetwork, err := IsPathOnNetworkMount(tempDir)
|
|
require.NoError(t, err)
|
|
assert.False(t, isNetwork, "temp directory should not be on a network mount")
|
|
}
|
|
|
|
func TestIsPathOnNetworkMount_FuseMount(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Require bindfs to be available
|
|
_, err := exec.LookPath("bindfs")
|
|
require.NoError(t, err, "bindfs must be installed for this test")
|
|
|
|
// Require fusermount to be available (needed for unmounting)
|
|
_, err = exec.LookPath("fusermount")
|
|
require.NoError(t, err, "fusermount must be installed for this test")
|
|
|
|
// Create source and mount directories
|
|
sourceDir := t.TempDir()
|
|
mountDir := t.TempDir()
|
|
|
|
// Mount sourceDir onto mountDir using bindfs (FUSE)
|
|
ctx := context.Background()
|
|
cmd := exec.CommandContext(ctx, "bindfs", sourceDir, mountDir)
|
|
require.NoError(t, cmd.Run(), "failed to mount bindfs")
|
|
|
|
// Ensure we unmount on cleanup
|
|
t.Cleanup(func() {
|
|
_ = exec.CommandContext(context.Background(), "fusermount", "-u", mountDir).Run()
|
|
})
|
|
|
|
// Test that the FUSE mount is detected
|
|
isNetwork, err := IsPathOnNetworkMount(mountDir)
|
|
require.NoError(t, err)
|
|
assert.True(t, isNetwork, "FUSE mount should be detected as network filesystem")
|
|
|
|
// Test that the source directory is NOT detected as network mount
|
|
isNetworkSource, err := IsPathOnNetworkMount(sourceDir)
|
|
require.NoError(t, err)
|
|
assert.False(t, isNetworkSource, "source directory should not be detected as network filesystem")
|
|
}
|
|
|
|
func TestGetFileOwnership_CurrentUser(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("current user", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Get current user running the tests
|
|
cur, err := osuser.Current()
|
|
if err != nil {
|
|
t.Skipf("unable to determine current user: %v", err)
|
|
}
|
|
|
|
// Determine expected owner/group using the same lookup logic
|
|
expectedOwner := cur.Uid
|
|
if u, err := osuser.LookupId(cur.Uid); err == nil {
|
|
expectedOwner = u.Username
|
|
}
|
|
|
|
expectedGroup := cur.Gid
|
|
if g, err := osuser.LookupGroupId(cur.Gid); err == nil {
|
|
expectedGroup = g.Name
|
|
}
|
|
|
|
// Parse UID/GID strings to uint32 for EntryInfo
|
|
uid64, err := strconv.ParseUint(cur.Uid, 10, 32)
|
|
require.NoError(t, err)
|
|
gid64, err := strconv.ParseUint(cur.Gid, 10, 32)
|
|
require.NoError(t, err)
|
|
|
|
// Build a minimal EntryInfo with current UID/GID
|
|
info := fsmodel.EntryInfo{ // from shared pkg
|
|
UID: uint32(uid64),
|
|
GID: uint32(gid64),
|
|
}
|
|
|
|
owner, group := getFileOwnership(info)
|
|
assert.Equal(t, expectedOwner, owner)
|
|
assert.Equal(t, expectedGroup, group)
|
|
})
|
|
|
|
t.Run("no user", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Find a UID that does not exist on this system
|
|
var unknownUIDStr string
|
|
for i := 60001; i < 70000; i++ { // search a high range typically unused
|
|
idStr := strconv.Itoa(i)
|
|
if _, err := osuser.LookupId(idStr); err != nil {
|
|
unknownUIDStr = idStr
|
|
|
|
break
|
|
}
|
|
}
|
|
if unknownUIDStr == "" {
|
|
t.Skip("could not find a non-existent UID in the probed range")
|
|
}
|
|
|
|
// Find a GID that does not exist on this system
|
|
var unknownGIDStr string
|
|
for i := 60001; i < 70000; i++ { // search a high range typically unused
|
|
idStr := strconv.Itoa(i)
|
|
if _, err := osuser.LookupGroupId(idStr); err != nil {
|
|
unknownGIDStr = idStr
|
|
|
|
break
|
|
}
|
|
}
|
|
if unknownGIDStr == "" {
|
|
t.Skip("could not find a non-existent GID in the probed range")
|
|
}
|
|
|
|
// Parse to uint32 for EntryInfo construction
|
|
uid64, err := strconv.ParseUint(unknownUIDStr, 10, 32)
|
|
require.NoError(t, err)
|
|
gid64, err := strconv.ParseUint(unknownGIDStr, 10, 32)
|
|
require.NoError(t, err)
|
|
|
|
info := fsmodel.EntryInfo{
|
|
UID: uint32(uid64),
|
|
GID: uint32(gid64),
|
|
}
|
|
|
|
owner, group := getFileOwnership(info)
|
|
// Expect numeric fallbacks because lookups should fail for unknown IDs
|
|
assert.Equal(t, unknownUIDStr, owner)
|
|
assert.Equal(t, unknownGIDStr, group)
|
|
})
|
|
}
|