Merge branch 'MDL-55404-master' of git://github.com/cameron1729/moodle
[moodle.git] / lib / tests / upgrade_util_test.php
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/>.
17 /**
18  * Upgrade utility class  tests.
19  *
20  * @package    core
21  * @copyright  2016 Cameron Ball <cameron@cameron1729.xyz>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
27 /**
28  * Upgrade utility class tests.
29  *
30  * @package   core
31  * @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
32  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33  */
34 class upgrade_util_testcase extends advanced_testcase {
36     /**
37      * A cURL version that supports TLS 1.2.
38      */
39     const VALID_CURL_VERSION = 467456;
41     /**
42      * A cURL version that does not support TLS 1.2.
43      */
44     const INVALID_CURL_VERSION = 467455;
46     /**
47      * The value of PHP_ZTS when thread safety is enabled.
48      */
49     const PHP_ZTS_ENABLED = 1;
51     /**
52      * The value of PHP_ZTS when thread safety is disabled.
53      */
54     const PHP_ZTS_DISABLED = 0;
56     /**
57      * Test PHP/cURL validation.
58      *
59      * @dataProvider validate_php_curl_tls_testcases()
60      * @param array $curlinfo server curl_version array
61      * @param int   $zts      0 or 1 as defined by PHP_ZTS
62      * @param bool  $expected expected result
63      */
64     public function test_validate_php_curl_tls($curlinfo, $zts, $expected) {
65         $expected === true && $this->assertTrue(\core\upgrade\util::validate_php_curl_tls($curlinfo, $zts));
66         $expected === false && $this->assertFalse(\core\upgrade\util::validate_php_curl_tls($curlinfo, $zts));
67     }
69     /**
70      * Test cases for validate_php_curl_tls test.
71      */
72     public function validate_php_curl_tls_testcases() {
73         $base = curl_version();
75         return [
76             'Not threadsafe - Valid SSL (GnuTLS)' => [
77                 ['ssl_version' => 'GnuTLS/4.20'] + $base,
78                 self::PHP_ZTS_DISABLED,
79                 true
80             ],
81             'Not threadsafe - Valid SSL (OpenSSL)' => [
82                 ['ssl_version' => 'OpenSSL'] + $base,
83                 self::PHP_ZTS_DISABLED,
84                 true
85             ],
86             'Not threadsafe - Valid SSL (WinSSL)' => [
87                 ['ssl_version' => 'WinSSL'] + $base,
88                 self::PHP_ZTS_DISABLED,
89                 true
90             ],
91             'Not threadsafe - Invalid SSL' => [
92                 ['ssl_version' => ''] + $base,
93                 self::PHP_ZTS_DISABLED,
94                 false
95             ],
96             'Threadsafe - Valid SSL (OpenSSL)' => [
97                 ['ssl_version' => 'OpenSSL/1729'] + $base,
98                 self::PHP_ZTS_ENABLED,
99                 true
100             ],
101             'Threadsafe - Valid SSL (GnuTLS)' => [
102                 ['ssl_version' => 'GnuTLS/3.14'] + $base,
103                 self::PHP_ZTS_ENABLED,
104                 true
105             ],
106             'Threadsafe - Invalid SSL' => [
107                 ['ssl_version' => ''] + $base,
108                 self::PHP_ZTS_ENABLED,
109                 false
110             ],
111             'Threadsafe - Invalid SSL (but not empty)' => [
112                 ['ssl_version' => 'Not GnuTLS or OpenSSL'] + $base,
113                 self::PHP_ZTS_ENABLED,
114                 false
115             ]
116         ];
117     }
119     /**
120      * Test various combinations of SSL/TLS libraries.
121      *
122      * @dataProvider can_use_tls12_testcases
123      * @param array $environment the server environment
124      * @param bool  $expected    expected result
125      */
126     public function test_can_use_tls12($environment, $expected) {
127         $curlinfo = $environment['curl_version'] + curl_version();
129         if ($curlinfo['version_number'] >= self::VALID_CURL_VERSION && !defined('CURL_SSLVERSION_TLSv1_2')) {
130             define('CURL_SSLVERSION_TLSv1_2', 6);
131         }
133         $expected === true && $this->assertTrue(\core\upgrade\util::can_use_tls12($curlinfo, $environment['uname']));
134         $expected === false && $this->assertFalse(\core\upgrade\util::can_use_tls12($curlinfo, $environment['uname']));
135     }
137     /**
138      * Test cases for the can_use_tls test.
139      *
140      * @return array of testcases
141      */
142     public function can_use_tls12_testcases() {
143         $versionmatrix = [
144             'OpenSSL'         => ['Older' => '0.9.8o',  'Min required' => '1.0.1c',           'Newer' => '1.0.1t'],
145             'GnuTLS'          => ['Older' => '1.5.0',   'Min requires' => '1.7.1',            'Newer' => '1.8.1'],
146             'NSS'             => ['Older' => '3.14.15', 'Min required' => '3.15.1 Basic ECC', 'Newer' => '3.17.2 Basic ECC'],
147             'CyaSSL'          => ['Older' => '0.9.9',   'Min required' => '1.1.0',            'Newer' => '1.2.0'],
148             'wolfSSL'         => ['Older' => '1.0.0',   'Min required' => '1.1.0',            'Newer' => '1.2.0'],
149             'WinSSL'          => ['Older' => '5.1',     'Min required' => '6.1',              'Newer' => '7.0'],
150             'SecureTransport' => ['Older' => '10.7.5',  'Min required' => '10.8.0',           'Newer' => '10.9.0']
151         ];
153         // This will generate an array of testcases from the matrix above.
154         // It generates one testcase for every version. If the version is too
155         // old or the cURL version (passed as an argument) is too old, the
156         // expected result of the testcase is false. Otherwise it is true.
157         //
158         // Each testcase is given a name like WinSSL/Valid env/Min required.
159         // The first part is the SSL/TLS library, the second part is whether
160         // or not the environment is valid (i.e., we are using a valid/invalid
161         // cURL version. The final part says which version of the SSL/TLS library
162         // is being used (i.e., Older, Min required or Newer).
163         $generatetestcases = function($curlversion) use ($versionmatrix) {
164             return array_reduce(array_keys($versionmatrix), function($carry, $sslflavour) use ($versionmatrix, $curlversion) {
165                 return $carry + array_reduce(array_keys($versionmatrix[$sslflavour]), function($carry, $sslversion)
166                         use ($versionmatrix, $curlversion, $sslflavour) {
167                     $env = $curlversion == self::VALID_CURL_VERSION ? 'Valid' : 'Invalid';
168                     $exceptions = ['WinSSL', 'SecureTransport'];
169                     $versionsuffix = in_array($sslflavour, $exceptions) ? '' : '/' . $versionmatrix[$sslflavour][$sslversion];
170                     return $carry + [$sslflavour . '/' . $env. ' env/' . $sslversion => [[
171                         'curl_version' => [
172                             'ssl_version' => $sslflavour . $versionsuffix,
173                             'version_number' => $curlversion
174                         ],
175                         'uname' => in_array($sslflavour, $exceptions) ? $versionmatrix[$sslflavour][$sslversion] : php_uname('r')
176                     ], $sslversion != 'Older' && $curlversion != self::INVALID_CURL_VERSION]];
177                 }, []);
178             }, []);
179         };
181         return $generatetestcases(self::VALID_CURL_VERSION) + $generatetestcases(self::INVALID_CURL_VERSION);
182     }