// 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) }) }