Passed
Push — pulls/good-things-from-phpstan ( 7312f2...8f8b5f )
by Sam
10:36
created

MySQLiConnectorTest::testUtf8mb4UnicodeCollation()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 17
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 25
rs 9.7
1
<?php
2
3
namespace SilverStripe\ORM\Tests;
4
5
use SilverStripe\Dev\SapphireTest;
6
use SilverStripe\Dev\TestOnly;
7
use SilverStripe\ORM\Tests\MySQLiConnectorTest\MySQLiConnector;
8
use SilverStripe\ORM\DB;
9
10
/**
11
 * @requires extension mysqli
12
 */
13
class MySQLiConnectorTest extends SapphireTest implements TestOnly
14
{
15
    /**
16
     * @dataProvider charsetProvider
17
     */
18
    public function testConnectionCharsetControl($charset, $defaultCollation)
19
    {
20
        $config = DB::getConfig();
21
        $config['charset'] = $charset;
22
        $config['database'] = 'information_schema';
23
24
        if (strtolower(substr($config['type'], 0, 5)) !== 'mysql') {
25
            return $this->markTestSkipped('The test only relevant for MySQL');
26
        }
27
28
        $connector = new MySQLiConnector();
29
        $connector->connect($config);
30
        $connection = $connector->getMysqliConnection();
31
32
        $cset = $connection->get_charset();
33
34
        $this->assertEquals($charset, $cset->charset);
35
        $this->assertEquals($defaultCollation, $cset->collation);
36
37
        unset($cset, $connection, $connector, $config);
38
    }
39
40
    /**
41
     * @depends testConnectionCharsetControl
42
     * @dataProvider charsetProvider
43
     */
44
    public function testConnectionCollationControl($charset, $defaultCollation, $customCollation)
45
    {
46
        $config = DB::getConfig();
47
        $config['charset'] = $charset;
48
        $config['collation'] = $customCollation;
49
        $config['database'] = 'information_schema';
50
51
        if (strtolower(substr($config['type'], 0, 5)) !== 'mysql') {
52
            return $this->markTestSkipped('The test only relevant for MySQL');
53
        }
54
55
        $connector = new MySQLiConnector();
56
        $connector->connect($config);
57
        $connection = $connector->getMysqliConnection();
58
59
        $cset = $connection->get_charset();
60
61
        $this->assertEquals($charset, $cset->charset);
62
63
        /* Warning! This is a MySQLi limitation.
64
         * If it changes in the future versions, this test may break.
65
         * We are still testing for it as a limitation and a
66
         * reminder that it exists.
67
         *
68
         * To make sure that we actually have correct collation see
69
         *  - testUtf8mb4GeneralCollation
70
         *  - testUtf8mb4UnicodeCollation
71
         */
72
        $this->assertEquals(
73
            $defaultCollation,
74
            $cset->collation,
75
            'This is an issue with mysqli. It always returns "default" collation, even if another is active'
76
        );
77
78
        $cset = $connection->query('show variables like "character_set_connection"')->fetch_array()[1];
79
        $collation = $connection->query('show variables like "collation_connection"')->fetch_array()[1];
80
81
        $this->assertEquals($charset, $cset);
82
        $this->assertEquals($customCollation, $collation);
83
84
        $connection->close();
85
        unset($cset, $connection, $connector, $config);
86
    }
87
88
    public function charsetProvider()
89
    {
90
        return [
91
            ['ascii', 'ascii_general_ci', 'ascii_bin'],
92
            ['utf8', 'utf8_general_ci', 'utf8_unicode_520_ci'],
93
            ['utf8mb4', 'utf8mb4_general_ci', 'utf8mb4_unicode_520_ci']
94
        ];
95
    }
96
97
    public function testUtf8mb4GeneralCollation()
98
    {
99
        $charset = 'utf8mb4';
100
        $collation = 'utf8mb4_general_ci';
101
102
        $config = DB::getConfig();
103
        $config['charset'] = $charset;
104
        $config['collation'] = $collation;
105
        $config['database'] = 'information_schema';
106
107
        if (strtolower(substr($config['type'], 0, 5)) !== 'mysql') {
108
            return $this->markTestSkipped('The test only relevant for MySQL');
109
        }
110
111
        $connector = new MySQLiConnector();
112
        $connector->connect($config, true);
113
        $connection = $connector->getMysqliConnection();
114
115
        $result = $connection->query(
116
            "select `a`.`value` from (select 'rst' `value` union select 'rßt' `value`) `a` order by `value`"
117
        )->fetch_all();
118
119
        $this->assertCount(1, $result, '`utf8mb4_general_ci` handles both values as equal to "rst"');
120
        $this->assertEquals('rst', $result[0][0]);
121
    }
122
123
    public function testUtf8mb4UnicodeCollation()
124
    {
125
        $charset = 'utf8mb4';
126
        $collation = 'utf8mb4_unicode_ci';
127
128
        $config = DB::getConfig();
129
        $config['charset'] = $charset;
130
        $config['collation'] = $collation;
131
        $config['database'] = 'information_schema';
132
133
        if (strtolower(substr($config['type'], 0, 5)) !== 'mysql') {
134
            return $this->markTestSkipped('The test only relevant for MySQL');
135
        }
136
137
        $connector = new MySQLiConnector();
138
        $connector->connect($config, true);
139
        $connection = $connector->getMysqliConnection();
140
141
        $result = $connection->query(
142
            "select `a`.`value` from (select 'rst' `value` union select 'rßt' `value`) `a` order by `value`"
143
        )->fetch_all();
144
145
        $this->assertCount(2, $result, '`utf8mb4_unicode_ci` must recognise "rst" and "rßt" as different values');
146
        $this->assertEquals('rßt', $result[0][0]);
147
        $this->assertEquals('rst', $result[1][0]);
148
    }
149
}
150