22
33namespace SwooleTW \Http \Tests \Transformers ;
44
5+ use Symfony \Component \HttpFoundation \ResponseHeaderBag ;
6+ use Symfony \Component \HttpFoundation \StreamedResponse ;
7+ use Symfony \Component \HttpFoundation \BinaryFileResponse ;
8+ use Symfony \Component \HttpFoundation \Cookie ;
9+ use Symfony \Component \HttpFoundation \File \File ;
510use Illuminate \Http \Response as IlluminateResponse ;
11+ use Illuminate \Support \Str ;
612use Swoole \Http \Response as SwooleResponse ;
713use Swoole \Http \Request as SwooleRequest ;
814use SwooleTW \Http \Tests \TestCase ;
915use SwooleTW \Http \Transformers \Response ;
16+ use Mockery ;
1017
1118class ResponseTest extends TestCase
1219{
@@ -32,4 +39,273 @@ public function testGetSwooleResponse()
3239
3340 $ this ->assertInstanceOf (SwooleResponse::class, $ swooleResponse );
3441 }
42+
43+ public function testGetSwooleRequest ()
44+ {
45+ $ response = Response::make (new IlluminateResponse , new SwooleResponse , new SwooleRequest );
46+ $ swooleRequest = $ response ->getSwooleRequest ();
47+
48+ $ this ->assertInstanceOf (SwooleRequest::class, $ swooleRequest );
49+ }
50+
51+ public function testSendHeaders ()
52+ {
53+ $ headers = ['test ' => ['123 ' , '456 ' ]];
54+ $ status = 200 ;
55+
56+ // rawcookie
57+ $ cookie1 = Mockery::mock (Cookie::class);
58+ $ cookie1 ->shouldReceive ('isRaw ' )->once ()->andReturn (true );
59+ $ cookie1 ->shouldReceive ('getName ' )->once ()->andReturn ('Cookie_1_getName ' );
60+ $ cookie1 ->shouldReceive ('getValue ' )->once ()->andReturn ('Cookie_1_getValue ' );
61+ $ cookie1 ->shouldReceive ('getExpiresTime ' )->once ()->andReturn ('Cookie_1_getExpiresTime ' );
62+ $ cookie1 ->shouldReceive ('getPath ' )->once ()->andReturn ('Cookie_1_getPath ' );
63+ $ cookie1 ->shouldReceive ('getDomain ' )->once ()->andReturn ('Cookie_1_getDomain ' );
64+ $ cookie1 ->shouldReceive ('isSecure ' )->once ()->andReturn ('Cookie_1_isSecure ' );
65+ $ cookie1 ->shouldReceive ('isHttpOnly ' )->once ()->andReturn ('Cookie_1_isHttpOnly ' );
66+
67+ // cookie
68+ $ cookie2 = Mockery::mock (Cookie::class);
69+ $ cookie2 ->shouldReceive ('isRaw ' )->once ()->andReturn (false );
70+ $ cookie2 ->shouldReceive ('getName ' )->once ()->andReturn ('Cookie_2_getName ' );
71+ $ cookie2 ->shouldReceive ('getValue ' )->once ()->andReturn ('Cookie_2_getValue ' );
72+ $ cookie2 ->shouldReceive ('getExpiresTime ' )->once ()->andReturn ('Cookie_2_getExpiresTime ' );
73+ $ cookie2 ->shouldReceive ('getPath ' )->once ()->andReturn ('Cookie_2_getPath ' );
74+ $ cookie2 ->shouldReceive ('getDomain ' )->once ()->andReturn ('Cookie_2_getDomain ' );
75+ $ cookie2 ->shouldReceive ('isSecure ' )->once ()->andReturn ('Cookie_2_isSecure ' );
76+ $ cookie2 ->shouldReceive ('isHttpOnly ' )->once ()->andReturn ('Cookie_2_isHttpOnly ' );
77+
78+ $ illuminateResponse = Mockery::mock (IlluminateResponse::class);
79+ $ illuminateResponse ->headers = Mockery::mock (ResponseHeaderBag::class);
80+
81+ $ illuminateResponse ->headers
82+ ->shouldReceive ('has ' )
83+ ->once ()
84+ ->with ('Date ' )
85+ ->andReturn (false );
86+
87+ $ illuminateResponse ->headers
88+ ->shouldReceive ('getCookies ' )
89+ ->once ()
90+ ->andReturn ([$ cookie1 , $ cookie2 ] );
91+
92+ $ illuminateResponse ->headers
93+ ->shouldReceive ('allPreserveCase ' )
94+ ->once ()
95+ ->andReturn ([
96+ 'Set-Cookie ' => uniqid (),
97+ ] + $ headers );
98+
99+ $ illuminateResponse ->shouldReceive ('setDate ' )
100+ ->once ()
101+ ->withArgs (function (\DateTime $ dateTime ) {
102+ $ timestamp = $ dateTime ->getTimestamp ();
103+ return $ timestamp <= time () && $ timestamp + 2 > time ();
104+ });
105+
106+ $ illuminateResponse ->shouldReceive ('getStatusCode ' )
107+ ->once ()
108+ ->andReturn ($ status );
109+
110+ $ swooleResponse = Mockery::mock (SwooleResponse::class);
111+ $ swooleResponse ->shouldReceive ('header ' )
112+ ->times (2 )
113+ ->withArgs (function ($ name , $ value ) use (&$ headers ) {
114+ $ header = array_shift ($ headers ['test ' ]);
115+ return $ name === 'test ' && $ header === $ value ;
116+ });
117+ $ swooleResponse ->shouldReceive ('status ' )
118+ ->once ()
119+ ->withArgs ([$ status ]);
120+ $ swooleResponse ->shouldReceive ('rawcookie ' )
121+ ->once ()
122+ ->withArgs ([
123+ 'Cookie_1_getName ' ,
124+ 'Cookie_1_getValue ' ,
125+ 'Cookie_1_getExpiresTime ' ,
126+ 'Cookie_1_getPath ' ,
127+ 'Cookie_1_getDomain ' ,
128+ 'Cookie_1_isSecure ' ,
129+ 'Cookie_1_isHttpOnly '
130+ ]);
131+ $ swooleResponse ->shouldReceive ('cookie ' )
132+ ->once ()
133+ ->withArgs ([
134+ 'Cookie_2_getName ' ,
135+ 'Cookie_2_getValue ' ,
136+ 'Cookie_2_getExpiresTime ' ,
137+ 'Cookie_2_getPath ' ,
138+ 'Cookie_2_getDomain ' ,
139+ 'Cookie_2_isSecure ' ,
140+ 'Cookie_2_isHttpOnly '
141+ ]);
142+
143+ $ swooleRequest = Mockery::mock (SwooleRequest::class);
144+
145+ $ response = Response::make ($ illuminateResponse , $ swooleResponse , $ swooleRequest );
146+
147+ /**
148+ * use Closure::call to bypass protect and private method
149+ * url: https://www.php.net/manual/en/closure.call.php
150+ */
151+ $ callback = function () {
152+ $ this ->sendHeaders ();
153+ };
154+ $ callback ->call ($ response );
155+ }
156+
157+ public function testSendStreamedResponseContent ()
158+ {
159+ $ illuminateResponse = Mockery::mock (StreamedResponse::class);
160+ $ illuminateResponse ->output = uniqid ();
161+
162+ $ swooleResponse = Mockery::mock (SwooleResponse::class);
163+ $ swooleResponse ->shouldReceive ('end ' )
164+ ->once ()
165+ ->withArgs ([$ illuminateResponse ->output ]);
166+
167+ $ swooleRequest = Mockery::mock (SwooleRequest::class);
168+
169+ $ response = Response::make ($ illuminateResponse , $ swooleResponse , $ swooleRequest );
170+
171+ /**
172+ * use Closure::call to bypass protect and private method
173+ * url: https://www.php.net/manual/en/closure.call.php
174+ */
175+ $ callback = function () {
176+ $ this ->sendContent ();
177+ };
178+ $ callback ->call ($ response );
179+ }
180+
181+ public function testSendBinaryFileResponseContent ()
182+ {
183+ $ path = uniqid ();
184+ $ file = Mockery::mock (File::class);
185+ $ file ->shouldReceive ('getPathname ' )
186+ ->once ()
187+ ->andReturn ($ path );
188+
189+ $ illuminateResponse = Mockery::mock (BinaryFileResponse::class);
190+ $ illuminateResponse ->shouldReceive ('getFile ' )
191+ ->once ()
192+ ->andReturn ($ file );
193+
194+ $ swooleResponse = Mockery::mock (SwooleResponse::class);
195+ $ swooleResponse ->shouldReceive ('sendfile ' )
196+ ->once ()
197+ ->withArgs ([$ path ]);
198+
199+ $ swooleRequest = Mockery::mock (SwooleRequest::class);
200+
201+ $ response = Response::make ($ illuminateResponse , $ swooleResponse , $ swooleRequest );
202+
203+ /**
204+ * use Closure::call to bypass protect and private method
205+ * url: https://www.php.net/manual/en/closure.call.php
206+ */
207+ $ callback = function () {
208+ $ this ->sendContent ();
209+ };
210+ $ callback ->call ($ response );
211+ }
212+
213+ public function testSendChunkedContent ()
214+ {
215+ $ http_compression_level = 5 ;
216+ $ content = Str::random (Response::CHUNK_SIZE * 3 );
217+ $ compressedContent = gzencode ($ content , $ http_compression_level );
218+ $ times = (int )ceil (strlen ($ compressedContent ) / Response::CHUNK_SIZE );
219+
220+ $ chunks = [];
221+ foreach (str_split ($ compressedContent , Response::CHUNK_SIZE ) as $ chunk ) {
222+ $ chunks [] = $ chunk ;
223+ }
224+
225+ app ()->instance ('config ' , new \Illuminate \Config \Repository ([
226+ 'swoole_http ' => [
227+ 'server ' => [
228+ 'options ' => [
229+ 'http_compression ' => true ,
230+ 'http_compression_level ' => $ http_compression_level
231+ ]
232+ ],
233+ ],
234+ ]));
235+
236+ $ illuminateResponse = Mockery::mock (IlluminateResponse::class);
237+ $ illuminateResponse ->headers = Mockery::mock (ResponseHeaderBag::class);
238+
239+ $ illuminateResponse ->headers
240+ ->shouldReceive ('get ' )
241+ ->once ()
242+ ->withArgs (['Content-Encoding ' ])
243+ ->andReturn (null );
244+
245+ $ illuminateResponse ->shouldReceive ('getContent ' )
246+ ->andReturn ($ content );
247+
248+ $ swooleResponse = Mockery::mock (SwooleResponse::class);
249+ $ swooleResponse ->shouldReceive ('header ' )
250+ ->once ()
251+ ->withArgs (['Content-Encoding ' , 'gzip ' ]);
252+
253+ $ swooleResponse ->shouldReceive ('write ' )
254+ ->times ($ times )
255+ ->withArgs (function ($ chunk ) use (&$ chunks ) {
256+ $ expectChunk = array_shift ($ chunks );
257+ return $ chunk === $ expectChunk ;
258+ });
259+ $ swooleResponse ->shouldReceive ('end ' )
260+ ->once ();
261+
262+ $ swooleRequest = Mockery::mock (SwooleRequest::class);
263+ $ swooleRequest ->header = ['accept-encoding ' => 'gzip, deflate, br ' ];
264+
265+ $ response = Response::make ($ illuminateResponse , $ swooleResponse , $ swooleRequest );
266+
267+ /**
268+ * use Closure::call to bypass protect and private method
269+ * url: https://www.php.net/manual/en/closure.call.php
270+ */
271+ $ callback = function () {
272+ $ this ->sendContent ();
273+ };
274+ $ callback ->call ($ response );
275+ }
276+
277+ public function testSend_ ()
278+ {
279+ $ status = 200 ;
280+ $ content = 'test ' ;
281+
282+ app ()->instance ('config ' , new \Illuminate \Config \Repository ([
283+ 'swoole_http ' => [
284+ 'server ' => [
285+ 'options ' => [
286+ 'http_compression ' => false ,
287+ ]
288+ ],
289+ ],
290+ ]));
291+
292+ $ swooleResponse = Mockery::mock (SwooleResponse::class);
293+ $ swooleResponse ->shouldReceive ('header ' )
294+ ->twice ()
295+ ->withArgs (function ($ name , $ value ) {
296+ return in_array ($ name , ['Date ' , 'Cache-Control ' ], true );
297+ });
298+ $ swooleResponse ->shouldReceive ('status ' )
299+ ->once ()
300+ ->with (200 );
301+ $ swooleResponse ->shouldReceive ('end ' )
302+ ->once ()
303+ ->withArgs ([$ content ]);
304+
305+ $ swooleRequest = Mockery::mock (SwooleRequest::class);
306+ $ swooleRequest ->header = ['accept-encoding ' => 'gzip, deflate, br ' ];
307+
308+ $ response = Response::make ($ content , $ swooleResponse , $ swooleRequest );
309+ $ response ->send ();
310+ }
35311}
0 commit comments