Issues (63)

Tests/BdfPrimeBundleTest.php (4 issues)

1
<?php
2
3
namespace Bdf\PrimeBundle\Tests;
4
5
require_once __DIR__.'/TestKernel.php';
6
7
use Bdf\Prime\Cache\ArrayCache;
8
use Bdf\Prime\Cache\DoctrineCacheAdapter;
9
use Bdf\Prime\Configuration;
10
use Bdf\Prime\Connection\SimpleConnection;
11
use Bdf\Prime\Console\UpgraderCommand;
12
use Bdf\Prime\Locatorizable;
13
use Bdf\Prime\Migration\MigrationManager;
14
use Bdf\Prime\Platform\Sql\Types\SqlStringType;
15
use Bdf\Prime\Schema\RepositoryUpgrader;
16
use Bdf\Prime\Schema\StructureUpgraderResolverAggregate;
17
use Bdf\Prime\Schema\StructureUpgraderResolverInterface;
18
use Bdf\Prime\ServiceLocator;
19
use Bdf\Prime\Sharding\ShardingConnection;
20
use Bdf\Prime\Sharding\ShardingQuery;
21
use Bdf\Prime\Types\ArrayType;
22
use Bdf\Prime\Types\TypeInterface;
23
use Bdf\PrimeBundle\Collector\PrimeDataCollector;
24
use Bdf\PrimeBundle\DependencyInjection\Compiler\PrimeConnectionFactoryPass;
25
use Bdf\PrimeBundle\PrimeBundle;
26
use Doctrine\Common\Cache\Psr6\DoctrineProvider;
27
use PHPUnit\Framework\TestCase;
28
use Symfony\Bundle\FrameworkBundle\Console\Application;
29
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
30
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
31
use Symfony\Component\Config\Loader\LoaderInterface;
32
use Symfony\Component\Console\Command\LazyCommand;
33
use Symfony\Component\DependencyInjection\ContainerBuilder;
34
use Symfony\Component\HttpFoundation\Request;
35
use Symfony\Component\HttpKernel\Kernel;
36
use Symfony\Component\Routing\RouteCollectionBuilder;
37
38
/**
39
 * BdfSerializerBundleTest.
40
 */
41
class BdfPrimeBundleTest extends TestCase
42
{
43
    public function testDefaultConfig()
44
    {
45
        $builder = new ContainerBuilder();
46
        $bundle = new PrimeBundle();
47
        $bundle->build($builder);
48
49
        $compilerPasses = $builder->getCompiler()->getPassConfig()->getPasses();
50
        $found = 0;
51
52
        foreach ($compilerPasses as $pass) {
53
            if ($pass instanceof PrimeConnectionFactoryPass) {
54
                ++$found;
55
            }
56
        }
57
58
        $this->assertSame(1, $found);
59
    }
60
61
    public function testKernel()
62
    {
63
        $kernel = new \TestKernel('dev', true);
64
        $kernel->boot();
65
66
        $this->assertInstanceOf(ServiceLocator::class, $kernel->getContainer()->get('prime'));
67
        $this->assertSame($kernel->getContainer()->get('prime'), $kernel->getContainer()->get(ServiceLocator::class));
68
        $this->assertInstanceOf(MigrationManager::class, $kernel->getContainer()->get(MigrationManager::class));
69
        $this->assertInstanceOf(SimpleConnection::class, $kernel->getContainer()->get(ServiceLocator::class)->connection('test'));
70
    }
71
72
    /**
73
     * @return void
74
     */
75
    public function testStructureUpgrader()
76
    {
77
        if (!interface_exists(StructureUpgraderResolverInterface::class)) {
78
            $this->markTestSkipped('StructureUpgraderResolverInterface not present');
79
        }
80
81
        $kernel = new \TestKernel('dev', true);
82
        $kernel->boot();
83
84
        $this->assertInstanceOf(StructureUpgraderResolverAggregate::class, $kernel->getContainer()->get(StructureUpgraderResolverInterface::class));
85
        $this->assertInstanceOf(StructureUpgraderResolverAggregate::class, $kernel->getContainer()->get(StructureUpgraderResolverAggregate::class));
86
87
        $console = new Application($kernel);
88
        $command = $console->get(UpgraderCommand::getDefaultName());
89
90
        if ($command instanceof LazyCommand) {
91
            $command = $command->getCommand();
92
        }
93
94
        $r = new \ReflectionProperty($command, 'resolver');
95
        $r->setAccessible(true);
96
97
        $this->assertSame(
98
            $kernel->getContainer()->get(StructureUpgraderResolverAggregate::class),
99
            $r->getValue($command)
100
        );
101
102
        $upgrader = $kernel->getContainer()->get(StructureUpgraderResolverAggregate::class)->resolveByDomainClass(\TestEntity::class);
103
104
        $this->assertInstanceOf(RepositoryUpgrader::class, $upgrader);
105
        $this->assertEquals('test_', $upgrader->table()->name());
106
107
        $this->assertEquals($upgrader, $kernel->getContainer()->get(StructureUpgraderResolverAggregate::class)->resolveByMapperClass(\TestEntityMapper::class));
108
    }
109
110
    public function testCollector()
111
    {
112
        $kernel = new \TestKernel('dev', true);
113
        $kernel->boot();
114
115
        $collector = $kernel->getContainer()->get(PrimeDataCollector::class);
116
117
        $this->assertInstanceOf(PrimeDataCollector::class, $collector);
118
        $kernel->handle(Request::create('http://127.0.0.1/'));
119
120
        $this->assertGreaterThanOrEqual(3, $collector->getQueryCount());
121
122
        $queries = array_map(function ($entry) { return $entry['sql']; }, $collector->getQueries()['']);
123
        $this->assertContains('SELECT * FROM test_ WHERE id = ? LIMIT 1', $queries);
124
    }
125
126
    public function testFunctional()
127
    {
128
        $kernel = new \TestKernel('dev', true);
129
        $kernel->boot();
130
131
        \TestEntity::repository()->schema()->migrate();
132
133
        $entity = new \TestEntity(['name' => 'foo']);
134
        $entity->insert();
135
136
        $this->assertEquals([$entity], \TestEntity::all());
137
        $this->assertEquals($entity, \TestEntity::where('name', 'foo')->first());
138
    }
139
140
    public function testShardingConnection()
141
    {
142
        $kernel = new class('test', true) extends Kernel {
143
            use \Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
144
145
            public function registerBundles(): iterable
146
            {
147
                return [
148
                    new FrameworkBundle(),
149
                    new PrimeBundle(),
150
                ];
151
            }
152
153
            protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
154
            {
155
                $loader->import(__DIR__.'/Fixtures/sharding.yaml');
156
            }
157
158
            protected function configureRoutes(RouteCollectionBuilder $routes)
159
            {
160
            }
161
        };
162
163
        $kernel->boot();
164
165
        /** @var ServiceLocator $prime */
166
        $prime = $kernel->getContainer()->get(ServiceLocator::class);
167
        $this->assertInstanceOf(ShardingConnection::class, $prime->connection('test'));
168
        $this->assertInstanceOf(ShardingQuery::class, $prime->connection('test')->builder());
169
170
        /** @var SimpleConnection $connection */
171
        $connection = $prime->connection('test.shard1');
172
        $this->assertSame($prime->connection('test')->getConfiguration(), $connection->getConfiguration());
173
    }
174
175
    public function testArrayCache()
176
    {
177
        $kernel = new class('test', true) extends Kernel {
178
            use \Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
179
180
            public function registerBundles(): iterable
181
            {
182
                return [
183
                    new FrameworkBundle(),
184
                    new PrimeBundle(),
185
                ];
186
            }
187
188
            protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
189
            {
190
                $loader->import(__DIR__.'/Fixtures/array_cache.yaml');
191
            }
192
193
            protected function configureRoutes($routes)
194
            {
195
            }
196
        };
197
198
        $kernel->boot();
199
200
        /** @var ServiceLocator $prime */
201
        $prime = $kernel->getContainer()->get(ServiceLocator::class);
202
        $this->assertEquals(new ArrayCache(), $prime->mappers()->getResultCache());
203
    }
204
205
    public function testPoolCache()
206
    {
207
        $kernel = new class('test', true) extends Kernel {
208
            use \Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
209
210
            public function registerBundles(): iterable
211
            {
212
                return [
213
                    new FrameworkBundle(),
214
                    new PrimeBundle(),
215
                ];
216
            }
217
218
            protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
219
            {
220
                $c->register('custom.cache', FilesystemAdapter::class);
221
222
                $loader->import(__DIR__.'/Fixtures/pool_cache.yaml');
223
            }
224
225
            protected function configureRoutes($routes)
226
            {
227
            }
228
        };
229
230
        $kernel->boot();
231
232
        /** @var ServiceLocator $prime */
233
        $prime = $kernel->getContainer()->get(ServiceLocator::class);
234
        $this->assertEquals(new DoctrineCacheAdapter(DoctrineProvider::wrap(new FilesystemAdapter())), $prime->mappers()->getResultCache());
235
    }
236
237
    public function testGlobalConfig()
238
    {
239
        $kernel = new class('test', true) extends Kernel {
240
            use \Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
241
242
            public function registerBundles(): iterable
243
            {
244
                return [
245
                    new FrameworkBundle(),
246
                    new PrimeBundle(),
247
                ];
248
            }
249
250
            protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
251
            {
252
                $loader->import(__DIR__.'/Fixtures/config.yaml');
253
            }
254
255
            protected function configureRoutes($routes)
256
            {
257
            }
258
        };
259
260
        $kernel->boot();
261
262
        /** @var ServiceLocator $prime */
263
        $prime = $kernel->getContainer()->get(ServiceLocator::class);
264
        /** @var SimpleConnection $connection */
265
        $connection = $prime->connection('test2');
266
267
        $this->assertNotNull($connection->getConfiguration()->getSQLLogger());
268
        $this->assertTrue($connection->getConfiguration()->getAutoCommit());
269
        $this->assertInstanceOf(FooType::class, $connection->getConfiguration()->getTypes()->get('foo'));
270
        $this->assertInstanceOf(BarType::class, $connection->getConfiguration()->getTypes()->get('bar'));
271
        $this->assertInstanceOf(ArrayType::class, $connection->getConfiguration()->getTypes()->get('array'));
272
    }
273
274
    public function testConnectionConfig()
275
    {
276
        $kernel = new class('test', true) extends Kernel {
277
            use \Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
278
279
            public function registerBundles(): iterable
280
            {
281
                return [
282
                    new FrameworkBundle(),
283
                    new PrimeBundle(),
284
                ];
285
            }
286
287
            protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
288
            {
289
                $loader->import(__DIR__.'/Fixtures/config.yaml');
290
            }
291
292
            protected function configureRoutes($routes)
293
            {
294
            }
295
        };
296
297
        $kernel->boot();
298
299
        /** @var ServiceLocator $prime */
300
        $prime = $kernel->getContainer()->get(ServiceLocator::class);
301
        /** @var SimpleConnection $connection */
302
        $connection = $prime->connection('test');
303
304
        $this->assertNull($connection->getConfiguration()->getSQLLogger());
305
        $this->assertFalse($connection->getConfiguration()->getAutoCommit());
306
        $this->assertInstanceOf(BarType::class, $connection->getConfiguration()->getTypes()->get('foo'));
307
        $this->assertInstanceOf(BarType::class, $connection->getConfiguration()->getTypes()->get('bar'));
308
        $this->assertInstanceOf(ArrayType::class, $connection->getConfiguration()->getTypes()->get('array'));
309
    }
310
311
    /**
312
     * Check that destroying entity with prime unconfigured will works.
313
     */
314
    public function testEntityDestroyAfterShutdown()
315
    {
316
        $this->expectNotToPerformAssertions();
317
318
        $kernel = new \TestKernel('test', true);
319
        $kernel->boot();
320
        \TestEntity::repository()->schema()->migrate();
321
        $entity = new \TestEntity(['name' => 'foo']);
322
        $entity->insert();
323
        $kernel->shutdown();
324
        $kernel->boot();
325
        $kernel->shutdown();
326
327
        unset($entity);
328
    }
329
330
    public function testShutdownShouldDisableActiveRecord()
331
    {
332
        $kernel = new \TestKernel('test', true);
333
        $kernel->boot();
334
        $this->assertTrue(Locatorizable::isActiveRecordEnabled());
335
        $kernel->shutdown();
336
        $this->assertFalse(Locatorizable::isActiveRecordEnabled());
337
    }
338
339
    public function testCustomPlatformTypesNotSupported()
340
    {
341
        $this->expectExceptionMessage('Define platform types is only supported by bdf-prime version >= 2.1');
342
343
        if (method_exists(Configuration::class, 'addPlatformType')) {
344
            $this->markTestSkipped();
345
        }
346
347
        $kernel = new class('test', true) extends Kernel {
348
            use \Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
349
350
            public function registerBundles(): iterable
351
            {
352
                return [
353
                    new FrameworkBundle(),
354
                    new PrimeBundle(),
355
                ];
356
            }
357
358
            protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
359
            {
360
                $loader->import(__DIR__.'/Fixtures/config_with_platform_types.yaml');
361
            }
362
363
            protected function configureRoutes($routes)
364
            {
365
            }
366
        };
367
368
        $kernel->boot();
369
    }
370
371
    public function testCustomPlatformTypes()
372
    {
373
        if (!method_exists(Configuration::class, 'addPlatformType')) {
374
            $this->markTestSkipped();
375
        }
376
377
        $kernel = new class('test', true) extends Kernel {
378
            use \Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
379
380
            public function registerBundles(): iterable
381
            {
382
                return [
383
                    new FrameworkBundle(),
384
                    new PrimeBundle(),
385
                ];
386
            }
387
388
            protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
389
            {
390
                $loader->import(__DIR__.'/Fixtures/config_with_platform_types.yaml');
391
            }
392
393
            protected function configureRoutes($routes)
394
            {
395
            }
396
        };
397
398
        $kernel->boot();
399
400
        $this->assertInstanceOf(OverriddenString::class, $kernel->getContainer()->get('prime')->connection('test')->platform()->types()->resolve(''));
401
        $this->assertSame('foo', $kernel->getContainer()->get('prime')->connection('test')->toDatabase(''));
402
    }
403
}
404
405
class FooType implements TypeInterface
406
{
407
    public function fromDatabase($value, array $fieldOptions = [])
408
    {
409
        // TODO: Implement fromDatabase() method.
410
    }
411
412
    public function toDatabase($value)
413
    {
414
        // TODO: Implement toDatabase() method.
415
    }
416
417
    public function name(): string
418
    {
419
        // TODO: Implement name() method.
420
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
421
422
    public function phpType(): string
423
    {
424
        // TODO: Implement phpType() method.
425
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
426
}
427
class BarType implements TypeInterface
428
{
429
    public function fromDatabase($value, array $fieldOptions = [])
430
    {
431
        // TODO: Implement fromDatabase() method.
432
    }
433
434
    public function toDatabase($value)
435
    {
436
        // TODO: Implement toDatabase() method.
437
    }
438
439
    public function name(): string
440
    {
441
        // TODO: Implement name() method.
442
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
443
444
    public function phpType(): string
445
    {
446
        // TODO: Implement phpType() method.
447
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
448
}
449
450
class OverriddenString extends SqlStringType
451
{
452
    public function toDatabase($value)
453
    {
454
        return 'foo';
455
    }
456
}
457