Commit | Line | Data |
---|---|---|
728bbd5b TO |
1 | <?php |
2 | namespace Civi; | |
3 | ||
4 | use PDO; | |
5 | use PDOException; | |
6 | ||
7 | /** | |
8 | * Class Test | |
9 | * | |
10 | * A facade for managing the test environment. | |
11 | */ | |
12 | class Test { | |
13 | ||
14 | /** | |
15 | * @var array | |
16 | */ | |
17 | private static $singletons = array(); | |
18 | ||
19 | /** | |
20 | * Get the data source used for testing. | |
21 | * | |
22 | * @param string|NULL $part | |
23 | * One of NULL, 'hostspec', 'port', 'username', 'password', 'database'. | |
24 | * @return string|array|NULL | |
25 | * If $part is omitted, return full DSN array. | |
26 | * If $part is a string, return that part of the DSN. | |
27 | */ | |
28 | public static function dsn($part = NULL) { | |
29 | if (!isset(self::$singletons['dsn'])) { | |
30 | require_once "DB.php"; | |
31 | self::$singletons['dsn'] = \DB::parseDSN(CIVICRM_DSN); | |
32 | } | |
33 | ||
34 | if ($part === NULL) { | |
35 | return self::$singletons['dsn']; | |
36 | } | |
37 | ||
38 | if (isset(self::$singletons['dsn'][$part])) { | |
39 | return self::$singletons['dsn'][$part]; | |
40 | } | |
41 | ||
42 | return NULL; | |
43 | } | |
44 | ||
45 | /** | |
46 | * Get a connection to the test database. | |
47 | * | |
48 | * @return PDO | |
49 | */ | |
50 | public static function pdo() { | |
51 | if (!isset(self::$singletons['pdo'])) { | |
52 | $dsninfo = self::dsn(); | |
53 | $host = $dsninfo['hostspec']; | |
54 | $port = @$dsninfo['port']; | |
55 | try { | |
56 | self::$singletons['pdo'] = new PDO("mysql:host={$host}" . ($port ? ";port=$port" : ""), | |
57 | $dsninfo['username'], $dsninfo['password'], | |
58 | array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE) | |
59 | ); | |
60 | } | |
61 | catch (PDOException $e) { | |
62 | echo "Can't connect to MySQL server:" . PHP_EOL . $e->getMessage() . PHP_EOL; | |
63 | exit(1); | |
64 | } | |
65 | } | |
66 | return self::$singletons['pdo']; | |
67 | } | |
68 | ||
69 | /** | |
33545abf | 70 | * Create a builder for the headless environment. |
728bbd5b TO |
71 | * |
72 | * @return \Civi\Test\CiviEnvBuilder | |
73 | * | |
74 | * @code | |
75 | * \Civi\Test::headless()->apply(); | |
76 | * \Civi\Test::headless()->sqlFile('ex.sql')->apply(); | |
77 | * @endCode | |
78 | */ | |
79 | public static function headless() { | |
80 | $civiRoot = dirname(__DIR__); | |
33545abf | 81 | $builder = new \Civi\Test\CiviEnvBuilder('CiviEnvBuilder'); |
728bbd5b TO |
82 | $builder |
83 | ->callback(function ($ctx) { | |
84 | if (CIVICRM_UF !== 'UnitTests') { | |
85 | throw new \RuntimeException("\\Civi\\Test::headless() requires CIVICRM_UF=UnitTests"); | |
86 | } | |
87 | $dbName = \Civi\Test::dsn('database'); | |
88 | echo "Installing {$dbName} schema\n"; | |
89 | \Civi\Test::schema()->dropAll(); | |
33545abf | 90 | }, 'headless-drop') |
728bbd5b TO |
91 | ->sqlFile($civiRoot . "/sql/civicrm.mysql") |
92 | ->sql("DELETE FROM civicrm_extension") | |
93 | ->callback(function ($ctx) { | |
94 | \Civi\Test::data()->populate(); | |
95 | }, 'populate'); | |
96 | return $builder; | |
97 | } | |
98 | ||
33545abf TO |
99 | /** |
100 | * Create a builder for end-to-end testing on the live environment. | |
101 | * | |
102 | * @return \Civi\Test\CiviEnvBuilder | |
103 | * | |
104 | * @code | |
105 | * \Civi\Test::e2e()->apply(); | |
106 | * \Civi\Test::e2e()->install('foo.bar')->apply(); | |
107 | * @endCode | |
108 | */ | |
109 | public static function e2e() { | |
110 | $builder = new \Civi\Test\CiviEnvBuilder('CiviEnvBuilder'); | |
111 | $builder | |
112 | ->callback(function ($ctx) { | |
113 | if (CIVICRM_UF === 'UnitTests') { | |
114 | throw new \RuntimeException("\\Civi\\Test::e2e() requires a real CMS. Found CIVICRM_UF=UnitTests."); | |
115 | } | |
116 | }, 'e2e-check'); | |
117 | return $builder; | |
118 | } | |
119 | ||
728bbd5b TO |
120 | /** |
121 | * @return \Civi\Test\Schema | |
122 | */ | |
123 | public static function schema() { | |
124 | if (!isset(self::$singletons['schema'])) { | |
125 | self::$singletons['schema'] = new \Civi\Test\Schema(); | |
126 | } | |
127 | return self::$singletons['schema']; | |
128 | } | |
129 | ||
130 | ||
131 | /** | |
132 | * @return \Civi\Test\Data | |
133 | */ | |
134 | public static function data() { | |
135 | if (!isset(self::$singletons['data'])) { | |
136 | self::$singletons['data'] = new \Civi\Test\Data('CiviTesterData'); | |
137 | } | |
138 | return self::$singletons['data']; | |
139 | } | |
140 | ||
141 | /** | |
142 | * Prepare and execute a batch of SQL statements. | |
143 | * | |
144 | * @param string $query | |
145 | * @return bool | |
146 | */ | |
147 | public static function execute($query) { | |
148 | $pdo = \Civi\Test::pdo(); | |
149 | ||
150 | $string = preg_replace("/^#[^\n]*$/m", "\n", $query); | |
151 | $string = preg_replace("/^(--[^-]).*/m", "\n", $string); | |
152 | ||
153 | $queries = preg_split('/;\s*$/m', $string); | |
154 | foreach ($queries as $query) { | |
155 | $query = trim($query); | |
156 | if (!empty($query)) { | |
157 | $result = $pdo->query($query); | |
158 | if ($pdo->errorCode() == 0) { | |
159 | continue; | |
160 | } | |
161 | else { | |
162 | var_dump($result); | |
163 | var_dump($pdo->errorInfo()); | |
164 | // die( "Cannot execute $query: " . $pdo->errorInfo() ); | |
165 | } | |
166 | } | |
167 | } | |
168 | return TRUE; | |
169 | } | |
170 | ||
171 | } |