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
37namespace Hoa\Consistency\Test\Unit;
38
39use Hoa\Consistency\Xcallable as SUT;
40use 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 */
50class 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