Merge pull request #128429 from liyuerich/volumepathhandler

add UT for volumepathhandler
This commit is contained in:
Kubernetes Prow Robot
2025-07-07 08:41:25 -07:00
committed by GitHub
2 changed files with 291 additions and 4 deletions

View File

@@ -103,12 +103,12 @@ func (v VolumePathHandler) MapDevice(devicePath string, mapPath string, linkName
}
if bindMount {
return mapBindMountDevice(v, devicePath, mapPath, linkName)
return mapBindMountDevice(devicePath, mapPath, linkName)
}
return mapSymlinkDevice(v, devicePath, mapPath, linkName)
return mapSymlinkDevice(devicePath, mapPath, linkName)
}
func mapBindMountDevice(v VolumePathHandler, devicePath string, mapPath string, linkName string) error {
func mapBindMountDevice(devicePath string, mapPath string, linkName string) error {
// Check bind mount exists
linkPath := filepath.Join(mapPath, string(linkName))
@@ -146,7 +146,7 @@ func mapBindMountDevice(v VolumePathHandler, devicePath string, mapPath string,
return nil
}
func mapSymlinkDevice(v VolumePathHandler, devicePath string, mapPath string, linkName string) error {
func mapSymlinkDevice(devicePath string, mapPath string, linkName string) error {
// Remove old symbolic link(or file) then create new one.
// This should be done because current symbolic link is
// stale across node reboot.

View File

@@ -0,0 +1,287 @@
/*
Copyright 2025 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package volumepathhandler
import (
"os"
"path/filepath"
"testing"
)
func TestMapDevice(t *testing.T) {
tempDir := t.TempDir()
testCases := []struct {
name string
devicePath string
mapPath string
linkName string
bindMount bool
expectError string
}{
{
name: "valid symlink map",
devicePath: "/dev/fakeDevice",
mapPath: filepath.Join(tempDir, "test-map-valid"),
linkName: "validLink",
bindMount: false,
expectError: "",
},
{
name: "empty device path",
devicePath: "",
mapPath: filepath.Join(tempDir, "test-map-empty-device"),
linkName: "emptyDeviceLink",
bindMount: false,
expectError: "failed to map device to map path. devicePath is empty",
},
{
name: "empty map path",
devicePath: "/dev/fakeDevice",
mapPath: "",
linkName: "emptyMapLink",
bindMount: false,
expectError: "failed to map device to map path. mapPath is empty",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if tc.mapPath != "" {
if err := os.MkdirAll(tc.mapPath, 0750); err != nil {
t.Fatalf("failed to create mapPath: %v", err)
}
}
handler := VolumePathHandler{}
err := handler.MapDevice(tc.devicePath, tc.mapPath, tc.linkName, tc.bindMount)
if tc.expectError != "" {
if err == nil || err.Error() != tc.expectError {
t.Fatalf("expected error: %v, got: %v", tc.expectError, err)
}
} else {
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
linkPath := filepath.Join(tc.mapPath, tc.linkName)
if _, err := os.Lstat(linkPath); os.IsNotExist(err) {
t.Fatalf("expected symlink to exist, got error: %v", err)
}
}
})
}
}
func TestUnmapDevice(t *testing.T) {
tempDir := t.TempDir()
testCases := []struct {
name string
mapPath string
linkName string
bindMount bool
setup func(string, string)
expectError string
}{
{
name: "valid symlink unmap",
mapPath: filepath.Join(tempDir, "test-unmap-valid"),
linkName: "validLink",
bindMount: false,
setup: func(mapPath, linkName string) {
if err := os.MkdirAll(mapPath, 0750); err != nil {
t.Fatalf("failed to create mapPath in setup: %v", err)
}
if err := os.Symlink("/dev/fakeDevice", filepath.Join(mapPath, linkName)); err != nil {
t.Fatalf("failed to create symlink in setup: %v", err)
}
},
expectError: "",
},
{
name: "symlink does not exist",
mapPath: filepath.Join(tempDir, "test-unmap-nonexistent"),
linkName: "nonexistentLink",
bindMount: false,
setup: func(mapPath, linkName string) {
if err := os.MkdirAll(mapPath, 0750); err != nil {
t.Fatalf("failed to create mapPath in setup: %v", err)
}
},
expectError: "",
},
{
name: "bind mount file exists but not mounted",
mapPath: filepath.Join(tempDir, "test-unmap-bind-file-exists"),
linkName: "bindFile",
bindMount: true,
setup: func(mapPath, linkName string) {
if err := os.MkdirAll(mapPath, 0750); err != nil {
t.Fatalf("failed to create mapPath in setup: %v", err)
}
linkPath := filepath.Join(mapPath, linkName)
f, err := os.OpenFile(linkPath, os.O_CREATE|os.O_RDWR, 0750)
if err != nil {
t.Fatalf("failed to create file in setup: %v", err)
}
if err := f.Close(); err != nil {
t.Fatalf("failed to close file in setup: %v", err)
}
},
expectError: "",
},
{
name: "bind mount file does not exist",
mapPath: filepath.Join(tempDir, "test-unmap-bind-file-not-exist"),
linkName: "bindFileNotExist",
bindMount: true,
setup: func(mapPath, linkName string) {
if err := os.MkdirAll(mapPath, 0750); err != nil {
t.Fatalf("failed to create mapPath in setup: %v", err)
}
// Do not create file
},
expectError: "",
},
{
name: "empty mapPath for symlink",
mapPath: "",
linkName: "someLink",
bindMount: false,
setup: func(mapPath, linkName string) {},
expectError: "failed to unmap device from map path. mapPath is empty",
},
{
name: "empty mapPath for bind mount",
mapPath: "",
linkName: "someBindFile",
bindMount: true,
setup: func(mapPath, linkName string) {},
expectError: "failed to unmap device from map path. mapPath is empty",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
handler := VolumePathHandler{}
if tc.setup != nil {
tc.setup(tc.mapPath, tc.linkName)
}
err := handler.UnmapDevice(tc.mapPath, tc.linkName, tc.bindMount)
if tc.expectError != "" {
if err == nil || err.Error() != tc.expectError {
t.Fatalf("expected error: %v, got: %v", tc.expectError, err)
}
} else {
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
linkPath := filepath.Join(tc.mapPath, tc.linkName)
if _, err := os.Lstat(linkPath); !os.IsNotExist(err) {
t.Fatalf("expected symlink to be removed, got error: %v", err)
}
}
})
}
}
func TestRemoveMapPath(t *testing.T) {
tempDir := t.TempDir()
mapPath := filepath.Join(tempDir, "test-remove-map-path")
if err := os.MkdirAll(mapPath, 0755); err != nil {
t.Fatalf("failed to create map path: %v", err)
}
testCases := []struct {
name string
mapPath string
expectError string
}{
{
name: "Remove Existing Map Path",
mapPath: mapPath,
expectError: "",
},
{
name: "Remove Non-existing Map Path",
mapPath: filepath.Join(tempDir, "non-existing-path"),
expectError: "",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
handler := VolumePathHandler{}
err := handler.RemoveMapPath(tc.mapPath)
if tc.expectError != "" {
if err == nil || err.Error() != tc.expectError {
t.Fatalf("expected error: %v, got: %v", tc.expectError, err)
}
} else {
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
if _, err := os.Stat(tc.mapPath); !os.IsNotExist(err) {
t.Fatalf("expected map path to be deleted, got error: %v", err)
}
}
})
}
}
func TestIsSymlinkExist(t *testing.T) {
tempDir := t.TempDir()
mapPath := filepath.Join(tempDir, "test-symlink")
linkName := "test-symlink-link"
if err := os.MkdirAll(mapPath, 0755); err != nil {
t.Fatalf("failed to create test directory: %v", err)
}
if err := os.Symlink("/dev/fakeDevice", filepath.Join(mapPath, linkName)); err != nil {
t.Fatalf("failed to create symlink: %v", err)
}
testCases := []struct {
name string
mapPath string
expectedExists bool
}{
{
name: "Check Existing Symlink",
mapPath: filepath.Join(mapPath, linkName),
expectedExists: true,
},
{
name: "Check Non-existing Symlink",
mapPath: filepath.Join(mapPath, "non-existing-symlink"),
expectedExists: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
exists, err := VolumePathHandler{}.IsSymlinkExist(tc.mapPath)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}
if exists != tc.expectedExists {
t.Fatalf("expected symlink existence to be: %v, got: %v", tc.expectedExists, exists)
}
})
}
}