summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Needham <needham.thomas@gmail.com>2014-02-18 17:35:49 +0100
committerTom Needham <needham.thomas@gmail.com>2014-02-18 17:35:49 +0100
commita573fe7d769f5eea26f52b818eee11779090bb50 (patch)
tree271658d1e79553f5d172a72d0fc9fa67bb4ef946
parent3b1083f46eb7dd67faddc8214799ee6396ffdea9 (diff)
parent0beaeed713977bcca0eb9da996af712526ee69d2 (diff)
downloadnextcloud-server-a573fe7d769f5eea26f52b818eee11779090bb50.tar.gz
nextcloud-server-a573fe7d769f5eea26f52b818eee11779090bb50.zip
Merge pull request #6650 from owncloud/migration_unit_tests
User migration fix, and basic unit test
-rw-r--r--lib/private/db.php2
-rw-r--r--lib/private/migrate.php105
-rw-r--r--lib/private/migration/content.php36
-rw-r--r--tests/lib/migrate.php89
4 files changed, 120 insertions, 112 deletions
diff --git a/lib/private/db.php b/lib/private/db.php
index 562065259fa..723c1ee07a3 100644
--- a/lib/private/db.php
+++ b/lib/private/db.php
@@ -44,7 +44,7 @@ class OC_DB {
/**
* @var \OC\DB\Connection $connection
*/
- static private $connection; //the prefered connection to use, only Doctrine
+ static private $connection; //the preferred connection to use, only Doctrine
static private $prefix=null;
static private $type=null;
diff --git a/lib/private/migrate.php b/lib/private/migrate.php
index 0b319177400..948b3d4572d 100644
--- a/lib/private/migrate.php
+++ b/lib/private/migrate.php
@@ -35,12 +35,8 @@ class OC_Migrate{
static private $zip=false;
// Stores the type of export
static private $exporttype=false;
- // Array of temp files to be deleted after zip creation
- static private $tmpfiles=array();
// Holds the db object
- static private $MDB2=false;
- // Schema db object
- static private $schema=false;
+ static private $migration_database=false;
// Path to the sqlite db
static private $dbpath=false;
// Holds the path to the zip file
@@ -131,7 +127,7 @@ class OC_Migrate{
if( !self::connectDB() ) {
return json_encode( array( 'success' => false ) );
}
- self::$content = new OC_Migration_Content( self::$zip, self::$MDB2 );
+ self::$content = new OC_Migration_Content( self::$zip, self::$migration_database );
// Export the app info
$exportdata = self::exportAppData();
// Add the data dir to the zip
@@ -257,7 +253,7 @@ class OC_Migrate{
$userfolder = $extractpath . $json->exporteduser;
$newuserfolder = $datadir . '/' . self::$uid;
foreach(scandir($userfolder) as $file){
- if($file !== '.' && $file !== '..' && is_dir($file)) {
+ if($file !== '.' && $file !== '..' && is_dir($userfolder.'/'.$file)) {
$file = str_replace(array('/', '\\'), '', $file);
// Then copy the folder over
@@ -359,24 +355,6 @@ class OC_Migrate{
}
/**
- * @brief connects to a MDB2 database scheme
- * @returns bool
- */
- static private function connectScheme() {
- // We need a mdb2 database connection
- self::$MDB2->loadModule( 'Manager' );
- self::$MDB2->loadModule( 'Reverse' );
-
- // Connect if this did not happen before
- if( !self::$schema ) {
- require_once 'MDB2/Schema.php';
- self::$schema=MDB2_Schema::factory( self::$MDB2 );
- }
-
- return true;
- }
-
- /**
* @brief creates a migration.db in the users data dir with their app data in
* @return bool whether operation was successfull
*/
@@ -463,47 +441,18 @@ class OC_Migrate{
return false;
}
// Already connected
- if(!self::$MDB2) {
- require_once 'MDB2.php';
-
+ if(!self::$migration_database) {
$datadir = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
-
- // DB type
- if( class_exists( 'SQLite3' ) ) {
- $dbtype = 'sqlite3';
- } else if( is_callable( 'sqlite_open' ) ) {
- $dbtype = 'sqlite';
- } else {
- OC_Log::write( 'migration', 'SQLite not found', OC_Log::ERROR );
- return false;
- }
-
- // Prepare options array
- $options = array(
- 'portability' => MDB2_PORTABILITY_ALL & (!MDB2_PORTABILITY_FIX_CASE),
- 'log_line_break' => '<br>',
- 'idxname_format' => '%s',
- 'debug' => true,
- 'quote_identifier' => true
- );
- $dsn = array(
- 'phptype' => $dbtype,
- 'database' => self::$dbpath,
- 'mode' => '0644'
+ $connectionParams = array(
+ 'path' => self::$dbpath,
+ 'driver' => 'pdo_sqlite',
);
+ $connectionParams['adapter'] = '\OC\DB\AdapterSqlite';
+ $connectionParams['wrapperClass'] = 'OC\DB\Connection';
+ $connectionParams['tablePrefix'] = '';
// Try to establish connection
- self::$MDB2 = MDB2::factory( $dsn, $options );
- // Die if we could not connect
- if( PEAR::isError( self::$MDB2 ) ) {
- die( self::$MDB2->getMessage() );
- OC_Log::write( 'migration', 'Failed to create/connect to migration.db', OC_Log::FATAL );
- OC_Log::write( 'migration', self::$MDB2->getUserInfo(), OC_Log::FATAL );
- OC_Log::write( 'migration', self::$MDB2->getMessage(), OC_Log::FATAL );
- return false;
- }
- // We always, really always want associative arrays
- self::$MDB2->setFetchMode(MDB2_FETCHMODE_ASSOC);
+ self::$migration_database = \Doctrine\DBAL\DriverManager::getConnection($connectionParams);
}
return true;
@@ -515,10 +464,7 @@ class OC_Migrate{
* @return bool whether the operation was successful
*/
static private function createAppTables( $appid ) {
-
- if( !self::connectScheme() ) {
- return false;
- }
+ $schema_manager = new OC\DB\MDB2SchemaManager(self::$migration_database);
// There is a database.xml file
$content = file_get_contents(OC_App::getAppPath($appid) . '/appinfo/database.xml' );
@@ -538,29 +484,16 @@ class OC_Migrate{
file_put_contents( $file2, $content );
// Try to create tables
- $definition = self::$schema->parseDatabaseDefinitionFile( $file2 );
-
- unlink( $file2 );
-
- // Die in case something went wrong
- if( $definition instanceof MDB2_Schema_Error ) {
- OC_Log::write( 'migration', 'Failed to parse database.xml for: '.$appid, OC_Log::FATAL );
- OC_Log::write( 'migration', $definition->getMessage().': '.$definition->getUserInfo(), OC_Log::FATAL );
- return false;
- }
-
- $definition['overwrite'] = true;
-
- $ret = self::$schema->createDatabase( $definition );
-
- // Die in case something went wrong
- if( $ret instanceof MDB2_Error ) {
+ try {
+ $schema_manager->createDbFromStructure($file2);
+ } catch(Exception $e) {
+ unlink( $file2 );
OC_Log::write( 'migration', 'Failed to create tables for: '.$appid, OC_Log::FATAL );
- OC_Log::write( 'migration', $ret->getMessage().': '.$ret->getUserInfo(), OC_Log::FATAL );
+ OC_Log::write( 'migration', $e->getMessage(), OC_Log::FATAL );
return false;
}
- return $tables;
+ return $tables;
}
/**
@@ -646,7 +579,7 @@ class OC_Migrate{
if( !self::connectDB( $db ) ) {
return false;
}
- $content = new OC_Migration_Content( self::$zip, self::$MDB2 );
+ $content = new OC_Migration_Content( self::$zip, self::$migration_database );
$provider->setData( self::$uid, $content, $info );
// Then do the import
if( !$appsstatus[$id] = $provider->import( $info->apps->$id, $importinfo ) ) {
diff --git a/lib/private/migration/content.php b/lib/private/migration/content.php
index 4413d722731..d6eee40786e 100644
--- a/lib/private/migration/content.php
+++ b/lib/private/migration/content.php
@@ -27,7 +27,7 @@
class OC_Migration_Content{
private $zip=false;
- // Holds the MDB2 object
+ // Holds the database object
private $db=null;
// Holds an array of tmpfiles to delete after zip creation
private $tmpfiles=array();
@@ -35,7 +35,7 @@ class OC_Migration_Content{
/**
* @brief sets up the
* @param $zip ZipArchive object
- * @param optional $db a MDB2 database object (required for exporttype user)
+ * @param optional $db a database object (required for exporttype user)
* @return bool
*/
public function __construct( $zip, $db=null ) {
@@ -63,17 +63,9 @@ class OC_Migration_Content{
// Optimize the query
$query = $this->db->prepare( $query );
+ $query = new OC_DB_StatementWrapper($query, false);
- // Die if we have an error (error means: bad query, not 0 results!)
- if( PEAR::isError( $query ) ) {
- $entry = 'DB Error: "'.$query->getMessage().'"<br />';
- $entry .= 'Offending command was: '.$query.'<br />';
- OC_Log::write( 'migration', $entry, OC_Log::FATAL );
- return false;
- } else {
- return $query;
- }
-
+ return $query;
}
/**
@@ -156,20 +148,14 @@ class OC_Migration_Content{
$sql .= $valuessql . " )";
// Make the query
$query = $this->prepare( $sql );
- if( !$query ) {
- OC_Log::write( 'migration', 'Invalid sql produced: '.$sql, OC_Log::FATAL );
- return false;
- exit();
+ $query->execute( $values );
+ // Do we need to return some values?
+ if( array_key_exists( 'idcol', $options ) ) {
+ // Yes we do
+ $return[] = $row[$options['idcol']];
} else {
- $query->execute( $values );
- // Do we need to return some values?
- if( array_key_exists( 'idcol', $options ) ) {
- // Yes we do
- $return[] = $row[$options['idcol']];
- } else {
- // Take a guess and return the first field :)
- $return[] = reset($row);
- }
+ // Take a guess and return the first field :)
+ $return[] = reset($row);
}
$fields = '';
$values = '';
diff --git a/tests/lib/migrate.php b/tests/lib/migrate.php
new file mode 100644
index 00000000000..39a9bfc8d5a
--- /dev/null
+++ b/tests/lib/migrate.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Copyright (c) 2014 Tom Needham <tom@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class Test_Migrate extends PHPUnit_Framework_TestCase {
+
+ public $users;
+ public $tmpfiles = array();
+
+ /**
+ * @brief Generates a test user and sets up their file system
+ * @return string the test users id
+ */
+ public function generateUser() {
+ $username = uniqid();
+ \OC_User::createUser($username, 'password');
+ \OC_Util::tearDownFS();
+ \OC_User::setUserId('');
+ \OC\Files\Filesystem::tearDown();
+ \OC_Util::setupFS($username);
+ $this->users[] = $username;
+ return $username;
+ }
+
+ /**
+ * @brief validates an export for a user
+ * @brief checks for existence of export_info.json and file folder
+ * @param string $exportedUser the user that was exported
+ * @param string $path the path to the .zip export
+ */
+ public function validateUserExport($exportedBy, $exportedUser, $path) {
+ $this->assertTrue(file_exists($path));
+ // Extract
+ $extract = get_temp_dir() . '/oc_import_' . uniqid();
+ //mkdir($extract);
+ $this->tmpfiles[] = $extract;
+ $zip = new ZipArchive;
+ $zip->open($path);
+ $zip->extractTo($extract);
+ $zip->close();
+ $this->assertTrue(file_exists($extract.'/export_info.json'));
+ $exportInfo = file_get_contents($extract.'/export_info.json');
+ $exportInfo = json_decode($exportInfo);
+ $this->assertNotNull($exportInfo);
+ $this->assertEquals($exportedUser, $exportInfo->exporteduser);
+ $this->assertEquals($exportedBy, $exportInfo->exportedby);
+ $this->assertTrue(file_exists($extract.'/'.$exportedUser.'/files'));
+ }
+
+ public function testUserSelfExport() {
+ // Create a user
+ $user = $this->generateUser();
+ \OC_User::setUserId($user);
+ $export = \OC_Migrate::export($user);
+ // Check it succeeded and exists
+ $this->assertTrue(json_decode($export)->success);
+ // Validate the export
+ $this->validateUserExport($user, $user, json_decode($export)->data);
+ }
+
+ public function testUserOtherExport() {
+ $user = $this->generateUser();
+ $user2 = $this->generateUser();
+ \OC_User::setUserId($user2);
+ $export = \OC_Migrate::export($user);
+ // Check it succeeded and exists
+ $this->assertTrue(json_decode($export)->success);
+ // Validate the export
+ $this->validateUserExport($user2, $user, json_decode($export)->data);
+ }
+
+ public function tearDown() {
+ $u = new OC_User();
+ foreach($this->users as $user) {
+ $u->deleteUser($user);
+ }
+ foreach($this->tmpfiles as $file) {
+ \OC_Helper::rmdirr($file);
+ }
+ }
+
+
+
+
+}