1
+ package embedfs
2
+
3
+ import (
4
+ "io"
5
+ "testing"
6
+
7
+ "github.com/go-git/go-billy/v6"
8
+ "github.com/go-git/go-billy/v6/embedfs_testdata"
9
+ "github.com/stretchr/testify/assert"
10
+ "github.com/stretchr/testify/require"
11
+ )
12
+
13
+ func TestChroot_Basic (t * testing.T ) {
14
+ t .Parallel ()
15
+
16
+ fs := New (embedfs_testdata .GetTestData ())
17
+
18
+ // Test chroot to existing directory
19
+ chrootFS , err := fs .Chroot ("testdata" )
20
+ require .NoError (t , err )
21
+ require .NotNil (t , chrootFS )
22
+
23
+ // Test that we can access files in the chrooted filesystem
24
+ f , err := chrootFS .Open ("file1.txt" )
25
+ require .NoError (t , err )
26
+ defer f .Close ()
27
+
28
+ content , err := io .ReadAll (f )
29
+ require .NoError (t , err )
30
+ assert .Equal (t , "Hello from embedfs!" , string (content ))
31
+ }
32
+
33
+ func TestChroot_NestedDirectory (t * testing.T ) {
34
+ t .Parallel ()
35
+
36
+ fs := New (embedfs_testdata .GetTestData ())
37
+
38
+ // Test chroot to nested directory
39
+ chrootFS , err := fs .Chroot ("testdata/subdir" )
40
+ require .NoError (t , err )
41
+ require .NotNil (t , chrootFS )
42
+
43
+ // Test that we can access nested files from the chrooted root
44
+ f , err := chrootFS .Open ("nested.txt" )
45
+ require .NoError (t , err )
46
+ defer f .Close ()
47
+
48
+ content , err := io .ReadAll (f )
49
+ require .NoError (t , err )
50
+ assert .Equal (t , "Nested file content" , string (content ))
51
+ }
52
+
53
+ func TestChroot_StatInChroot (t * testing.T ) {
54
+ t .Parallel ()
55
+
56
+ fs := New (embedfs_testdata .GetTestData ())
57
+
58
+ chrootFS , err := fs .Chroot ("testdata" )
59
+ require .NoError (t , err )
60
+
61
+ // Test stat on files that exist in chrooted directory
62
+ fi , err := chrootFS .Stat ("file1.txt" )
63
+ require .NoError (t , err )
64
+ assert .Equal (t , "file1.txt" , fi .Name ())
65
+ assert .False (t , fi .IsDir ())
66
+
67
+ // Test stat on directories that exist in chrooted directory
68
+ fi , err = chrootFS .Stat ("subdir" )
69
+ require .NoError (t , err )
70
+ assert .Equal (t , "subdir" , fi .Name ())
71
+ assert .True (t , fi .IsDir ())
72
+
73
+ // Test stat with absolute path in chrooted filesystem
74
+ fi , err = chrootFS .Stat ("/file2.txt" )
75
+ require .NoError (t , err )
76
+ assert .Equal (t , "file2.txt" , fi .Name ())
77
+ assert .False (t , fi .IsDir ())
78
+ }
79
+
80
+ func TestChroot_ReadDirInChroot (t * testing.T ) {
81
+ t .Parallel ()
82
+
83
+ fs := New (embedfs_testdata .GetTestData ())
84
+
85
+ chrootFS , err := fs .Chroot ("testdata" )
86
+ require .NoError (t , err )
87
+
88
+ // Test reading directory contents from chrooted root
89
+ entries , err := chrootFS .ReadDir ("/" )
90
+ require .NoError (t , err )
91
+
92
+ expectedFiles := []string {"empty.txt" , "file1.txt" , "file2.txt" , "subdir" }
93
+ assert .Len (t , entries , len (expectedFiles ))
94
+
95
+ foundFiles := make (map [string ]bool )
96
+ for _ , entry := range entries {
97
+ foundFiles [entry .Name ()] = true
98
+ }
99
+
100
+ for _ , expected := range expectedFiles {
101
+ assert .True (t , foundFiles [expected ], "Expected file %s not found" , expected )
102
+ }
103
+
104
+ // Test reading subdirectory from chrooted filesystem
105
+ entries , err = chrootFS .ReadDir ("subdir" )
106
+ require .NoError (t , err )
107
+ assert .Len (t , entries , 1 )
108
+ assert .Equal (t , "nested.txt" , entries [0 ].Name ())
109
+ }
110
+
111
+ func TestChroot_PathNormalization (t * testing.T ) {
112
+ t .Parallel ()
113
+
114
+ fs := New (embedfs_testdata .GetTestData ())
115
+
116
+ // Test chroot with different path formats
117
+ tests := []struct {
118
+ name string
119
+ chrootPath string
120
+ openPath string
121
+ expectFile string
122
+ }{
123
+ {
124
+ name : "absolute chroot path" ,
125
+ chrootPath : "/testdata" ,
126
+ openPath : "file1.txt" ,
127
+ expectFile : "file1.txt" ,
128
+ },
129
+ {
130
+ name : "relative chroot path" ,
131
+ chrootPath : "testdata" ,
132
+ openPath : "file1.txt" ,
133
+ expectFile : "file1.txt" ,
134
+ },
135
+ {
136
+ name : "absolute open path in chroot" ,
137
+ chrootPath : "testdata" ,
138
+ openPath : "/file1.txt" ,
139
+ expectFile : "file1.txt" ,
140
+ },
141
+ {
142
+ name : "nested chroot" ,
143
+ chrootPath : "testdata/subdir" ,
144
+ openPath : "nested.txt" ,
145
+ expectFile : "nested.txt" ,
146
+ },
147
+ }
148
+
149
+ for _ , tt := range tests {
150
+ t .Run (tt .name , func (t * testing.T ) {
151
+ chrootFS , err := fs .Chroot (tt .chrootPath )
152
+ require .NoError (t , err )
153
+
154
+ f , err := chrootFS .Open (tt .openPath )
155
+ require .NoError (t , err )
156
+ defer f .Close ()
157
+
158
+ assert .Equal (t , tt .expectFile , f .Name ())
159
+ })
160
+ }
161
+ }
162
+
163
+ func TestChroot_NonExistentPath (t * testing.T ) {
164
+ t .Parallel ()
165
+
166
+ fs := New (embedfs_testdata .GetTestData ())
167
+
168
+ // Test chroot to non-existent directory - billy's chroot helper allows this
169
+ chrootFS , err := fs .Chroot ("nonexistent" )
170
+ require .NoError (t , err )
171
+ require .NotNil (t , chrootFS )
172
+
173
+ // But accessing files within the non-existent chroot should fail
174
+ _ , err = chrootFS .Open ("anyfile.txt" )
175
+ assert .Error (t , err )
176
+ }
177
+
178
+ func TestChroot_Join (t * testing.T ) {
179
+ t .Parallel ()
180
+
181
+ fs := New (embedfs_testdata .GetTestData ())
182
+ chrootFS , err := fs .Chroot ("testdata" )
183
+ require .NoError (t , err )
184
+
185
+ // Test Join operation in chrooted filesystem
186
+ joined := chrootFS .Join ("subdir" , "nested.txt" )
187
+ assert .Equal (t , "subdir/nested.txt" , joined )
188
+
189
+ // Test that joined path can be used to open file
190
+ f , err := chrootFS .Open (joined )
191
+ require .NoError (t , err )
192
+ defer f .Close ()
193
+
194
+ content , err := io .ReadAll (f )
195
+ require .NoError (t , err )
196
+ assert .Equal (t , "Nested file content" , string (content ))
197
+ }
198
+
199
+ func TestChroot_UnsupportedOperations (t * testing.T ) {
200
+ t .Parallel ()
201
+
202
+ fs := New (embedfs_testdata .GetTestData ())
203
+ chrootFS , err := fs .Chroot ("testdata" )
204
+ require .NoError (t , err )
205
+
206
+ // Test that write operations still fail in chrooted embedfs
207
+ _ , err = chrootFS .Create ("newfile.txt" )
208
+ require .ErrorIs (t , err , billy .ErrReadOnly )
209
+
210
+ err = chrootFS .Remove ("file1.txt" )
211
+ require .ErrorIs (t , err , billy .ErrReadOnly )
212
+
213
+ err = chrootFS .Rename ("file1.txt" , "renamed.txt" )
214
+ require .ErrorIs (t , err , billy .ErrReadOnly )
215
+
216
+ err = chrootFS .MkdirAll ("newdir" , 0755 )
217
+ require .ErrorIs (t , err , billy .ErrReadOnly )
218
+ }
219
+
220
+ func TestChroot_NestedChroot (t * testing.T ) {
221
+ t .Parallel ()
222
+
223
+ fs := New (embedfs_testdata .GetTestData ())
224
+
225
+ // Test creating nested chrootfs
226
+ firstChroot , err := fs .Chroot ("testdata" )
227
+ require .NoError (t , err )
228
+
229
+ secondChroot , err := firstChroot .Chroot ("subdir" )
230
+ require .NoError (t , err )
231
+
232
+ // Test that nested chroot works correctly
233
+ f , err := secondChroot .Open ("nested.txt" )
234
+ require .NoError (t , err )
235
+ defer f .Close ()
236
+
237
+ content , err := io .ReadAll (f )
238
+ require .NoError (t , err )
239
+ assert .Equal (t , "Nested file content" , string (content ))
240
+
241
+ // Test that we can't access parent directory from nested chroot
242
+ entries , err := secondChroot .ReadDir ("/" )
243
+ require .NoError (t , err )
244
+ assert .Len (t , entries , 1 )
245
+ assert .Equal (t , "nested.txt" , entries [0 ].Name ())
246
+ }
247
+
248
+ func TestChroot_FileOperations (t * testing.T ) {
249
+ t .Parallel ()
250
+
251
+ fs := New (embedfs_testdata .GetTestData ())
252
+ chrootFS , err := fs .Chroot ("testdata" )
253
+ require .NoError (t , err )
254
+
255
+ // Test file operations in chrooted filesystem
256
+ f , err := chrootFS .Open ("file2.txt" )
257
+ require .NoError (t , err )
258
+ defer f .Close ()
259
+
260
+ // Test Read
261
+ buf := make ([]byte , 10 )
262
+ n , err := f .Read (buf )
263
+ require .NoError (t , err )
264
+ assert .Equal (t , "Another te" , string (buf [:n ]))
265
+
266
+ // Test Seek
267
+ _ , err = f .Seek (0 , io .SeekStart )
268
+ require .NoError (t , err )
269
+
270
+ // Test ReadAt
271
+ buf2 := make ([]byte , 7 )
272
+ n , err = f .ReadAt (buf2 , 8 )
273
+ require .NoError (t , err )
274
+ assert .Equal (t , "test fi" , string (buf2 [:n ]))
275
+
276
+ // Test that file position wasn't affected by ReadAt
277
+ n , err = f .Read (buf )
278
+ require .NoError (t , err )
279
+ assert .Equal (t , "Another te" , string (buf [:n ]))
280
+ }
281
+
282
+ func TestChroot_Lstat (t * testing.T ) {
283
+ t .Parallel ()
284
+
285
+ fs := New (embedfs_testdata .GetTestData ())
286
+ chrootFS , err := fs .Chroot ("testdata" )
287
+ require .NoError (t , err )
288
+
289
+ // Test Lstat in chrooted filesystem (should behave same as Stat for embedfs)
290
+ fi , err := chrootFS .Lstat ("file1.txt" )
291
+ require .NoError (t , err )
292
+ assert .Equal (t , "file1.txt" , fi .Name ())
293
+ assert .False (t , fi .IsDir ())
294
+ }
0 commit comments