Skip to content

Commit

Permalink
Issue #443: Added web upgrade tests for every possible upgrade path i…
Browse files Browse the repository at this point in the history
…n the beta

* Tests for beta 1 => beta 6, beta 2 => beta 6, beta 3 => beta 6, etc
  • Loading branch information
Mark Wilkie authored and ginatrapani committed Dec 19, 2010
1 parent f1f6557 commit 613906d
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 39 deletions.
40 changes: 34 additions & 6 deletions tests/TestOfUpgradeController.php
Expand Up @@ -242,28 +242,36 @@ public function testProcessOneMigrations() {
}

public function testProcessSnowflakeMigration() {
$config = Config::getInstance();
$app_path = $config->getValue('source_root_path');
$snowflakekey = 'runnig_snowflake_uprade';


// no snowflake update needed...
$this->pdo->query("truncate table " . $this->prefix . "options");
$this->simulateLogin('me@example.com', true);
$this->assertFalse(isset($_SESSION[$app_path][$snowflakekey]));

$config = Config::getInstance();
$config->setValue('THINKUP_VERSION', '0.3');
$config->setValue('THINKUP_VERSION', '0.4');
$controller = new UpgradeController(true);
$results = $controller->go();
$this->assertPattern('/no upgrade needed/', $results);
$this->assertPattern('/needs 1 database update/', $results);

// snowflake update needed...
$this->pdo->query("truncate table " . $this->prefix . "options");
$this->pdo->query("drop table " . $this->prefix . "options");
$this->db->exec('ALTER TABLE ' . $this->prefix .
'instances CHANGE last_post_id last_status_id bigint(11) NOT NULL');
$controller = new UpgradeController(true);
$results = $controller->go();
$this->assertPattern('/needs 1 database update/', $results);
$this->assertPattern('/needs 2 database updates/', $results);
$v_mgr = $controller->getViewManager();
$queries = $v_mgr->getTemplateDataItem('migrations');
$this->assertEqual(1, count($queries), 'one migration query');
$this->assertEqual(2, count($queries), 'two migration queries');
$this->assertTrue($_SESSION[$app_path][$snowflakekey]);


// run snowflake migration
$this->pdo->query("truncate table " . $this->prefix . "options");
$_GET['migration_index'] = 1;
$controller = new UpgradeController(true);
$results = $controller->go();
Expand All @@ -273,6 +281,26 @@ public function testProcessSnowflakeMigration() {
$data = $stmt->fetch();
$this->assertEqual($data['Field'], 'last_post_id');
$this->assertPattern('/bigint\(20\)\s+unsigned/i', $data['Type']);
$this->assertTrue($_SESSION[$app_path][$snowflakekey]);

// run version 4 upgrade
$_GET['migration_index'] = 2;
$controller = new UpgradeController(true);
$results = $controller->go();
$this->assertTrue($obj->processed);
$stmt = $this->pdo->query("desc " . $this->prefix . "instances last_post_id");
$data = $stmt->fetch();
$this->assertEqual($data['Field'], 'last_post_id');
$this->assertPattern('/bigint\(20\)\s+unsigned/i', $data['Type']);

// no snowflake session data when complete
$config = Config::getInstance();
unset($_GET['migration_index']);
$_GET['migration_done'] = true;
$results = $controller->go();
$obj = json_decode($results);
$this->assertTrue($obj->migration_complete);
$this->assertFalse(isset($_SESSION[$app_path][$snowflakekey]));
}

public function testProcessTwoMigrations() {
Expand Down
146 changes: 114 additions & 32 deletions tests/WebTestOfUpgradeDatabase.php
Expand Up @@ -52,6 +52,10 @@ public function setUp() {

//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() {
Expand All @@ -74,12 +78,62 @@ public function 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->_set_up_app($migration_versions[$i], $MIGRATIONS);
$this->_run_migrations($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->_set_up_app($migration_versions[2], $MIGRATIONS);
$this->pdo->query('ALTER TABLE ' . $this->prefix .
'instances CHANGE last_post_id last_status_id bigint(11) NOT NULL');
$this->_run_migrations($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/updaye");

}

/**
* sets up inital app
*/
public function _set_up_app($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';
global $TEST_DATABASE;

//install beta 1
$zipfile = $this->getIntsall('http://github.com/downloads/ginatrapani/ThinkUp/thinkup-0.1.zip',
'0.1', $this->installs_dir);
$zipfile = $this->getIntsall($zip_url, $version, $this->installs_dir);

//Extract into test_installer directory and set necessary folder permissions
exec('cp ' . $zipfile . ' webapp/test_installer/.;'.
Expand All @@ -98,7 +152,6 @@ public function testMigrations() {
$this->assertText('Great! Your system has everything it needs to run ThinkUp. You may proceed to the next '.
'step.');
$this->get('index.php?step=2');
//$this->showSource();
$this->assertText('Create Your ThinkUp Account');

$this->setField('full_name', 'ThinkUp J. User');
Expand All @@ -123,6 +176,7 @@ public function testMigrations() {

//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
Expand Down Expand Up @@ -160,7 +214,7 @@ public function testMigrations() {

$current_version = $config->getValue('THINKUP_VERSION');
if($LATEST_VERSION == $current_version) {
$this->debug("Building build for latest version: $LATEST_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 lasest version $LATEST_VERSION: $sql_files[0]");
Expand All @@ -180,19 +234,30 @@ public function testMigrations() {
exec('extras/scripts/generate-distribution');
exec('cp build/thinkup.zip build/' . $LATEST_VERSION . '.zip');
}
return array('MIGRATIONS' => $MIGRATIONS, 'latest_migration_file' => $latest_migration_file );
}

foreach($MIGRATIONS as $version => $migration_data) {
/**
* runs migrations list
*/
public function _run_migrations($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->getIntsall($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';
Expand All @@ -204,34 +269,47 @@ public function testMigrations() {
fclose($fp);
}

// no web based upgrade mode until version 4
if($version > 0.3) {
$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);
for($i = 1; $i <= $migration_data['migrations']; $i++) {
$this->get($token_url . "&migration_index=" . $i);
}
$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');
} else {
$dir = $this->install_dir . '/thinkup/install/sql/mysql_migrations';
$dir_list = glob($dir . '/*.migration');
for ($i = 0; $i < count($dir_list); $i++) {
$mig_match = '/_v' . $version .'\.sql\.migration/';
if(preg_match($mig_match, $dir_list[$i], $matches)) {
$migration_string = file_get_contents($dir_list[$i]);
$this->pdo->query($migration_string);
$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) {
$cnt++;
$this->debug("running migration: " . $json_migration->version);
$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 ];
//var_dump($assertions);
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);
$this->assertEqual(preg_match($assertion_sql['match'], $data[ $assertion_sql['column'] ]), 1,
$assertion_sql['match'] . ' should match ' . $data[ $assertion_sql['column'] ]);
$stmt->closeCursor();
}
}
//return;
$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);
$this->assertEqual(preg_match($assertion['match'], $data[ $assertion['column'] ]), 1,
Expand All @@ -240,9 +318,6 @@ public function testMigrations() {
}
}
}
if($latest_migration_file && file_exists($latest_migration_file)) {
unlink( $latest_migration_file );
}
}

/**
Expand All @@ -254,7 +329,14 @@ public function testMigrations() {
public function getIntsall($url, $version, $path) {
$ch = curl_init();
$zipfile = $path . '/' . $version . '.zip';
if(! file_exists($zipfile)) {

// 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);
Expand Down
13 changes: 13 additions & 0 deletions tests/migration-assertions.php
Expand Up @@ -32,6 +32,19 @@
$LATEST_VERSION = 0.6;

$MIGRATIONS = array(
/* beta 0.1 */
'0.1' => array(
'zip_url' => 'http://github.com/downloads/ginatrapani/ThinkUp/thinkup-0.1.zip',
'migration_assertions' => array(
'sql' => array(
array(
'query' => 'desc tu_owners email',
'match' => "/varchar\(200\)/",
'column' => 'Type',
)
)
)
),

/* beta 0.2 */
'0.2' => array(
Expand Down
32 changes: 31 additions & 1 deletion webapp/_lib/controller/class.UpgradeController.php
Expand Up @@ -106,6 +106,8 @@ public function authControl() {
}
$this->setJsonData(array('migration_complete' => true) );
$this->deleteTokenFile();
// remove snowflake in progress session if needed
$this->snowflakeSession(false, true);
} else {
$this->setPageTitle('Upgrade the ThinkUp Database Structure');
$this->setViewTemplate('install.upgrade.tpl');
Expand Down Expand Up @@ -233,8 +235,11 @@ public function getMigrationList($version) {
if($migration_version > $version && $migration_version <= $config->getValue('THINKUP_VERSION')) {
if($migration_version == 0.3) {
$install_dao = DAOFactory::getDAO('InstallerDAO');
if(! $install_dao->needsSnowflakeUpgrade()) {
if(! $install_dao->needsSnowflakeUpgrade() && ! $this->snowflakeSession(false) ) {
continue;
} else {
// set snowflake in progress session
$this->snowflakeSession(true, false);
}
}
$migration_string = file_get_contents($dir_list[$i]);
Expand Down Expand Up @@ -294,4 +299,29 @@ public function generateUpgradeToken() {
}
}
}

/**
* Sets/Deletes data in the session to let us know we needed to run the snowflake migration
* @param boolean Delete the seeion if defined
*/
public function snowflakeSession($value = false, $delete = false) {
$config = Config::getInstance();
$app_path = $config->getValue('source_root_path');
$key = 'runnig_snowflake_uprade';
if($delete) {
if(isset( $_SESSION[$app_path][$key] )) {
unset($_SESSION[$app_path][$key]);
}
} else {
if($value) {
$_SESSION[$app_path][$key] = $value;
} else {
if(isset($_SESSION[$app_path]) && isset($_SESSION[$app_path][$key]) ) {
return $_SESSION[$app_path][$key];
} else {
return false;
}
}
}
}
}

0 comments on commit 613906d

Please sign in to comment.