1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core; 18 19 use ReflectionClass; 20 use mysqli; 21 use moodle_database, mysqli_native_moodle_database; 22 use moodle_exception; 23 24 /** 25 * Test specific features of the MySql dml. 26 * 27 * @package core 28 * @category test 29 * @copyright 2023 Catalyst IT 30 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 * @covers \mysqli_native_moodle_database 32 */ 33 class mysqli_native_moodle_database_test extends \advanced_testcase { 34 35 /** 36 * Set up. 37 */ 38 public function setUp(): void { 39 global $DB; 40 parent::setUp(); 41 // Skip tests if not using Postgres. 42 if (!($DB instanceof mysqli_native_moodle_database)) { 43 $this->markTestSkipped('MySql-only test'); 44 } 45 } 46 47 /** 48 * SSL connection helper. 49 * 50 * @param bool|null $compress 51 * @param string|null $ssl 52 * @return mysqli 53 * @throws moodle_exception 54 */ 55 public function new_connection(?bool $compress = false, ?string $ssl = null): mysqli { 56 global $DB; 57 58 // Open new connection. 59 $cfg = $DB->export_dbconfig(); 60 if (!isset($cfg->dboptions)) { 61 $cfg->dboptions = []; 62 } 63 64 $cfg->dboptions['clientcompress'] = $compress; 65 $cfg->dboptions['ssl'] = $ssl; 66 67 // Get a separate disposable db connection handle with guaranteed 'readonly' config. 68 $db2 = moodle_database::get_driver_instance($cfg->dbtype, $cfg->dblibrary); 69 $db2->raw_connect($cfg->dbhost, $cfg->dbuser, $cfg->dbpass, $cfg->dbname, $cfg->prefix, $cfg->dboptions); 70 71 $reflector = new ReflectionClass($db2); 72 $rp = $reflector->getProperty('mysqli'); 73 $rp->setAccessible(true); 74 return $rp->getValue($db2); 75 } 76 77 /** 78 * Test client compression helper. 79 * 80 * @param mysqli $mysqli 81 * @return array 82 */ 83 public function connection_status($mysqli): array { 84 $mysqli->query("SELECT * FROM INFORMATION_SCHEMA.TABLES"); 85 86 $stats = []; 87 foreach ($mysqli->query('SHOW SESSION STATUS')->fetch_all(MYSQLI_ASSOC) as $r) { 88 $stats[$r['Variable_name']] = $r['Value']; 89 } 90 return $stats; 91 } 92 93 /** 94 * Test client compression. 95 * 96 * @return void 97 */ 98 public function test_client_compression(): void { 99 $mysqli = $this->new_connection(); 100 $stats = $this->connection_status($mysqli); 101 $this->assertEquals('OFF', $stats['Compression']); 102 $sent = $stats['Bytes_sent']; 103 104 $mysqlic = $this->new_connection(true); 105 $stats = $this->connection_status($mysqlic); 106 $this->assertEquals('ON', $stats['Compression']); 107 $sentc = $stats['Bytes_sent']; 108 109 $this->assertLessThan($sent, $sentc); 110 } 111 112 /** 113 * Test SSL connection. 114 * 115 * Well as much as we can, mysqli does not reliably report connect errors. 116 * @return void 117 */ 118 public function test_ssl_connection(): void { 119 try { 120 $mysqli = $this->new_connection(false, 'require'); 121 // Either connect ... 122 $this->assertNotNull($mysqli); 123 } catch (moodle_exception $e) { 124 // ... or fail. 125 // Unfortunately we cannot be sure with the error string. 126 $this->markTestIncomplete('SSL not supported?'); 127 } 128 129 try { 130 $mysqli = $this->new_connection(false, 'verify-full'); 131 // Either connect ... 132 $this->assertNotNull($mysqli); 133 } catch (moodle_exception $e) { 134 // ... or fail with invalid cert. 135 // Same as above, but we cannot really expect properly signed cert, so ignore. 136 } 137 138 $this->expectException(moodle_exception::class); 139 $this->new_connection(false, 'invalid-mode'); 140 } 141 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body