Passed
Pull Request — master (#488)
by
unknown
12:22
created

ContextTest::tearDownAfterClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\SqlParser\Tests\Lexer;
6
7
use PhpMyAdmin\SqlParser\Context;
8
use PhpMyAdmin\SqlParser\Tests\TestCase;
9
10
use function class_exists;
11
12
class ContextTest extends TestCase
13
{
14
    public static function tearDownAfterClass(): void
15
    {
16
        Context::setMode();
17
    }
18
19
    public function testLoad(): void
20
    {
21
        // Default context is 5.7.0.
22
        $this->assertEquals('\\PhpMyAdmin\\SqlParser\\Contexts\\ContextMySql50700', Context::$loadedContext);
23
        $this->assertArrayHasKey('STORED', Context::$keywords);
24
        $this->assertArrayNotHasKey('AUTHORS', Context::$keywords);
25
26
        // Restoring context.
27
        Context::load('');
28
        $this->assertEquals('\\PhpMyAdmin\\SqlParser\\Contexts\\ContextMySql50700', Context::$defaultContext);
29
        $this->assertArrayHasKey('STORED', Context::$keywords);
30
        $this->assertArrayNotHasKey('AUTHORS', Context::$keywords);
31
    }
32
33
    /**
34
     * Test for loading closest SQL context
35
     *
36
     * @dataProvider contextLoadingProvider
37
     */
38
    public function testLoadClosest(string $context, string|null $expected): void
39
    {
40
        $this->assertEquals($expected, Context::loadClosest($context));
41
        if ($expected !== null) {
42
            $this->assertEquals('\\PhpMyAdmin\\SqlParser\\Contexts\\Context' . $expected, Context::$loadedContext);
43
            $this->assertTrue(class_exists(Context::$loadedContext));
44
        }
45
46
        // Restoring context.
47
        Context::load('');
48
    }
49
50
    /**
51
     * @return array<string, array<int, string|null>>
52
     * @psalm-return array<string, array{string, (string|null)}>
53
     */
54
    public static function contextLoadingProvider(): array
55
    {
56
        return [
57
            'MySQL match' => [
58
                'MySql50500',
59
                'MySql50500',
60
            ],
61
            'MySQL strip' => [
62
                'MySql50712',
63
                'MySql50700',
64
            ],
65
            'MySQL fallback' => [
66
                'MySql99999',
67
                'MySql50700',
68
            ],
69
            'MariaDB match' => [
70
                'MariaDb100000',
71
                'MariaDb100000',
72
            ],
73
            'MariaDB stripg' => [
74
                'MariaDb109900',
75
                'MariaDb100000',
76
            ],
77
            'MariaDB fallback' => [
78
                'MariaDb990000',
79
                'MariaDb100300',
80
            ],
81
            'Invalid' => [
82
                'Sql',
83
                null,
84
            ],
85
        ];
86
    }
87
88
    /**
89
     * @dataProvider contextNamesProvider
90
     */
91
    public function testLoadAll(string $context): void
92
    {
93
        Context::load($context);
94
        $this->assertEquals('\\PhpMyAdmin\\SqlParser\\Contexts\\Context' . $context, Context::$loadedContext);
95
96
        // Restoring context.
97
        Context::load('');
98
    }
99
100
    /**
101
     * @return string[][]
102
     */
103
    public static function contextNamesProvider(): array
104
    {
105
        return [
106
            ['MySql50000'],
107
            ['MySql50100'],
108
            ['MySql50500'],
109
            ['MySql50600'],
110
            ['MySql50700'],
111
            ['MySql80000'],
112
            ['MariaDb100000'],
113
            ['MariaDb100100'],
114
            ['MariaDb100200'],
115
            ['MariaDb100300'],
116
        ];
117
    }
118
119
    public function testLoadError(): void
120
    {
121
        $this->assertFalse(Context::load('Foo'));
122
    }
123
124
    /**
125
     * @param int|string $mode
126
     *
127
     * @dataProvider providerForTestMode
128
     */
129
    public function testMode($mode, int $expected): void
130
    {
131
        Context::setMode($mode);
132
        $this->assertSame($expected, Context::getMode());
133
    }
134
135
    /**
136
     * @return array<int, array<int, int|string>>
137
     * @psalm-return list<array{int|string, int}>
138
     */
139
    public static function providerForTestMode(): array
140
    {
141
        return [
142
            [0, Context::SQL_MODE_NONE],
143
            [1, 1],
144
            ['', Context::SQL_MODE_NONE],
145
            ['invalid', Context::SQL_MODE_NONE],
146
            ['ALLOW_INVALID_DATES', Context::SQL_MODE_ALLOW_INVALID_DATES],
147
            ['ANSI_QUOTES', Context::SQL_MODE_ANSI_QUOTES],
148
            ['COMPAT_MYSQL', Context::SQL_MODE_COMPAT_MYSQL],
149
            ['ERROR_FOR_DIVISION_BY_ZERO', Context::SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO],
150
            ['HIGH_NOT_PRECEDENCE', Context::SQL_MODE_HIGH_NOT_PRECEDENCE],
151
            ['IGNORE_SPACE', Context::SQL_MODE_IGNORE_SPACE],
152
            ['NO_AUTO_CREATE_USER', Context::SQL_MODE_NO_AUTO_CREATE_USER],
153
            ['NO_AUTO_VALUE_ON_ZERO', Context::SQL_MODE_NO_AUTO_VALUE_ON_ZERO],
154
            ['NO_BACKSLASH_ESCAPES', Context::SQL_MODE_NO_BACKSLASH_ESCAPES],
155
            ['NO_DIR_IN_CREATE', Context::SQL_MODE_NO_DIR_IN_CREATE],
156
            ['NO_ENGINE_SUBSTITUTION', Context::SQL_MODE_NO_ENGINE_SUBSTITUTION],
157
            ['NO_FIELD_OPTIONS', Context::SQL_MODE_NO_FIELD_OPTIONS],
158
            ['NO_KEY_OPTIONS', Context::SQL_MODE_NO_KEY_OPTIONS],
159
            ['NO_TABLE_OPTIONS', Context::SQL_MODE_NO_TABLE_OPTIONS],
160
            ['NO_UNSIGNED_SUBTRACTION', Context::SQL_MODE_NO_UNSIGNED_SUBTRACTION],
161
            ['NO_ZERO_DATE', Context::SQL_MODE_NO_ZERO_DATE],
162
            ['NO_ZERO_IN_DATE', Context::SQL_MODE_NO_ZERO_IN_DATE],
163
            ['ONLY_FULL_GROUP_BY', Context::SQL_MODE_ONLY_FULL_GROUP_BY],
164
            ['PIPES_AS_CONCAT', Context::SQL_MODE_PIPES_AS_CONCAT],
165
            ['REAL_AS_FLOAT', Context::SQL_MODE_REAL_AS_FLOAT],
166
            ['STRICT_ALL_TABLES', Context::SQL_MODE_STRICT_ALL_TABLES],
167
            ['STRICT_TRANS_TABLES', Context::SQL_MODE_STRICT_TRANS_TABLES],
168
            ['NO_ENCLOSING_QUOTES', Context::SQL_MODE_NO_ENCLOSING_QUOTES],
169
            ['ANSI', Context::SQL_MODE_ANSI],
170
            ['DB2', Context::SQL_MODE_DB2],
171
            ['MAXDB', Context::SQL_MODE_MAXDB],
172
            ['MSSQL', Context::SQL_MODE_MSSQL],
173
            ['ORACLE', Context::SQL_MODE_ORACLE],
174
            ['POSTGRESQL', Context::SQL_MODE_POSTGRESQL],
175
            ['TRADITIONAL', Context::SQL_MODE_TRADITIONAL],
176
        ];
177
    }
178
179
    public function testModeWithCombinedModes(): void
180
    {
181
        Context::setMode(
182
            Context::SQL_MODE_REAL_AS_FLOAT | Context::SQL_MODE_ANSI_QUOTES | Context::SQL_MODE_IGNORE_SPACE
183
        );
184
        $this->assertSame(
185
            Context::SQL_MODE_REAL_AS_FLOAT | Context::SQL_MODE_ANSI_QUOTES | Context::SQL_MODE_IGNORE_SPACE,
186
            Context::getMode()
187
        );
188
        $this->assertTrue(Context::hasMode(Context::SQL_MODE_REAL_AS_FLOAT | Context::SQL_MODE_IGNORE_SPACE));
189
        $this->assertTrue(Context::hasMode(Context::SQL_MODE_ANSI_QUOTES));
190
        $this->assertFalse(Context::hasMode(Context::SQL_MODE_REAL_AS_FLOAT | Context::SQL_MODE_ALLOW_INVALID_DATES));
191
        $this->assertFalse(Context::hasMode(Context::SQL_MODE_ALLOW_INVALID_DATES));
192
193
        Context::setMode(Context::SQL_MODE_TRADITIONAL);
194
        $this->assertSame(Context::SQL_MODE_TRADITIONAL, Context::getMode());
195
196
        Context::setMode();
197
        $this->assertSame(Context::SQL_MODE_NONE, Context::getMode());
198
    }
199
200
    public function testModeWithString(): void
201
    {
202
        Context::setMode('REAL_AS_FLOAT,ANSI_QUOTES,IGNORE_SPACE');
203
        $this->assertSame(
204
            Context::SQL_MODE_REAL_AS_FLOAT | Context::SQL_MODE_ANSI_QUOTES | Context::SQL_MODE_IGNORE_SPACE,
205
            Context::getMode()
206
        );
207
        $this->assertTrue(Context::hasMode(Context::SQL_MODE_REAL_AS_FLOAT | Context::SQL_MODE_IGNORE_SPACE));
208
        $this->assertTrue(Context::hasMode(Context::SQL_MODE_ANSI_QUOTES));
209
        $this->assertFalse(Context::hasMode(Context::SQL_MODE_REAL_AS_FLOAT | Context::SQL_MODE_ALLOW_INVALID_DATES));
210
        $this->assertFalse(Context::hasMode(Context::SQL_MODE_ALLOW_INVALID_DATES));
211
212
        Context::setMode('TRADITIONAL');
213
        $this->assertSame(Context::SQL_MODE_TRADITIONAL, Context::getMode());
214
215
        Context::setMode('');
216
        $this->assertSame(Context::SQL_MODE_NONE, Context::getMode());
217
    }
218
219
    public function testEscape(): void
220
    {
221
        Context::setMode(Context::SQL_MODE_NO_ENCLOSING_QUOTES);
222
        $this->assertEquals('test', Context::escape('test'));
223
224
        Context::setMode(Context::SQL_MODE_ANSI_QUOTES);
225
        $this->assertEquals('"test"', Context::escape('test'));
226
227
        Context::setMode();
228
        $this->assertEquals('`test`', Context::escape('test'));
229
230
        $this->assertEquals(['`a`', '`b`'], Context::escapeAll(['a', 'b']));
231
    }
232
233
    public function testEscapeAll(): void
234
    {
235
        Context::setMode();
236
        $this->assertEquals(['`a`', '`b`'], Context::escapeAll(['a', 'b']));
237
    }
238
}
239