1717use CodeIgniter \Config \Services ;
1818use CodeIgniter \Superglobals ;
1919use CodeIgniter \Test \CIUnitTestCase ;
20- use CodeIgniter \Test \Filters \CITestStreamFilter ;
2120use CodeIgniter \Test \Mock \MockInputOutput ;
2221use CodeIgniter \Test \StreamFilterTrait ;
2322use PHPUnit \Framework \Attributes \Group ;
2423use PHPUnit \Framework \Attributes \PreserveGlobalState ;
24+ use PHPUnit \Framework \Attributes \RequiresOperatingSystem ;
2525use PHPUnit \Framework \Attributes \RunInSeparateProcess ;
2626use PHPUnit \Framework \Attributes \WithoutErrorHandler ;
2727
@@ -70,14 +70,6 @@ protected function tearDown(): void
7070 CLI ::reset ();
7171 }
7272
73- /**
74- * Gets buffer contents then releases it.
75- */
76- protected function getBuffer (): string
77- {
78- return $ this ->getStreamFilterBuffer ();
79- }
80-
8173 protected function resetEnvironment (): void
8274 {
8375 putenv ('encryption.key ' );
@@ -88,31 +80,35 @@ protected function resetEnvironment(): void
8880 public function testGenerateKeyShowsEncodedKey (): void
8981 {
9082 command ('key:generate --show ' );
91- $ this ->assertStringContainsString ('hex2bin: ' , $ this ->getBuffer ());
83+ $ this ->assertStringContainsString ('hex2bin: ' , $ this ->getStreamFilterBuffer ());
9284
85+ $ this ->resetStreamFilterBuffer ();
9386 command ('key:generate --prefix base64 --show ' );
94- $ this ->assertStringContainsString ('base64: ' , $ this ->getBuffer ());
87+ $ this ->assertStringContainsString ('base64: ' , $ this ->getStreamFilterBuffer ());
9588
89+ $ this ->resetStreamFilterBuffer ();
9690 command ('key:generate --prefix hex2bin --show ' );
97- $ this ->assertStringContainsString ('hex2bin: ' , $ this ->getBuffer ());
91+ $ this ->assertStringContainsString ('hex2bin: ' , $ this ->getStreamFilterBuffer ());
9892 }
9993
10094 #[PreserveGlobalState(false )]
10195 #[RunInSeparateProcess]
10296 public function testGenerateKeyCreatesNewKey (): void
10397 {
10498 command ('key:generate ' );
105- $ this ->assertStringContainsString (' successfully set. ' , $ this ->getBuffer ());
99+ $ this ->assertStringContainsString (sprintf ( ' New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
106100 $ this ->assertStringContainsString (env ('encryption.key ' ), (string ) file_get_contents ($ this ->envPath ));
107101 $ this ->assertStringContainsString ('hex2bin: ' , (string ) file_get_contents ($ this ->envPath ));
108102
103+ $ this ->resetStreamFilterBuffer ();
109104 command ('key:generate --prefix base64 --force ' );
110- $ this ->assertStringContainsString (' successfully set. ' , $ this ->getBuffer ());
105+ $ this ->assertStringContainsString (sprintf ( ' New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
111106 $ this ->assertStringContainsString (env ('encryption.key ' ), (string ) file_get_contents ($ this ->envPath ));
112107 $ this ->assertStringContainsString ('base64: ' , (string ) file_get_contents ($ this ->envPath ));
113108
109+ $ this ->resetStreamFilterBuffer ();
114110 command ('key:generate --prefix hex2bin --force ' );
115- $ this ->assertStringContainsString (' successfully set. ' , $ this ->getBuffer ());
111+ $ this ->assertStringContainsString (sprintf ( ' New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
116112 $ this ->assertStringContainsString (env ('encryption.key ' ), (string ) file_get_contents ($ this ->envPath ));
117113 $ this ->assertStringContainsString ('hex2bin: ' , (string ) file_get_contents ($ this ->envPath ));
118114 }
@@ -123,8 +119,9 @@ public function testDefaultShippedEnvIsMissing(): void
123119 command ('key:generate ' );
124120 rename (ROOTPATH . 'lostenv ' , ROOTPATH . 'env ' );
125121
126- $ this ->assertStringContainsString ('Both default shipped ' , $ this ->getBuffer ());
127- $ this ->assertStringContainsString ('Error in setting ' , $ this ->getBuffer ());
122+ $ this ->assertStringContainsString ('Both default shipped ' , $ this ->getStreamFilterBuffer ());
123+ $ this ->assertStringContainsString ('Here \'s your new key instead: ' , $ this ->getStreamFilterBuffer ());
124+ $ this ->assertStringNotContainsString ('Failed to write ' , $ this ->getStreamFilterBuffer ());
128125 }
129126
130127 /**
@@ -136,7 +133,7 @@ public function testKeyGenerateWhenKeyIsMissingInDotEnvFile(): void
136133
137134 command ('key:generate ' );
138135
139- $ this ->assertStringContainsString (' Application \' s new encryption key was successfully set. ' , $ this ->getBuffer ());
136+ $ this ->assertStringContainsString (sprintf ( ' New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
140137 $ this ->assertSame ("\nencryption.key = " . env ('encryption.key ' ), file_get_contents ($ this ->envPath ));
141138 }
142139
@@ -152,9 +149,9 @@ public function testKeyGenerateWhenNewHexKeyIsSubsequentlyCommentedOut(): void
152149 ));
153150 $ this ->assertSame (1 , $ count , 'Failed commenting out the previously set application key. ' );
154151
155- CITestStreamFilter:: $ buffer = '' ;
152+ $ this -> resetStreamFilterBuffer () ;
156153 command ('key:generate --force ' );
157- $ this ->assertStringContainsString (' was successfully set. ' , $ this ->getBuffer ());
154+ $ this ->assertStringContainsString (sprintf ( ' New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
158155 $ this ->assertNotSame ($ key , env ('encryption.key ' , $ key ), 'Failed replacing the commented out key. ' );
159156 }
160157
@@ -170,9 +167,9 @@ public function testKeyGenerateWhenNewBase64KeyIsSubsequentlyCommentedOut(): voi
170167 ));
171168 $ this ->assertSame (1 , $ count , 'Failed commenting out the previously set application key. ' );
172169
173- CITestStreamFilter:: $ buffer = '' ;
170+ $ this -> resetStreamFilterBuffer () ;
174171 command ('key:generate --force ' );
175- $ this ->assertStringContainsString (' was successfully set. ' , $ this ->getBuffer ());
172+ $ this ->assertStringContainsString (sprintf ( ' New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
176173 $ this ->assertNotSame ($ key , env ('encryption.key ' , $ key ), 'Failed replacing the commented out key. ' );
177174 }
178175
@@ -190,10 +187,10 @@ public function testKeyGenerateReplacesUnloadedKeyInDotEnvFile(): void
190187 $ this ->assertSame ('' , env ('encryption.key ' , '' ));
191188
192189 command ('key:generate --force ' );
190+ $ this ->assertStringContainsString (sprintf ('New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
193191
194- $ this ->assertStringContainsString ('was successfully set. ' , $ this ->getBuffer ());
195-
196- $ contents = (string ) file_get_contents ($ this ->envPath );
192+ $ contents = @file_get_contents ($ this ->envPath );
193+ $ this ->assertIsString ($ contents , 'Failed to read .env file contents. ' );
197194 $ this ->assertStringNotContainsString ($ existingKey , $ contents );
198195 $ this ->assertStringContainsString ('encryption.key = ' . env ('encryption.key ' ), $ contents );
199196 }
@@ -234,7 +231,7 @@ public function testKeyGenerateNotFooledByCommentMentioningEncryptionKey(): void
234231 );
235232 }
236233
237- public function testKeyGenerateAbortsWhenOverwritePromptIsDeclined (): void
234+ public function testKeyGenerateCancelsWhenOverwritePromptIsDeclined (): void
238235 {
239236 command ('key:generate ' );
240237 $ key = env ('encryption.key ' , '' );
@@ -244,12 +241,13 @@ public function testKeyGenerateAbortsWhenOverwritePromptIsDeclined(): void
244241 $ io ->setInputs (['n ' ]);
245242 CLI ::setInputOutput ($ io );
246243
244+ $ this ->resetStreamFilterBuffer ();
247245 command ('key:generate ' );
248246
249247 $ this ->assertSame ($ key , env ('encryption.key ' , '' ), 'Existing key should not change. ' );
250248 $ this ->assertStringContainsString ($ key , (string ) file_get_contents ($ this ->envPath ));
251249 $ this ->assertStringContainsString ('Overwrite existing key? ' , $ io ->getOutput ());
252- $ this ->assertStringContainsString ('Setting new encryption key aborted . ' , $ io ->getOutput ());
250+ $ this ->assertStringContainsString ('Setting new encryption key cancelled . ' , $ io ->getOutput ());
253251 }
254252
255253 public function testKeyGenerateOverwritesWhenOverwritePromptIsConfirmed (): void
@@ -262,12 +260,13 @@ public function testKeyGenerateOverwritesWhenOverwritePromptIsConfirmed(): void
262260 $ io ->setInputs (['y ' ]);
263261 CLI ::setInputOutput ($ io );
264262
263+ $ this ->resetStreamFilterBuffer ();
265264 command ('key:generate --prefix base64 ' );
266265
267266 $ this ->assertNotSame ($ oldKey , env ('encryption.key ' , $ oldKey ));
268267 $ this ->assertStringContainsString ('base64: ' , (string ) file_get_contents ($ this ->envPath ));
269268 $ this ->assertStringContainsString ('Overwrite existing key? ' , $ io ->getOutput ());
270- $ this ->assertStringContainsString (' successfully set. ' , $ io ->getOutput ());
269+ $ this ->assertStringContainsString (sprintf ( ' New encryption key written to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ) , $ io ->getOutput ());
271270 }
272271
273272 #[PreserveGlobalState(false )]
@@ -279,19 +278,20 @@ public function testKeyGenerateAbortsNonInteractivelyWithExistingKey(): void
279278 $ this ->assertNotSame ('' , $ key );
280279
281280 $ this ->resetStreamFilterBuffer ();
282-
283281 command ('key:generate --no-interaction ' );
284282
285283 $ this ->assertSame ($ key , env ('encryption.key ' , '' ), 'Existing key should not change. ' );
286- $ this ->assertStringContainsString ('Setting new encryption key aborted. ' , $ this ->getBuffer ());
287- $ this ->assertStringContainsString ('--force ' , $ this ->getBuffer ());
284+ $ this ->assertStringContainsString (
285+ 'Setting new encryption key aborted: pass --force to overwrite the existing key in non-interactive mode. ' ,
286+ $ this ->getStreamFilterBuffer (),
287+ );
288288 }
289289
290290 public function testKeyGenerateErrorsOnInvalidPrefixNonInteractively (): void
291291 {
292292 command ('key:generate --prefix invalid --show --no-interaction ' );
293293
294- $ this ->assertStringContainsString ('Invalid prefix "invalid" ' , $ this ->getBuffer ());
294+ $ this ->assertStringContainsString ('Invalid prefix "invalid" ' , $ this ->getStreamFilterBuffer ());
295295 }
296296
297297 public function testKeyGeneratePromptsForInvalidPrefix (): void
@@ -305,4 +305,20 @@ public function testKeyGeneratePromptsForInvalidPrefix(): void
305305 $ this ->assertStringContainsString ('Please provide a valid prefix to use. ' , $ io ->getOutput ());
306306 $ this ->assertStringContainsString ('hex2bin: ' , $ io ->getOutput ());
307307 }
308+
309+ #[RequiresOperatingSystem('Linux|Darwin ' )]
310+ public function testKeyGenerateErrorsWhenEnvFileIsNotWritable (): void
311+ {
312+ command ('key:generate ' );
313+ chmod ($ this ->envPath , 0o444 );
314+
315+ try {
316+ $ this ->resetStreamFilterBuffer ();
317+ command ('key:generate --force ' );
318+
319+ $ this ->assertStringContainsString (sprintf ('Failed to write new encryption key to ROOTPATH%s.env. ' , DIRECTORY_SEPARATOR ), $ this ->getStreamFilterBuffer ());
320+ } finally {
321+ chmod ($ this ->envPath , 0o644 );
322+ }
323+ }
308324}
0 commit comments