forked from ThinkUpLLC/ThinkUp
/
WebTestOfUpgradeDatabase.php
381 lines (336 loc) · 17.1 KB
/
WebTestOfUpgradeDatabase.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
<?php
/**
*
* ThinkUp/tests/classes/WebTestOfUpgradeDatabase.php
*
* Copyright (c) 2009-2011 Mark Wilkie
*
* LICENSE:
*
* This file is part of ThinkUp (http://thinkupapp.com).
*
* ThinkUp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any
* later version.
*
* ThinkUp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with ThinkUp. If not, see
* <http://www.gnu.org/licenses/>.
*
*
* @author Mark Wilkie <mwilkie[at]gmail[dot]com>
* @license http://www.gnu.org/licenses/gpl.html
* @copyright 2009-2010 Mark Wilkie
*/
require_once dirname(__FILE__).'/init.tests.php';
require_once THINKUP_ROOT_PATH.'webapp/_lib/extlib/simpletest/autorun.php';
require_once THINKUP_ROOT_PATH.'webapp/config.inc.php';
require_once THINKUP_ROOT_PATH.'webapp/_lib/extlib/simpletest/web_tester.php';
class WebTestOfUpgradeDatabase extends ThinkUpBasicWebTestCase {
public function setUp() {
date_default_timezone_set('America/Los_Angeles');
parent::setUp();
$optiondao = new OptionMySQLDAO();
$this->pdo = OptionMysqlDAO::$PDO;
$this->install_dir = THINKUP_ROOT_PATH.'webapp/test_installer';
$this->installs_dir = THINKUP_ROOT_PATH.'build';
// Make sure test_installer and build directories exists
if (!file_exists($this->install_dir)) {
exec('mkdir ' . $this->install_dir);
}
if (!file_exists($this->installs_dir)) {
exec('mkdir ' . $this->installs_dir);
}
//Clean up files from test installation
exec('rm -rf ' . THINKUP_ROOT_PATH.'webapp/test_installer' . '/*');
$config = Config::getInstance();
$this->prefix = $config->getValue('table_prefix');
}
public function tearDown() {
//Clean up test installation files
exec('rm -rf ' . THINKUP_ROOT_PATH.'webapp/test_installer' . '/*');
// Delete test database created during installation process
require THINKUP_WEBAPP_PATH.'config.inc.php';
//Override default CFG values
$THINKUP_CFG['db_name'] = $this->test_database_name;
$this->testdb_helper = new ThinkUpTestDatabaseHelper();
$this->testdb_helper->drop($this->test_database_name);
parent::tearDown();
}
public function testMigrations() {
// run updates and migrations
require 'tests/migration-assertions.php';
$migrations_count = count($MIGRATIONS);
$migration_versions = array();
foreach($MIGRATIONS as $version => $migration_data) {
array_push($migration_versions, $version);
}
$migration_max_index = $migrations_count-1;
for($i = 0; $i < $migrations_count-1; $i++) {
$run_migrations = array($migration_versions[$migration_max_index] =>
$MIGRATIONS[ $migration_versions[$migration_max_index] ]);
$this->debug("Testing migration " . $migration_versions[$i] . " => "
. $migration_versions[$migration_max_index] );
$data = $this->setUpApp($migration_versions[$i], $MIGRATIONS);
$this->runMigrations($run_migrations, $migration_versions[$i]);
if($data['latest_migration_file'] && file_exists($data['latest_migration_file'])) {
unlink( $data['latest_migration_file'] );
}
$this->tearDown();
$this->restart();
$this->debug("Done Testing migration " . $migration_versions[$i] . " => "
. $migration_versions[$migration_max_index] );
$this->debug("");
}
// then test a migration from 4 that needs a snowflake uprade
$this->debug("Testing snowflake migration/update");
$run_migrations = array($migration_versions[$migration_max_index] =>
$MIGRATIONS[ $migration_versions[$migration_max_index] ]);
$this->debug("Testing migration " . $migration_versions[2] . " => ".$migration_versions[$migration_max_index]);
$data = $this->setUpApp($migration_versions[2], $MIGRATIONS);
$this->pdo->query('ALTER TABLE ' . $this->prefix .
'instances CHANGE last_post_id last_status_id bigint(11) NOT NULL');
$this->runMigrations($run_migrations, $migration_versions[$i]);
if($data['latest_migration_file'] && file_exists($data['latest_migration_file'])) {
unlink( $data['latest_migration_file'] );
}
$this->debug("Done Testing snowflake migration/update");
}
/**
* Sets up initial app
*/
private function setUpApp($version, $MIGRATIONS) {
// run updates and migrations
require 'tests/migration-assertions.php';
$this->debug("Setting up base install for upgrade: $version");
$zip_url = $MIGRATIONS[$version]['zip_url'];
require THINKUP_WEBAPP_PATH.'config.inc.php';
//install beta 1
$zipfile = $this->getInstall($zip_url, $version, $this->installs_dir);
//Extract into test_installer directory and set necessary folder permissions
exec('cp ' . $zipfile . ' webapp/test_installer/.;'.
'cd webapp/test_installer/;'.
'unzip ' . $zipfile . ';chmod -R 777 thinkup');
//Config file doesn't exist
$this->assertFalse(file_exists($THINKUP_CFG['source_root_path'].
'webapp/test_installer/thinkup/config.inc.php'));
//Set test mode
$this->get($this->url.'/test_installer/thinkup/install/setmode.php?m=tests');
//Include config again to get test db credentials
require THINKUP_WEBAPP_PATH.'config.inc.php';
//$this->showText();
//Start installation process
$this->get($this->url.'/test_installer/thinkup/');
$this->assertTitle("ThinkUp");
$this->assertText('ThinkUp\'s configuration file does not exist! Try installing ThinkUp.');
$this->clickLink("installing ThinkUp.");
$this->assertText('Great! Your system has everything it needs to run ThinkUp. You may proceed to the next '.
'step.');
//Set test mode
putenv("MODE=TESTS");
//Include config again to get test db credentials
require THINKUP_WEBAPP_PATH.'config.inc.php';
$this->get('index.php?step=2');
$this->assertText('Create Your ThinkUp Account');
$this->setField('full_name', 'ThinkUp J. User');
$this->setField('site_email', 'user@example.com');
$this->setField('password', 'secret');
$this->setField('confirm_password', 'secret');
$this->setField('timezone', 'America/Los_Angeles');
$this->setField('db_host', $THINKUP_CFG['db_host']);
$this->setField('db_name', $THINKUP_CFG['db_name']);
$this->setField('db_user', $THINKUP_CFG['db_user']);
$this->setField('db_passwd', $THINKUP_CFG['db_password']);
$this->setField('db_socket', $THINKUP_CFG['db_socket']);
$this->clickSubmitByName('Submit');
$this->assertText('ThinkUp has been installed successfully. Check your email account; an account activation '.
'message has been sent.');
//Config file has been written
$this->assertTrue(file_exists($THINKUP_CFG['source_root_path'].
'webapp/test_installer/thinkup/config.inc.php'));
//Test bad activation code
$this->get($this->url.'/test_installer/thinkup/session/activate.php?usr=user@example.com&code=dummycode');
//$this->showText();
$this->assertText('Houston, we have a problem: Account activation failed.');
//Get activation code for user from database
date_default_timezone_set('America/Los_Angeles');
$owner_dao = new OwnerMySQLDAO();
$code = $owner_dao->getActivationCode('user@example.com');
$activation_code = $code['activation_code'];
//Visit activation page
$this->get($this->url.'/test_installer/thinkup/session/activate.php?usr=user@example.com&code='.
$activation_code);
$this->assertNoText('Houston, we have a problem: Account activation failed.');
$this->assertText('Success! Your account has been activated. Please log in.');
//Log into ThinkUp
$this->clickLink('Log in');
$this->setField('email', 'user@example.com');
$this->setField('pwd', 'secret');
$this->click("Log In");
$this->assertText('You have no accounts configured. Set up an account now');
//Visit Configuration/Settings page and assert content there
if (floatval($version) >= 0.6) {
$this->click("Settings"); //link name changed in beta 6
} else {
$this->click("Configuration");
}
$this->assertTitle('Configure Your Account | ThinkUp');
$this->assertText('As an administrator you can configure all installed plugins.');
// run updates and migrations
require 'tests/migration-assertions.php';
// build latest version for testing
$migration_sql_dir = THINKUP_ROOT_PATH . 'webapp/install/sql/mysql_migrations/';
$latest_migration_file = false;
$config = Config::getInstance();
$current_version = $config->getValue('THINKUP_VERSION');
$latest_migration = glob($migration_sql_dir . '*_v' . $LATEST_VERSION .'.sql.migration');
if($LATEST_VERSION == $current_version) {
$this->debug("Building zip for latest version: $LATEST_VERSION");
$sql_files = glob($migration_sql_dir . '*.sql');
if (sizeof($sql_files) > 0) {
$this->debug("found sql update for latest version $LATEST_VERSION: $sql_files[0]");
if(! isset($latest_migration[0])) {
$date_stamp = date("Y-m-d");
$latest_migration_file = $migration_sql_dir . $date_stamp . '_v' . $LATEST_VERSION .
'.sql.migration';
$fp = fopen($latest_migration_file, 'w');
$sql_files = glob($migration_sql_dir . '*.sql');
$sql_file = $sql_files[0];
$sql_migration = file_get_contents($sql_file);
fwrite($fp, " -- migration file " . $sql_file . "\n\n");
fwrite($fp, $sql_migration);
fwrite($fp, "\n\n--");
fclose($fp);
}
}
exec('extras/scripts/generate-distribution');
exec('cp build/thinkup.zip build/' . $LATEST_VERSION . '.zip');
if(file_exists($latest_migration_file)) {
unlink( $latest_migration_file );
}
}
return array('MIGRATIONS' => $MIGRATIONS, 'latest_migration_file' => $latest_migration_file );
}
/**
* Runs migrations list
*/
private function runMigrations($TMIGRATIONS, $base_version) {
require 'tests/migration-assertions.php';
foreach($TMIGRATIONS as $version => $migration_data) {
$this->debug("Running migration test for version: $version");
$url = $migration_data['zip_url'];
$zipfile = $this->getInstall($url, $version, $this->installs_dir);
if(! $zipfile) {
error_log("Warn: $zipfile not found...");
continue;
}
$this->debug("unzipping $zipfile");
//Extract into test_installer directory and set necessary folder permissions
exec('cp ' . $zipfile . ' webapp/test_installer/.;'.
'cd webapp/test_installer/;unzip -o ' . $zipfile);
// run updates and migrations
require 'tests/migration-assertions.php';
// update version php file
if($version == $LATEST_VERSION) {
$version_file = $this->install_dir . '/thinkup/install/version.php';
$version_php = file_get_contents($version_file);
$version_php =
preg_replace("/THINKUP_VERSION =.*;/", "THINKUP_VERSION = $LATEST_VERSION;", $version_php);
$fp = fopen($version_file, 'w');
fwrite($fp, $version_php);
fclose($fp);
}
$this->get($this->url.'/test_installer/thinkup/');
$this->assertText("ThinkUp's database needs an update");
$file_token = file_get_contents($this->install_dir.'/thinkup/_lib/view/compiled_view/upgrade_token');
$token_url = $this->url.'/test_installer/thinkup/install/upgrade.php?upgrade_token=' . $file_token;
$this->get($token_url);
$content = $this->getBrowser()->getContent();
preg_match("/sql_array = (\[.*?])/", $content, $matches);
$json_array = json_decode($matches[1]);
$cnt = 0;
foreach($json_array as $json_migration) {
$this->debug("running migration: " . $json_migration->version);
// if there is setup_sql run it
if(isset($MIGRATIONS[$json_migration->version ]['setup_sql'])) {
$this->debug('running setup_sql scripts');
$install_dao = DAOFactory::getDAO('InstallerDAO');
foreach($MIGRATIONS[$json_migration->version ]['setup_sql'] as $sql) {
$this->debug('running setup_sql script: ' . substr($sql, 0, 40) . '...');
$install_dao->runMigrationSQL($sql);
}
}
$cnt++;
$this->get($token_url . "&migration_index=" . $cnt);
$this->assertText('{"processed":true,');
$this->debug("Running migration assertion test for " . $json_migration->version);
$assertions = $MIGRATIONS[ $json_migration->version ];
foreach($assertions['migration_assertions']['sql'] as $assertion_sql) {
// don't run the database_version assertion if it exists, this will get run below...
if(preg_match("/database_version/i", $assertion_sql['query'])) {
continue;
}
$this->debug("Running assertion sql: " . $assertion_sql['query']);
$stmt = $this->pdo->query($assertion_sql['query']);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if(isset($assertion_sql['no_match'])) {
$this->assertFalse($data, 'no results for query'); // a table or column deleted?
} else {
$this->assertEqual(preg_match($assertion_sql['match'], $data[ $assertion_sql['column'] ]), 1,
$assertion_sql['match'] . ' should match ' . $data[ $assertion_sql['column'] ]);
$stmt->closeCursor();
}
$stmt->closeCursor();
}
}
$this->get($token_url . '&migration_done=true');
$this->assertText('{"migration_complete":true}');
$this->get($this->url.'/test_installer/thinkup/');
$this->assertText('Logged in as: user@example.com');
// run db migration tests
$this->debug("Running final migration assertion test for $version");
foreach($migration_data['migration_assertions'] as $assertions) {
foreach($assertions as $assertion) {
$this->debug("Running assertion sql: " . $assertion['query']);
$stmt = $this->pdo->query($assertion['query']);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if(isset($assertion['no_match'])) {
$this->assertFalse($data, 'no results for query'); // a table or column deleted?
} else {
$this->assertEqual(preg_match($assertion['match'], $data[ $assertion['column'] ]), 1,
$assertion['match'] . ' should match ' . $data[ $assertion['column'] ]);
}
$stmt->closeCursor();
}
}
}
}
/**
* Downloads install/upgrade zip file if needed, returns path to zip file.
* @param str Url
* @param str Version
* @return str Path to download file
*/
private function getInstall($url, $version, $path) {
$ch = curl_init();
$zipfile = $path . '/' . $version . '.zip';
// if zip file is not there or is older than 8 hours old
if(! file_exists($zipfile) || ( time() - filemtime($zipfile) > (60 * 60 * 8) ) ) {
if( file_exists($zipfile) ) {
$this->debug("zip file for $version is old, refreshing");
unlink($zipfile);
}
$this->debug("Fetching zip file $url");
$ch = curl_init($url);//Here is the file we are downloading
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$data = curl_exec($ch);
file_put_contents($zipfile, $data);
}
return $zipfile;
}
}