Completed
Pull Request — master (#63)
by Eugene
05:25
created

TestCase::handleCustomAnnotations()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 12
nop 1
dl 0
loc 23
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the Tarantool Client package.
5
 *
6
 * (c) Eugene Leonovich <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Tarantool\Client\Tests\Integration;
15
16
use PHPUnit\Framework\TestCase as BaseTestCase;
17
use PHPUnit\Util\Test;
18
use Tarantool\Client\Client;
19
use Tarantool\Client\Connection\Connection;
20
use Tarantool\Client\Connection\StreamConnection;
21
use Tarantool\Client\Exception\CommunicationFailed;
22
use Tarantool\Client\Handler\Handler;
23
use Tarantool\Client\Request\Request;
24
25
abstract class TestCase extends BaseTestCase
26
{
27
    protected const STAT_REQUEST_SELECT = 'SELECT';
28
    protected const STAT_REQUEST_AUTH = 'AUTH';
29
30
    /**
31
     * @var Client
32
     */
33
    protected $client;
34
35
    private const REGEX_REQURES_TARANTOOL_VERSION = '/tarantool\s+?(?<version>.+?)$/i';
36
37
    public static function setUpBeforeClass() : void
38
    {
39
        $annotations = Test::parseTestMethodAnnotations(static::class);
40
41
        self::handleCustomAnnotations($annotations['class']);
42
    }
43
44
    protected function setUp() : void
45
    {
46
        $this->client = ClientBuilder::createFromEnv()->build();
47
48
        $annotations = $this->getAnnotations();
49
50
        self::handleCustomAnnotations($annotations['method']);
51
    }
52
53
    private static function handleCustomAnnotations(array $annotations) : void
54
    {
55
        if (isset($annotations['requires'])) {
56
            foreach ($annotations['requires'] as $requirement) {
57
                if (!preg_match(self::REGEX_REQURES_TARANTOOL_VERSION, $requirement, $matches)) {
58
                    continue;
59
                }
60
61
                [$major, $minor, $patch] = \sscanf($matches['version'], '%d.%d.%d');
62
                $requiredVersionId = $major * 10000 + $minor * 100 + $patch;
63
64
                if (self::getTarantoolVersionId() < $requiredVersionId) {
65
                    self::markTestSkipped(sprintf('Tarantool >= %s is required.', $matches['version']));
66
                }
67
68
                break;
69
            }
70
        }
71
72
        if (isset($annotations['eval'])) {
73
            $client = ClientBuilder::createFromEnv()->build();
74
            foreach ($annotations['eval'] as $expr) {
75
                $client->evaluate($expr);
76
            }
77
        }
78
    }
79
80
    final protected static function getTotalCalls(string $requestName) : int
81
    {
82
        $client = ClientBuilder::createFromEnv()->build();
83
84
        return $client->evaluate("return box.stat().$requestName.total")[0];
85
    }
86
87
    final protected static function getTarantoolVersionId() : int
88
    {
89
        $connection = ClientBuilder::createFromEnv()->createConnection();
90
91
        return $connection->open()->getServerVersionId();
92
    }
93
94
    final protected static function triggerUnexpectedResponse(Handler $handler, Request $initialRequest, int $sync = 0) : Connection
95
    {
96
        $connection = $handler->getConnection();
97
        $packer = $handler->getPacker();
98
        $rawRequest = $packer->pack($initialRequest, $sync);
99
100
        // write a request without reading a response
101
        $connection->open();
102
        if (!\fwrite(self::getRawStream($connection), $rawRequest)) {
103
            throw new CommunicationFailed('Unable to write request.');
104
        }
105
106
        return $connection;
107
    }
108
109
    final public static function getRawStream(StreamConnection $connection)
110
    {
111
        $prop = (new \ReflectionObject($connection))->getProperty('stream');
112
        $prop->setAccessible(true);
113
114
        return $prop->getValue($connection);
115
    }
116
}
117