@@ -8,7 +8,11 @@ describe('Mounting', () => {
8
8
let php : PHP ;
9
9
10
10
beforeEach ( async ( ) => {
11
- php = new PHP ( await loadNodeRuntime ( RecommendedPHPVersion ) ) ;
11
+ php = new PHP (
12
+ await loadNodeRuntime ( RecommendedPHPVersion , {
13
+ followSymlinks : true ,
14
+ } )
15
+ ) ;
12
16
} ) ;
13
17
afterEach ( async ( ) => {
14
18
php . exit ( ) ;
@@ -21,25 +25,19 @@ describe('Mounting', () => {
21
25
'long-post-body.txt'
22
26
) ;
23
27
24
- const unmount = await php . mount (
28
+ await php . mount (
25
29
'/single-file.txt' ,
26
30
createNodeFsMountHandler ( testFilePath )
27
31
) ;
28
32
29
33
const vfsContent = await php . readFileAsText ( '/single-file.txt' ) ;
30
34
const localContent = fs . readFileSync ( testFilePath , 'utf8' ) ;
31
35
expect ( vfsContent ) . toEqual ( localContent ) ;
32
-
33
- await unmount ( ) ;
34
- expect ( php . isFile ( '/single-file.txt' ) ) . toBe ( false ) ;
35
36
} ) ;
36
37
37
38
it ( 'Should mount nested directories with recursive structure matching' , async ( ) => {
38
39
const testDataPath = path . join ( __dirname , 'test-data' ) ;
39
- const unmount = await php . mount (
40
- '/nested-test' ,
41
- createNodeFsMountHandler ( testDataPath )
42
- ) ;
40
+ await php . mount ( '/nested-test' , createNodeFsMountHandler ( testDataPath ) ) ;
43
41
44
42
// Recursively compare directory structure
45
43
const compareDirectories = ( vfsPath : string , localPath : string ) => {
@@ -79,160 +77,98 @@ describe('Mounting', () => {
79
77
const localContent = fs . readFileSync ( localNestedPath , 'utf8' ) ;
80
78
expect ( vfsContent ) . toEqual ( localContent ) ;
81
79
}
82
-
83
- await unmount ( ) ;
84
- expect ( php . isDir ( '/nested-test' ) ) . toBe ( false ) ;
85
80
} ) ;
86
81
87
- describe ( 'File types and system operations' , ( ) => {
88
- it ( 'Should handle all file types with comprehensive FS comparison' , async ( ) => {
89
- const testDataPath = path . join ( __dirname , 'test-data' ) ;
82
+ it ( 'Should mount a symlink' , async ( ) => {
83
+ const symlinkPath = path . join ( __dirname , 'test-data' , 'symlink.txt' ) ;
84
+ const symlinkTarget = path . join (
85
+ __dirname ,
86
+ 'test-data' ,
87
+ 'long-post-body.txt'
88
+ ) ;
89
+ const vfsMountPoint = '/symlink.txt' ;
90
+ try {
91
+ fs . symlinkSync ( symlinkTarget , symlinkPath , 'file' ) ;
92
+
90
93
await php . mount (
91
- '/comprehensive-test' ,
92
- createNodeFsMountHandler ( testDataPath )
94
+ vfsMountPoint ,
95
+ createNodeFsMountHandler ( symlinkPath )
93
96
) ;
94
97
95
- const localFiles = fs . readdirSync ( testDataPath ) ;
96
-
97
- for ( const file of localFiles ) {
98
- const localPath = path . join ( testDataPath , file ) ;
99
- const vfsPath = `/comprehensive-test/${ file } ` ;
100
- const localStat = fs . statSync ( localPath ) ;
101
-
102
- if ( localStat . isFile ( ) ) {
103
- // Test binary files (images)
104
- if ( file . endsWith ( '.jpg' ) || file . endsWith ( '.png' ) ) {
105
- const vfsBinary = await php . readFileAsBuffer ( vfsPath ) ;
106
- const localBinary = fs . readFileSync ( localPath ) ;
107
- expect ( Buffer . from ( vfsBinary ) ) . toEqual ( localBinary ) ;
108
- expect ( vfsBinary . length ) . toBe ( localStat . size ) ;
109
- }
110
- // Test text files (certificates, documents)
111
- else if ( file . endsWith ( '.txt' ) || file . endsWith ( '.pem' ) ) {
112
- const vfsText = await php . readFileAsText ( vfsPath ) ;
113
- const localText = fs . readFileSync ( localPath , 'utf8' ) ;
114
- expect ( vfsText ) . toEqual ( localText ) ;
115
- expect ( vfsText . length ) . toBe ( localStat . size ) ;
116
-
117
- // Special certificate validation
118
- if (
119
- file . endsWith ( '.pem' ) &&
120
- localText . includes ( '-----BEGIN CERTIFICATE-----' )
121
- ) {
122
- expect ( vfsText ) . toContain (
123
- '-----BEGIN CERTIFICATE-----'
124
- ) ;
125
- }
126
- }
127
-
128
- // Test stat operations
129
- const phpStat = await php . run ( {
130
- code : `<?php
131
- $stat = stat('/comprehensive-test/${ file } ');
132
- echo json_encode([
133
- 'size' => $stat['size'],
134
- 'mode' => $stat['mode'],
135
- 'mtime' => $stat['mtime'],
136
- 'is_file' => is_file('/comprehensive-test/${ file } '),
137
- 'is_readable' => is_readable('/comprehensive-test/${ file } '),
138
- 'filesize' => filesize('/comprehensive-test/${ file } ')
139
- ]);
140
- ` ,
141
- } ) ;
142
-
143
- const vfsStatResult = JSON . parse ( phpStat . text ) ;
144
- expect ( vfsStatResult . size ) . toBe ( localStat . size ) ;
145
- expect ( vfsStatResult . mtime ) . toBe (
146
- Math . floor ( localStat . mtime . getTime ( ) / 1000 )
147
- ) ;
148
- expect ( vfsStatResult . is_file ) . toBe ( true ) ;
149
- expect ( vfsStatResult . is_readable ) . toBe ( true ) ;
150
- expect ( vfsStatResult . filesize ) . toBe ( localStat . size ) ;
151
- }
152
- }
153
-
154
- // Test directory listing through PHP
155
- const phpListing = await php . run ( {
156
- code : `<?php
157
- $files = scandir('/comprehensive-test');
158
- echo json_encode(array_filter($files, function($file) {
159
- return !in_array($file, ['.', '..']);
160
- }));
161
- ` ,
162
- } ) ;
163
-
164
- const vfsPhpFiles = JSON . parse ( phpListing . text ) ;
165
- expect ( vfsPhpFiles . sort ( ) ) . toEqual ( localFiles . sort ( ) ) ;
166
- } ) ;
98
+ expect ( php . isFile ( vfsMountPoint ) ) . toBe ( true ) ;
99
+ expect ( php . readFileAsText ( vfsMountPoint ) ) . toEqual (
100
+ fs . readFileSync ( symlinkTarget , 'utf8' )
101
+ ) ;
102
+ } finally {
103
+ fs . unlinkSync ( symlinkPath ) ;
104
+ }
167
105
} ) ;
168
106
169
- describe ( 'Unmounting' , ( ) => {
170
- it ( 'Should unmount a file and remove created node from VFS' , async ( ) => {
171
- const testFilePath = path . join (
172
- __dirname ,
173
- 'test-data' ,
174
- 'long-post-body.txt'
175
- ) ;
107
+ it ( 'Should unmount a file and remove created node from VFS' , async ( ) => {
108
+ const testFilePath = path . join (
109
+ __dirname ,
110
+ 'test-data' ,
111
+ 'long-post-body.txt'
112
+ ) ;
176
113
177
- const unmount = await php . mount (
178
- '/single-file.txt' ,
179
- createNodeFsMountHandler ( testFilePath )
180
- ) ;
114
+ const unmount = await php . mount (
115
+ '/single-file.txt' ,
116
+ createNodeFsMountHandler ( testFilePath )
117
+ ) ;
181
118
182
- expect ( php . isFile ( '/single-file.txt' ) ) . toBe ( true ) ;
119
+ expect ( php . isFile ( '/single-file.txt' ) ) . toBe ( true ) ;
183
120
184
- await unmount ( ) ;
185
- expect ( php . isFile ( '/single-file.txt' ) ) . toBe ( false ) ;
186
- } ) ;
121
+ await unmount ( ) ;
122
+ expect ( php . isFile ( '/single-file.txt' ) ) . toBe ( false ) ;
123
+ } ) ;
187
124
188
- it ( 'Should unmount a directory and remove created node from VFS' , async ( ) => {
189
- const testDataPath = path . join ( __dirname , 'test-data' ) ;
190
- const unmount = await php . mount (
191
- '/nested-test' ,
192
- createNodeFsMountHandler ( testDataPath )
193
- ) ;
125
+ it ( 'Should unmount a directory and remove created node from VFS' , async ( ) => {
126
+ const testDataPath = path . join ( __dirname , 'test-data' ) ;
127
+ const unmount = await php . mount (
128
+ '/nested-test' ,
129
+ createNodeFsMountHandler ( testDataPath )
130
+ ) ;
194
131
195
- expect ( php . isDir ( '/nested-test' ) ) . toBe ( true ) ;
132
+ expect ( php . isDir ( '/nested-test' ) ) . toBe ( true ) ;
196
133
197
- await unmount ( ) ;
198
- expect ( php . isDir ( '/nested-test' ) ) . toBe ( false ) ;
199
- } ) ;
134
+ await unmount ( ) ;
135
+ expect ( php . isDir ( '/nested-test' ) ) . toBe ( false ) ;
136
+ } ) ;
200
137
201
- it ( 'Should unmount a file, but not remove the parent directory from VFS if it was created manually' , async ( ) => {
202
- const testFilePath = path . join (
203
- __dirname ,
204
- 'test-data' ,
205
- 'long-post-body.txt'
206
- ) ;
138
+ it ( 'Should unmount a file, but not remove the parent directory from VFS if it was created manually' , async ( ) => {
139
+ const testFilePath = path . join (
140
+ __dirname ,
141
+ 'test-data' ,
142
+ 'long-post-body.txt'
143
+ ) ;
207
144
208
- const mountPoint = '/sub-dir/single-file.txt' ;
145
+ const mountPoint = '/sub-dir/single-file.txt' ;
209
146
210
- await php . mkdir ( dirname ( mountPoint ) ) ;
147
+ await php . mkdir ( dirname ( mountPoint ) ) ;
211
148
212
- const unmount = await php . mount (
213
- mountPoint ,
214
- createNodeFsMountHandler ( testFilePath )
215
- ) ;
149
+ const unmount = await php . mount (
150
+ mountPoint ,
151
+ createNodeFsMountHandler ( testFilePath )
152
+ ) ;
216
153
217
- expect ( php . isFile ( mountPoint ) ) . toBe ( true ) ;
154
+ expect ( php . isFile ( mountPoint ) ) . toBe ( true ) ;
218
155
219
- await unmount ( ) ;
220
- expect ( php . isDir ( dirname ( mountPoint ) ) ) . toBe ( true ) ;
221
- } ) ;
156
+ await unmount ( ) ;
157
+ expect ( php . isDir ( dirname ( mountPoint ) ) ) . toBe ( true ) ;
158
+ } ) ;
222
159
223
- it ( 'Should unmount a directory, but not remove the parent directory from VFS if it was created manually' , async ( ) => {
224
- const testDataPath = path . join ( __dirname , 'test-data' ) ;
160
+ it ( 'Should unmount a directory, but not remove the parent directory from VFS if it was created manually' , async ( ) => {
161
+ const testDataPath = path . join ( __dirname , 'test-data' ) ;
225
162
226
- await php . mkdir ( '/nested-test' ) ;
227
- const unmount = await php . mount (
228
- '/nested-test' ,
229
- createNodeFsMountHandler ( testDataPath )
230
- ) ;
163
+ await php . mkdir ( '/nested-test' ) ;
164
+ const unmount = await php . mount (
165
+ '/nested-test' ,
166
+ createNodeFsMountHandler ( testDataPath )
167
+ ) ;
231
168
232
- expect ( php . isDir ( '/nested-test' ) ) . toBe ( true ) ;
169
+ expect ( php . isDir ( '/nested-test' ) ) . toBe ( true ) ;
233
170
234
- await unmount ( ) ;
235
- expect ( php . isDir ( '/nested-test' ) ) . toBe ( true ) ;
236
- } ) ;
171
+ await unmount ( ) ;
172
+ expect ( php . isDir ( '/nested-test' ) ) . toBe ( true ) ;
237
173
} ) ;
238
174
} ) ;
0 commit comments