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\Autoloader as SUT;
40use Hoa\Test;
41
42/**
43 * Class \Hoa\Consistency\Test\Unit\Autoloader.
44 *
45 * Test suite of the autoloader.
46 *
47 * @copyright  Copyright © 2007-2017 Hoa community
48 * @license    New BSD License
49 */
50class Autoloader extends Test\Unit\Suite
51{
52    public function case_add_namespace_prepend()
53    {
54        $this
55            ->given(
56                $autoloader     = new SUT(),
57                $prefix         = 'Foo\Bar\\',
58                $baseDirectoryA = 'Source/Foo/Bar/',
59                $baseDirectoryB = 'Source/Foo/Bar/'
60            )
61            ->when(
62                $autoloader->addNamespace($prefix, $baseDirectoryA),
63                $result = $autoloader->addNamespace($prefix, $baseDirectoryB)
64            )
65            ->then
66                ->boolean($autoloader->hasBaseDirectory($prefix))
67                    ->isTrue()
68                ->array($autoloader->getBaseDirectories($prefix))
69                    ->isEqualTo([
70                        $baseDirectoryB,
71                        $baseDirectoryA
72                    ]);
73    }
74
75    public function case_add_namespace_append()
76    {
77        $this
78            ->given(
79                $autoloader     = new SUT(),
80                $prefix         = 'Foo\Bar\\',
81                $baseDirectoryA = 'Source/Foo/Bar/',
82                $baseDirectoryB = 'Source/Foo/Bar/'
83            )
84            ->when(
85                $autoloader->addNamespace($prefix, $baseDirectoryA),
86                $result = $autoloader->addNamespace($prefix, $baseDirectoryB)
87            )
88            ->then
89                ->boolean($autoloader->hasBaseDirectory($prefix))
90                    ->isTrue()
91                ->array($autoloader->getBaseDirectories($prefix))
92                    ->isEqualTo([
93                        $baseDirectoryA,
94                        $baseDirectoryB
95                    ]);
96    }
97
98    public function case_add_namespace_with_invalid_prefix()
99    {
100        $this
101            ->given(
102                $autoloader    = new SUT(),
103                $prefix        = '\\\\Foo\Bar',
104                $baseDirectory = 'Source/Foo/Bar/'
105            )
106            ->when($result = $autoloader->addNamespace($prefix, $baseDirectory))
107            ->then
108                ->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))
109                    ->isTrue()
110                ->array($autoloader->getBaseDirectories('Foo\Bar\\'))
111                    ->isEqualTo([$baseDirectory]);
112    }
113
114    public function case_add_namespace_with_invalid_base_directory()
115    {
116        $this
117            ->given(
118                $autoloader    = new SUT(),
119                $prefix        = 'Foo\Bar\\',
120                $baseDirectory = 'Source/Foo/Bar'
121            )
122            ->when($result = $autoloader->addNamespace($prefix, $baseDirectory))
123            ->then
124                ->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))
125                    ->isTrue()
126                ->array($autoloader->getBaseDirectories('Foo\Bar\\'))
127                    ->isEqualTo(['Source/Foo/Bar/']);
128    }
129
130    public function case_add_namespace_with_crazy_invalid_base_directory()
131    {
132        $this
133            ->given(
134                $autoloader    = new SUT(),
135                $prefix        = 'Foo\Bar\\',
136                $baseDirectory = 'Source/Foo/Bar/////'
137            )
138            ->when($result = $autoloader->addNamespace($prefix, $baseDirectory))
139            ->then
140                ->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))
141                    ->isTrue()
142                ->array($autoloader->getBaseDirectories('Foo\Bar\\'))
143                    ->isEqualTo(['Source/Foo/Bar/']);
144    }
145
146    public function case_load()
147    {
148        $this
149            ->given(
150                $autoloader = new \Mock\Hoa\Consistency\Autoloader(),
151                $autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/Bar/'),
152                $this->calling($autoloader)->requireFile = function ($file) {
153                    return $file;
154                }
155            )
156            ->when($result = $autoloader->load('Foo\Bar\Baz\Qux'))
157            ->then
158                ->string($result)
159                    ->isEqualTo('Source/Foo/Bar/Baz/Qux.php');
160    }
161
162    public function case_load_invalid_entity()
163    {
164        $this
165            ->given($autoloader = new SUT())
166            ->when($result = $autoloader->load('Foo'))
167            ->then
168                ->variable($result)
169                    ->isNull();
170    }
171
172    public function case_load_flex_entity()
173    {
174        $self = $this;
175
176        $this
177            ->given(
178                $autoloader = new \Mock\Hoa\Consistency\Autoloader(),
179                $autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/'),
180                $this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) {
181                    $called = true;
182                    $self
183                        ->string($entity)
184                            ->isEqualTo('Foo\Bar\Baz\Baz');
185
186                    return;
187                },
188                $autoloader->register()
189            )
190            ->when($result = $autoloader->load('Foo\Bar\Baz'))
191            ->then
192                ->variable($result)
193                    ->isNull()
194                ->boolean($called)
195                    ->isTrue();
196    }
197
198    public function case_load_unmapped_flex_entity()
199    {
200        $self = $this;
201
202        $this
203            ->given(
204                $autoloader = new \Mock\Hoa\Consistency\Autoloader(),
205                $this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) {
206                    $called = true;
207
208                    return;
209                },
210                $autoloader->register()
211            )
212            ->when($result = $autoloader->load('Foo\Bar\Baz'))
213            ->then
214                ->variable($result)
215                    ->isNull()
216                ->variable($called)
217                    ->isNull();
218    }
219
220    public function case_require_existing_file()
221    {
222        $this
223            ->given(
224                $autoloader = new SUT(),
225
226                $this->function->file_exists = true,
227
228                $constantName = 'HOA_TEST_' . uniqid(),
229                $filename     = 'hoa://Test/Vfs/Foo?type=file',
230
231                file_put_contents($filename, '<?php define("' . $constantName . '", "BAR");')
232            )
233            ->when($result = $autoloader->requireFile($filename))
234            ->then
235                ->boolean($result)
236                    ->isTrue()
237                ->string(constant($constantName))
238                    ->isEqualTo('BAR');
239    }
240
241    public function case_require_not_existing_file()
242    {
243        $this
244            ->given(
245                $autoloader                  = new SUT(),
246                $this->function->file_exists = false
247            )
248            ->when($result = $autoloader->requireFile('/hoa/flatland'))
249            ->then
250                ->boolean($result)
251                    ->isFalse();
252    }
253
254    public function case_has_not_base_directory()
255    {
256        $this
257            ->given($autoloader = new SUT())
258            ->when($result = $autoloader->hasBaseDirectory('foo'))
259            ->then
260                ->boolean($result)
261                    ->isFalse();
262    }
263
264    public function case_get_base_undeclared_namespace_prefix()
265    {
266        $this
267            ->given($autoloader = new SUT())
268            ->when($result = $autoloader->getBaseDirectories('foo'))
269            ->then
270                ->array($result)
271                    ->isEmpty();
272    }
273
274    public function case_dnew()
275    {
276        $this
277            ->given($classname = 'Hoa\Consistency\Autoloader')
278            ->when($result = SUT::dnew($classname))
279            ->then
280                ->object($result)
281                    ->isInstanceOf($classname);
282    }
283
284    public function case_dnew_unknown_class()
285    {
286        $this
287            ->given($this->function->spl_autoload_call = null)
288            ->exception(function () {
289                SUT::dnew('Foo');
290            })
291                ->isInstanceOf('ReflectionException');
292    }
293
294    public function case_get_loaded_classes()
295    {
296        $this
297            ->given(
298                $declaredClasses                      = get_declared_classes(),
299                $this->function->get_declared_classes = $declaredClasses
300            )
301            ->when($result = SUT::getLoadedClasses())
302            ->then
303                ->array($result)
304                    ->isEqualTo($declaredClasses);
305    }
306
307    public function case_register()
308    {
309        $self = $this;
310
311        $this
312            ->given($autoloader = new SUT())
313            ->when($result = $autoloader->register())
314            ->then
315                ->boolean($result)
316                    ->isTrue()
317                ->array($autoloader->getRegisteredAutoloaders())
318                    ->isEqualTo(spl_autoload_functions());
319    }
320
321    public function case_unregister()
322    {
323        $this
324            ->given(
325                $autoloader               = new SUT(),
326                $oldRegisteredAutoloaders = $autoloader->getRegisteredAutoloaders()
327            )
328            ->when($result = $autoloader->register())
329            ->then
330                ->boolean($result)
331                    ->isTrue()
332                ->integer(count($autoloader->getRegisteredAutoloaders()))
333                    ->isEqualTo(count($oldRegisteredAutoloaders) + 1)
334
335            ->when($result = $autoloader->unregister())
336            ->then
337                ->boolean($result)
338                    ->isTrue()
339                ->array($autoloader->getRegisteredAutoloaders())
340                    ->isEqualTo($oldRegisteredAutoloaders);
341    }
342}
343