44
55namespace TypePHP \Tests \Internal ;
66
7- use ReflectionClass ;
87use TypePHP \Contract \FileFilter ;
98use TypePHP \Internal \Config ;
109use TypePHP \Internal \StreamWrapper ;
1110
1211describe ('StreamWrapper Unit Tests ' , function () {
1312 beforeEach (function () {
1413 Config::reset ();
14+ StreamWrapper::reset ();
1515 });
1616
1717 afterEach (function () {
1818 Config::reset ();
19+ StreamWrapper::reset ();
1920 });
2021
2122 describe ('transformSource() ' , function () {
@@ -92,7 +93,7 @@ function testIgnoredFileFunc(int $id): int
9293 });
9394 });
9495
95- describe ('url_stat() & Smart Negative Caching ' , function () {
96+ describe ('url_stat() & Cache Invalidation ' , function () {
9697 test ('caches positive stat results in memory ' , function () {
9798 $ wrapper = new StreamWrapper ();
9899 $ existingFile = __FILE__ ;
@@ -105,39 +106,14 @@ function testIgnoredFileFunc(int $id): int
105106 ;
106107 });
107108
108- test ('caches negative misses for static vendor paths ' , function () {
109+ test ('returns false cleanly without throwing warnings on non-existent files ' , function () {
109110 $ wrapper = new StreamWrapper ();
110111 $ projectRoot = str_replace ('\\' , '/ ' , Config::getProjectRoot ());
111- $ missingVendorFile = $ projectRoot . '/vendor/non_existent_package/Missing .php ' ;
112+ $ missingFile = $ projectRoot . '/non_existent_path_probe_123 .php ' ;
112113
113- $ miss1 = $ wrapper ->url_stat ($ missingVendorFile , 0 );
114- $ miss2 = $ wrapper ->url_stat ($ missingVendorFile , 0 );
115-
116- expect ($ miss1 )->toBeFalse ()
117- ->and ($ miss2 )->toBeFalse ()
118- ;
119-
120- $ ref = new ReflectionClass (StreamWrapper::class);
121- $ negProp = $ ref ->getProperty ('staticNegativeStatCache ' );
122- $ negCache = $ negProp ->getValue ();
123-
124- expect ($ negCache )->toHaveKey ($ missingVendorFile );
125- });
126-
127- test ('never caches negative misses for dynamic writable paths (var/cache, storage) ' , function () {
128- $ wrapper = new StreamWrapper ();
129- $ projectRoot = str_replace ('\\' , '/ ' , Config::getProjectRoot ());
130- $ missingVarCacheFile = $ projectRoot . '/var/cache/test/Container.php ' ;
131-
132- $ miss = $ wrapper ->url_stat ($ missingVarCacheFile , 0 );
114+ $ miss = $ wrapper ->url_stat ($ missingFile , 0 );
133115
134116 expect ($ miss )->toBeFalse ();
135-
136- $ ref = new ReflectionClass (StreamWrapper::class);
137- $ negProp = $ ref ->getProperty ('staticNegativeStatCache ' );
138- $ negCache = $ negProp ->getValue ();
139-
140- expect ($ negCache )->not ()->toHaveKey ($ missingVarCacheFile );
141117 });
142118
143119 test ('invalidates stat cache upon file mutation operations (mkdir, unlink, rename, touch) ' , function () {
@@ -151,11 +127,14 @@ function testIgnoredFileFunc(int $id): int
151127 $ stat = $ wrapper ->url_stat ($ tempFile , 0 );
152128 expect ($ stat )->toBeArray ();
153129
130+ // Touch invalidates statCache
154131 $ wrapper ->stream_metadata ($ tempFile , STREAM_META_TOUCH , [time (), time ()]);
155132
133+ // Rename invalidates statCache
156134 $ renamedFile = $ tempDir . '/renamed.php ' ;
157135 $ wrapper ->rename ($ tempFile , $ renamedFile );
158136
137+ // Unlink invalidates statCache
159138 $ wrapper ->unlink ($ renamedFile );
160139 $ wrapper ->rmdir ($ tempDir , 0 );
161140
@@ -177,6 +156,16 @@ function testIgnoredFileFunc(int $id): int
177156 $ wrapper ->stream_close ();
178157 });
179158
159+ test ('serves raw untransformed source code to read-only functions like file_get_contents for clean error screens ' , function () {
160+ $ targetFile = __DIR__ . '/../Fixtures/Services/UserService.php ' ;
161+
162+ $ content = file_get_contents ($ targetFile );
163+
164+ expect ($ content )->not ()->toContain ('RuntimeTypeChecker::setupScope ' )
165+ ->and ($ content )->toContain ('class UserService extends BaseService ' )
166+ ;
167+ });
168+
180169 test ('bypasses AST transformation for unwhitelisted vendor files ' , function () {
181170 Config::set ([
182171 'include ' => ['src/** ' ],
@@ -241,4 +230,4 @@ function testIgnoredFileFunc(int $id): int
241230 ;
242231 });
243232 });
244- });
233+ });
0 commit comments