1
16
17 package hostutil
18
19 import (
20 "errors"
21 "fmt"
22 "net"
23 "os"
24 "path/filepath"
25 goruntime "runtime"
26 "strings"
27 "testing"
28
29 "github.com/stretchr/testify/assert"
30 "k8s.io/mount-utils"
31 "k8s.io/utils/exec"
32 )
33
34
35 type fakeMounter struct {
36 mount.FakeMounter
37 mountRefs []string
38 raiseError bool
39 }
40
41
42
43 func (f *fakeMounter) GetMountRefs(pathname string) ([]string, error) {
44 if f.raiseError {
45 return nil, errors.New("Expected error.")
46 }
47
48 return f.mountRefs, nil
49 }
50
51 func TestDeviceNameFromMount(t *testing.T) {
52 hu := NewHostUtil()
53 path := "/tmp/foo"
54 if goruntime.GOOS == "windows" {
55 path = "C:" + path
56 }
57
58 testCases := map[string]struct {
59 mountRefs []string
60 expectedPath string
61 raiseError bool
62 expectedError string
63 }{
64 "GetMountRefs error": {
65 raiseError: true,
66 expectedError: "Expected error.",
67 },
68 "No Refs error": {
69 expectedError: fmt.Sprintf("directory %s is not mounted", path),
70 },
71 "No Matching refs": {
72 mountRefs: []string{filepath.Join("foo", "lish")},
73 expectedPath: filepath.Base(path),
74 },
75 "Matched ref": {
76 mountRefs: []string{filepath.Join(path, "lish")},
77 expectedPath: "lish",
78 },
79 }
80
81 for name, tc := range testCases {
82 t.Run(name, func(t *testing.T) {
83 mounter := &fakeMounter{
84 mountRefs: tc.mountRefs,
85 raiseError: tc.raiseError,
86 }
87
88 path, err := hu.GetDeviceNameFromMount(mounter, path, path)
89 if tc.expectedError != "" {
90 if err == nil || err.Error() != tc.expectedError {
91 t.Fatalf("expected error message `%s` but got `%v`", tc.expectedError, err)
92 }
93 return
94 }
95
96 expectedPath := filepath.FromSlash(tc.expectedPath)
97 assert.Equal(t, expectedPath, path)
98 })
99 }
100 }
101
102 func createSocketFile(socketDir string) (string, error) {
103 testSocketFile := filepath.Join(socketDir, "mt.sock")
104
105
106
107
108 oldDir, _ := os.Getwd()
109
110 err := os.Chdir(socketDir)
111 if err != nil {
112 return "", err
113 }
114 defer func() {
115 os.Chdir(oldDir)
116 }()
117 _, socketCreateError := net.Listen("unix", "mt.sock")
118 return testSocketFile, socketCreateError
119 }
120
121 func TestGetFileType(t *testing.T) {
122 hu := NewHostUtil()
123
124 testCase := []struct {
125 name string
126 skipWindows bool
127 expectedType FileType
128 setUp func() (string, string, error)
129 }{
130 {
131 "Directory Test",
132 false,
133 FileTypeDirectory,
134 func() (string, string, error) {
135 tempDir, err := os.MkdirTemp("", "test-get-filetype-")
136 return tempDir, tempDir, err
137 },
138 },
139 {
140 "File Test",
141 false,
142 FileTypeFile,
143 func() (string, string, error) {
144 tempFile, err := os.CreateTemp("", "test-get-filetype")
145 if err != nil {
146 return "", "", err
147 }
148 tempFile.Close()
149 return tempFile.Name(), tempFile.Name(), nil
150 },
151 },
152 {
153 "Socket Test",
154 false,
155 FileTypeSocket,
156 func() (string, string, error) {
157 tempDir, err := os.MkdirTemp("", "test-get-filetype-")
158 if err != nil {
159 return "", "", err
160 }
161 tempSocketFile, err := createSocketFile(tempDir)
162 return tempSocketFile, tempDir, err
163 },
164 },
165 {
166 "Block Device Test",
167 true,
168 FileTypeBlockDev,
169 func() (string, string, error) {
170 tempDir, err := os.MkdirTemp("", "test-get-filetype-")
171 if err != nil {
172 return "", "", err
173 }
174
175 tempBlockFile := filepath.Join(tempDir, "test_blk_dev")
176 outputBytes, err := exec.New().Command("mknod", tempBlockFile, "b", "89", "1").CombinedOutput()
177 if err != nil {
178 err = fmt.Errorf("%v: %s ", err, outputBytes)
179 }
180 return tempBlockFile, tempDir, err
181 },
182 },
183 {
184 "Character Device Test",
185 true,
186 FileTypeCharDev,
187 func() (string, string, error) {
188 tempDir, err := os.MkdirTemp("", "test-get-filetype-")
189 if err != nil {
190 return "", "", err
191 }
192
193 tempCharFile := filepath.Join(tempDir, "test_char_dev")
194 outputBytes, err := exec.New().Command("mknod", tempCharFile, "c", "89", "1").CombinedOutput()
195 if err != nil {
196 err = fmt.Errorf("%v: %s ", err, outputBytes)
197 }
198 return tempCharFile, tempDir, err
199 },
200 },
201 }
202
203 for idx, tc := range testCase {
204 if goruntime.GOOS == "windows" && tc.skipWindows {
205 continue
206 }
207 path, cleanUpPath, err := tc.setUp()
208 defer os.RemoveAll(cleanUpPath)
209 if err != nil {
210
211
212 if isOperationNotPermittedError(err) {
213 continue
214 }
215 t.Fatalf("[%d-%s] unexpected error : %v", idx, tc.name, err)
216 }
217
218 fileType, err := hu.GetFileType(path)
219 if err != nil {
220 t.Fatalf("[%d-%s] unexpected error : %v", idx, tc.name, err)
221 }
222 if fileType != tc.expectedType {
223 t.Fatalf("[%d-%s] expected %s, but got %s", idx, tc.name, tc.expectedType, fileType)
224 }
225 }
226 }
227
228 func isOperationNotPermittedError(err error) bool {
229 return strings.Contains(err.Error(), "Operation not permitted")
230 }
231
View as plain text