1 <?php
2 
3 /**
4  * Hoa
5  *
6  *
7  * @license
8  *
9  * New BSD License
10  *
11  * Copyright © 2007-2017, Hoa community. All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions are met:
15  *     * Redistributions of source code must retain the above copyright
16  *       notice, this list of conditions and the following disclaimer.
17  *     * Redistributions in binary form must reproduce the above copyright
18  *       notice, this list of conditions and the following disclaimer in the
19  *       documentation and/or other materials provided with the distribution.
20  *     * Neither the name of the Hoa nor the names of its contributors may be
21  *       used to endorse or promote products derived from this software without
22  *       specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 namespace Hoa\Consistency\Test\Unit;
38 
39 use Hoa\Consistency\Xcallable as SUT;
40 use Hoa\Test;
41 
42 /**
43  * Class \Hoa\Consistency\Test\Unit\Xcallable.
44  *
45  * Test suite of the xcallable class.
46  *
47  * @copyright  Copyright © 2007-2017 Hoa community
48  * @license    New BSD License
49  */
50 class Xcallable extends Test\Unit\Suite
51 {
52     public function case_form_function()
53     {
54         $this
55             ->when($result = new SUT('strtoupper'))
56             ->then
57                 ->string($result('foo'))
58                     ->isEqualTo('FOO')
59                 ->string($result->getValidCallback())
60                     ->isEqualTo('strtoupper')
61                 ->string($result->getHash())
62                     ->isEqualTo('function#strtoupper')
63                     ->isEqualTo($result . '')
64                 ->object($reflection = $result->getReflection())
65                     ->isInstanceOf('ReflectionFunction')
66                 ->string($reflection->getName())
67                     ->isEqualTo('strtoupper');
68     }
69 
70     public function case_form_class___method()
71     {
72         $this
73             ->when($result = new SUT(__CLASS__ . '::strtoupper'))
74             ->then
75                 ->string($result('foo'))
76                     ->isEqualTo('FOO')
77                 ->array($result->getValidCallback())
78                     ->isEqualTo([__CLASS__, 'strtoupper'])
79                 ->string($result->getHash())
80                     ->isEqualTo('class#' . __CLASS__ . '::strtoupper')
81                     ->isEqualTo($result . '')
82                 ->object($reflection = $result->getReflection())
83                     ->isInstanceOf('ReflectionMethod')
84                 ->string($reflection->getName())
85                     ->isEqualTo('strtoupper');
86     }
87 
88     public function case_form_class_method()
89     {
90         $this
91             ->when($result = new SUT(__CLASS__, 'strtoupper'))
92             ->then
93                 ->string($result('foo'))
94                     ->isEqualTo('FOO')
95                 ->array($result->getValidCallback())
96                     ->isEqualTo([__CLASS__, 'strtoupper'])
97                 ->string($result->getHash())
98                     ->isEqualTo('class#' . __CLASS__ . '::strtoupper')
99                     ->isEqualTo($result . '')
100                 ->object($reflection = $result->getReflection())
101                     ->isInstanceOf('ReflectionMethod')
102                 ->string($reflection->getName())
103                     ->isEqualTo('strtoupper');
104     }
105 
106     public function case_form_object_method()
107     {
108         $this
109             ->when($result = new SUT($this, 'strtolower'))
110             ->then
111                 ->string($result('FOO'))
112                     ->isEqualTo('foo')
113                 ->array($result->getValidCallback())
114                     ->isEqualTo([$this, 'strtolower'])
115                 ->string($result->getHash())
116                     ->matches(
117                         '/^object\([^:]+\)#' .
118                         preg_quote(__CLASS__) .
119                         '::strtolower$/'
120                     )
121                     ->isEqualTo($result . '')
122                 ->object($reflection = $result->getReflection())
123                     ->isInstanceOf('ReflectionMethod')
124                 ->string($reflection->getName())
125                     ->isEqualTo('strtolower');
126     }
127 
128     public function case_form_object_invoke()
129     {
130         $this
131             ->when($result = new SUT($this))
132             ->then
133                 ->string($result('foo'))
134                     ->isEqualTo('FOO')
135                 ->array($result->getValidCallback())
136                     ->isEqualTo([$this, '__invoke'])
137                 ->string($result->getHash())
138                     ->matches(
139                         '/^object\([^:]+\)#' .
140                         preg_quote(__CLASS__) .
141                         '::__invoke$/'
142                     )
143                     ->isEqualTo($result . '')
144                 ->object($reflection = $result->getReflection())
145                     ->isInstanceOf('ReflectionMethod')
146                 ->string($reflection->getName())
147                     ->isEqualTo('__invoke');
148     }
149 
150     public function case_form_closure()
151     {
152         $this
153             ->given(
154                 $closure = function ($string) {
155                     return strtoupper($string);
156                 }
157             )
158             ->when($result = new SUT($closure))
159             ->then
160                 ->string($result('foo'))
161                     ->isEqualTo('FOO')
162                 ->object($result->getValidCallback())
163                     ->isIdenticalTo($closure)
164                 ->string($result->getHash())
165                     ->matches('/^closure\([^:]+\)$/')
166                     ->isEqualTo($result . '')
167                 ->object($reflection = $result->getReflection())
168                     ->isInstanceOf('ReflectionFunction')
169                 ->string($reflection->getName())
170                     ->isEqualTo('Hoa\Consistency\Test\Unit\{closure}');
171     }
172 
173     public function case_form_array_of_class_method()
174     {
175         $this
176             ->when($result = new SUT([__CLASS__, 'strtoupper']))
177             ->then
178                 ->string($result('foo'))
179                     ->isEqualTo('FOO')
180                 ->array($result->getValidCallback())
181                     ->isEqualTo([__CLASS__, 'strtoupper'])
182                 ->string($result->getHash())
183                     ->isEqualTo('class#' . __CLASS__ . '::strtoupper')
184                     ->isEqualTo($result . '')
185                 ->object($reflection = $result->getReflection())
186                     ->isInstanceOf('ReflectionMethod')
187                 ->string($reflection->getName())
188                     ->isEqualTo('strtoupper');
189     }
190 
191     public function case_form_array_of_object_method()
192     {
193         $this
194             ->when($result = new SUT([$this, 'strtolower']))
195             ->then
196                 ->string($result('FOO'))
197                     ->isEqualTo('foo')
198                 ->array($result->getValidCallback())
199                     ->isEqualTo([$this, 'strtolower'])
200                 ->string($result->getHash())
201                     ->matches(
202                         '/^object\([^:]+\)#' .
203                         preg_quote(__CLASS__) .
204                         '::strtolower$/'
205                     )
206                     ->isEqualTo($result . '')
207                 ->object($reflection = $result->getReflection())
208                     ->isInstanceOf('ReflectionMethod')
209                 ->string($reflection->getName())
210                     ->isEqualTo('strtolower');
211     }
212 
213     public function case_form_able_not_a_string()
214     {
215         $this
216             ->exception(function () {
217                 new SUT(__CLASS__, 123);
218             })
219                 ->isInstanceOf('Hoa\Consistency\Exception');
220     }
221 
222     public function case_form_function_not_defined()
223     {
224         $this
225             ->exception(function () {
226                 new SUT('__hoa_test_undefined_function__');
227             })
228                 ->isInstanceOf('Hoa\Consistency\Exception');
229     }
230 
231     public function case_form_able_cannot_be_deduced()
232     {
233         $this
234             ->given($this->function->method_exists = false)
235             ->exception(function () {
236                 new SUT($this);
237             })
238                 ->isInstanceOf('Hoa\Consistency\Exception');
239     }
240 
241     public function case_invoke()
242     {
243         $this
244             ->given(
245                 $callable = new SUT(
246                     function ($x, $y, $z) {
247                         return [$x, $y, $z];
248                     }
249                 )
250             )
251             ->when($result = $callable(7, [4.2], 'foo'))
252             ->then
253                 ->array($result)
254                     ->isEqualTo([7, [4.2], 'foo']);
255     }
256 
257     public function case_distribute_arguments()
258     {
259         $this
260             ->given(
261                 $callable = new SUT(
262                     function ($x, $y, $z) {
263                         return [$x, $y, $z];
264                     }
265                 )
266             )
267             ->when($result = $callable->distributeArguments([7, [4.2], 'foo']))
268             ->then
269                 ->array($result)
270                     ->isEqualTo([7, [4.2], 'foo']);
271     }
272 
273     protected function _get_valid_callback_stream_xxx($argument, $method)
274     {
275         $this
276             ->given(
277                 $stream    = new \Mock\Hoa\Stream\IStream\Out(),
278                 $arguments = [$argument],
279                 $xcallable = new SUT($stream)
280             )
281             ->when($result = $xcallable->getValidCallback($arguments))
282             ->then
283                 ->array($result)
284                     ->isEqualTo([$stream, $method]);
285     }
286 
287     public function case_get_valid_callback_stream_character()
288     {
289         return $this->_get_valid_callback_stream_xxx('f', 'writeCharacter');
290     }
291 
292     public function case_get_valid_callback_stream_string()
293     {
294         return $this->_get_valid_callback_stream_xxx('foo', 'writeString');
295     }
296 
297     public function case_get_valid_callback_stream_boolean()
298     {
299         return $this->_get_valid_callback_stream_xxx(true, 'writeBoolean');
300     }
301 
302     public function case_get_valid_callback_stream_integer()
303     {
304         return $this->_get_valid_callback_stream_xxx(7, 'writeInteger');
305     }
306 
307     public function case_get_valid_callback_stream_array()
308     {
309         return $this->_get_valid_callback_stream_xxx([4, 2], 'writeArray');
310     }
311 
312     public function case_get_valid_callback_stream_float()
313     {
314         return $this->_get_valid_callback_stream_xxx(4.2, 'writeFloat');
315     }
316 
317     public function case_get_valid_callback_stream_other()
318     {
319         return $this->_get_valid_callback_stream_xxx($this, 'writeAll');
320     }
321 
322     public static function strtoupper($string)
323     {
324         return strtoupper($string);
325     }
326 
327     public function strtolower($string)
328     {
329         return strtolower($string);
330     }
331 
332     public function __invoke($string)
333     {
334         return strtoupper($string);
335     }
336 
337     public function __toString()
338     {
339         return 'hello';
340     }
341 }
342