From: <tna...@us...> - 2008-03-12 05:52:17
|
Revision: 17514 http://gallery.svn.sourceforge.net/gallery/?rev=17514&view=rev Author: tnalmdal Date: 2008-03-11 22:52:22 -0700 (Tue, 11 Mar 2008) Log Message: ----------- Convert LanguageManager to make a single request to download all the langauge packages for a particular language. The results are returned as as a custom multipart download. Review 582 Modified Paths: -------------- trunk/gallery2/lib/tools/phpunit/UnitTestRepository.class trunk/gallery2/lib/tools/phpunit/UnitTestRepositoryUtilities.class trunk/gallery2/modules/core/AdminLanguageManager.inc trunk/gallery2/modules/core/CoreModuleExtras.inc trunk/gallery2/modules/core/classes/GalleryCoreApi.class trunk/gallery2/modules/core/classes/GalleryRepository.class trunk/gallery2/modules/core/classes/GalleryRepositoryUtilities.class trunk/gallery2/modules/core/module.inc trunk/gallery2/modules/core/test/phpunit/RepositoryTest.class trunk/gallery2/modules/core/test/phpunit/RepositoryTestStorage.class trunk/gallery2/modules/core/test/phpunit/RepositoryUtilitiesTest.class Modified: trunk/gallery2/lib/tools/phpunit/UnitTestRepository.class =================================================================== --- trunk/gallery2/lib/tools/phpunit/UnitTestRepository.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/lib/tools/phpunit/UnitTestRepository.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -138,4 +138,8 @@ function getLanguagePackageFiles($locales) { return $this->_makeReply('getLanguagePackageFiles', array($locales)); } + + function downloadAndUnpackPackages($filesToDownload, &$callback) { + return $this->_makeReply('downloadAndUnpackPackages', array($filesToDownload, $callback)); + } } Modified: trunk/gallery2/lib/tools/phpunit/UnitTestRepositoryUtilities.class =================================================================== --- trunk/gallery2/lib/tools/phpunit/UnitTestRepositoryUtilities.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/lib/tools/phpunit/UnitTestRepositoryUtilities.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -105,12 +105,22 @@ return $this->_makeReply('unpackPackage', array($packageFile, $outputDirecory)); } - function preVerifyPackage($packageName, $descriptor) { - return $this->_makeReply('preVerifyPackage', array($packageName, $descriptor)); + function preVerifyPackage($pluginType, $pluginId, $packageName, $descriptor) { + return $this->_makeReply('preVerifyPackage', array($pluginType, $pluginId, $packageName, + $descriptor)); } - function verifyPackageIntegrity($packageName, $descriptor) { - return $this->_makeReply('verifyPackageIntegrity', array($packageName, $descriptor)); + function verifyPackageIntegrity($pluginType, $pluginId, $packageName, $descriptor) { + return $this->_makeReply('verifyPackageIntegrity', array($pluginType, $pluginId, + $packageName, $descriptor)); } + + function downloadAggregatePackages($source, $filesToDownload) { + return $this->_makeReply('downloadAggregatePackages', array($source, $filesToDownload)); + } + + function splitAggregatePackage($source, $outputFile, &$callback) { + return $this->_makeReply('splitAggregatePackage', array($source, $outputFile, $callback)); + } } ?> \ No newline at end of file Modified: trunk/gallery2/modules/core/AdminLanguageManager.inc =================================================================== --- trunk/gallery2/modules/core/AdminLanguageManager.inc 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/AdminLanguageManager.inc 2008-03-12 05:52:22 UTC (rev 17514) @@ -134,8 +134,11 @@ } } - $totalActions = $this->_countInstallActions($sourceFiles) + count($deleteLanguages); + $installLanguagesCount = $this->_countInstallActions($sourceFiles); + /* Add one for the actual download */ + $totalActions = $installLanguagesCount + count($deleteLanguages) + 1; + /* If actions > 0, then we have some language packages to work with */ if ($totalActions > 0) { $templateAdapter->updateProgressBar($heading, '', 0); @@ -143,17 +146,19 @@ $callback = array('method' => array($templateAdapter, 'updateProgressBar'), 'title' => $heading, 'current' => 0, 'total' => $totalActions); - list ($ret, $downloadStatus, $count) = - $this->_downloadAndInstallLanguagePackages($sourceFiles, $repositories, $callback); - if ($ret) { - return $ret; + if ($installLanguagesCount > 0) { + list ($ret, $downloadStatus, $count) = $this->_downloadAndInstallLanguagePackages( + $sourceFiles, $repositories, $callback); + if ($ret) { + return $ret; + } + if (!empty($downloadStatus)) { + $status['error'] = array_merge($status['error'], $downloadStatus); + } + + $status['languagePacksInstalled'] = $count; } - if (!empty($downloadStatus)) { - $status['error'] = array_merge($status['error'], $downloadStatus); - } - $status['languagePacksInstalled'] = $count; - /* Delete old language packs */ list ($ret, $languagePacksDeleted, $failedToDeleteLanguage) = $this->_deleteLanguagePackages($deleteLanguages, $callback); @@ -188,7 +193,7 @@ $session->putStatus($status); $urlGenerator =& $gallery->getUrlGenerator(); - $templateAdapter->completeProgressBar($urlGenerator->generateUrl($redirect), false); + $templateAdapter->completeProgressBar($urlGenerator->generateUrl($redirect), true); return $ret; } @@ -318,27 +323,22 @@ $count = 0; foreach ($sourceFiles as $source => $files) { $repository = $repositories[$source]; + $filesToDownload = array(); foreach ($files as $pluginType => $plugins) { foreach ($plugins as $pluginId => $pluginDownloadData) { - list($ret, $value, $downloadStatus) = $repository->downloadPackagesForPlugin( - $pluginType, $pluginId, $pluginDownloadData, $callback); - if ($ret) { - $gallery->debug('downloadSourceFiles, failed: ' . $ret->getAsText()); - return array($ret, null, null); + foreach ($pluginDownloadData['files'] as $key => $file) { + $filesToDownload[] = $file; } - $fileCount = count($pluginDownloadData['files']); - if (!empty($downloadStatus)) { - $status = array_merge($status, $downloadStatus); - /* Adjust total count for any errors */ - foreach ($downloadStatus as $errorType => $plugInTypeStatus) { - if (!empty($plugInTypeStatus[$pluginId])) { - $fileCount -= count($plugInTypeStatus[$pluginId]); - } - } - } - $count += $fileCount - 1; } } + + list($ret, $downloadStatus, $fileCount) = + $repository->downloadAndUnpackPackages($filesToDownload, $callback); + if ($ret) { + return array($ret, null, null); + } + $count += $fileCount; + $status = array_merge($status, $downloadStatus); } return array(null, $status, $count); Modified: trunk/gallery2/modules/core/CoreModuleExtras.inc =================================================================== --- trunk/gallery2/modules/core/CoreModuleExtras.inc 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/CoreModuleExtras.inc 2008-03-12 05:52:22 UTC (rev 17514) @@ -2536,6 +2536,8 @@ /* Language Manager Implementation */ case '1.2.29': /* GalleryCoreApi::fetchWebFile accepts post data and can use the POST method */ + case '1.2.30': + /* Implement Mulitpart request downloads for Language Manager */ case 'end of upgrade path': /* @@ -2879,6 +2881,7 @@ case '1.2.27': case '1.2.28': case '1.2.29': + case '1.2.30': case 'end of upgrade path': /* Modified: trunk/gallery2/modules/core/classes/GalleryCoreApi.class =================================================================== --- trunk/gallery2/modules/core/classes/GalleryCoreApi.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/classes/GalleryCoreApi.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -86,7 +86,7 @@ * - remove GalleryRepository::getLanguageDescription */ function getApiVersion() { - return array(7, 49); + return array(7, 50); } /** Modified: trunk/gallery2/modules/core/classes/GalleryRepository.class =================================================================== --- trunk/gallery2/modules/core/classes/GalleryRepository.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/classes/GalleryRepository.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -597,9 +597,8 @@ '%s%ss/%s/', GalleryCoreApi::getCodeBasePath(), $pluginType, $pluginId); if (!$platform->file_exists($pluginOutputDir) && !$platform->mkdir($pluginOutputDir)) { - $ret = GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__, - "Couldn't create directory [$pluginOutputDir]"); - return array($ret, null); + return array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__, + "Couldn't create directory [$pluginOutputDir]"), null); } /* Write package to the local repository cache directory. */ @@ -746,10 +745,16 @@ } /** - * @see GalleryRepositoryUtilities::preVerifyPackage + * Verify that a package will install cleanly by examining all of its paths and making sure + * that any file operations that we intend to make will be successful. + * + * @param string $packageName name of the package to check + * @param array $descriptor descriptor of the plugin the package belongs to + * @return array of files that can't be overwritten (empty array if everything is ok) */ function preVerifyPackage($packageName, $descriptor) { - return $this->_utilities->preVerifyPackage($packageName, $descriptor); + return $this->_utilities->preVerifyPackage($descriptor['pluginType'], + $descriptor['pluginId'], $packageName, $descriptor); } /** @@ -759,7 +764,7 @@ * @param array $descriptor descriptor of the plugin the package belongs to * @return GalleryStatus a status code */ - function verifyPackageIntegrity($packageName, $descriptor) { + function verifyPackageIntegrity($packageName, $descriptor) { return $this->_utilities->verifyPackageIntegrity($descriptor['pluginType'], $descriptor['pluginId'], $packageName, $descriptor['contents']); } @@ -929,5 +934,139 @@ function getLanguagePackageFiles($locales) { return $this->_index->getLanguagePackageFiles($locales); } + + /** + * Retrieve all the specified files as one http request and separate into individual packages. + * @param string $source name of the repository to be accessed + * @param array $filesToDownload list of files to download + * @param array $callback progress notification callback + * @return array GalleryStatus a status code + * array string status messages indicating problems encounterd + * int count of packages installed + */ + function downloadAndUnpackPackages($filesToDownload, &$callback) { + global $gallery; + $phpVm = $gallery->getPhpVm(); + $platform =& $gallery->getPlatform(); + + $utilities = $this->_utilities; + + list ($ret, $aggregateFile) = + $utilities->downloadAggregatePackages($this->_source, $filesToDownload); + if ($ret) { + return array($ret, null, null); + } + + call_user_func($callback['method'], $callback['title'], '', + ++$callback['current'] / $callback['total']); + + list ($ret, $packages) = $utilities->splitAggregatePackage($this->_source, $aggregateFile, + $callback); + $platform->unlink($aggregateFile); + if ($ret) { + return array($ret, null, null); + } + + list($ret, $status) = $this->_preverifyAggregatePackages($packages, $callback); + if ($ret) { + return array($ret, null, null); + } + + $installedPackageCount = 0; + $cacheDir = $gallery->getConfig('repository.cache') . $this->_source . '/'; + foreach ($packages as $pluginType => $plugins) { + foreach ($plugins as $pluginId => $data) { + if (!empty($status['failedToInstall'][$pluginType][$pluginId])) { + $callback['current'] += + count($status['failedToInstall'][$pluginType][$pluginId]); + call_user_func($callback['method'], $callback['title'], '', + $callback['current'] / $callback['total']); + continue; + } + $pluginOutputDir = GalleryCoreApi::getCodeBasePath("{$pluginType}s/$pluginId/"); + + $descriptor = $data['descriptor']; + foreach ($data['files'] as $packageFile) { + $gallery->guaranteeTimeLimit(30); + /* Unpack files from package. */ + $utilities->unpackPackage($cacheDir . $packageFile[1], $pluginOutputDir); + $installedPackageCount++; + + $ret = $utilities->verifyPackageIntegrity($pluginType, $pluginId, + $packageFile[0], $descriptor); + if ($ret) { + return array($ret, null, null); + } + + /* Update plugin package map. */ + list ($ret, $version, $build) = $this->getPackageVersionAndBuild( + $pluginType, $pluginId, $packageFile[0]); + if ($ret) { + return array($ret, null, null); + } + $ret = $utilities->updatePackageMetaData( + $pluginType, $pluginId, $packageFile[0], $version, $build, 0); + if ($ret) { + return array($ret, null, null); + } + + call_user_func($callback['method'], $callback['title'], '', + ++$callback['current'] / $callback['total']); + } + } + } + + return array(null, $status, $installedPackageCount); + } + + /** + * Preverify that we will have no trouble unpacking and writing the packages we downloaded + * + * @param array $packages packages returned from splitAggregatePackage + * @param array $callback progress notification callback + * @return array GalleryStatus a status code + * array string status messages indicating problems encounterd + */ + function _preverifyAggregatePackages($packages, &$callback) { + global $gallery; + + $status = array(); + foreach ($packages as $pluginType => $plugins) { + foreach ($plugins as $pluginId => $data) { + $gallery->guaranteeTimeLimit(30); + /* Make sure output directory exists. */ + $pluginOutputDir = GalleryCoreApi::getCodeBasePath("{$pluginType}s/$pluginId/"); + + list ($success) = GalleryUtilities::guaranteeDirExists($pluginOutputDir); + if (!$success) { + return array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__, + "Couldn't create directory [$pluginOutputDir]"), null); + } + + if (!empty($data['descriptor'])) { + $descriptor = $data['descriptor']; + foreach ($data['files'] as $packageFile) { + $lockedFiles = $this->_utilities->preVerifyPackage($pluginType, $pluginId, + $packageFile[0], $descriptor); + if (!empty($lockedFiles)) { + $status['failedToInstall'][$pluginType][$pluginId][] = $packageFile[1]; + continue; + } + } + } else { + GalleryCoreApi::addEventLogEntry('Gallery Error', 'No Descriptor', + sprintf('No descriptor requested for %s %s', $pluginType, $pluginId)); + + foreach ($data['files'] as $packageFile) { + $status['failedToInstall'][$pluginType][$pluginId][] = $packageFile[1]; + $callback['current']++; + } + $percentage = $callback['current'] / $callback['total']; + call_user_func($callback['method'], $callback['title'], '', $percentage); + } + } + } + return array(null, $status); + } } ?> Modified: trunk/gallery2/modules/core/classes/GalleryRepositoryUtilities.class =================================================================== --- trunk/gallery2/modules/core/classes/GalleryRepositoryUtilities.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/classes/GalleryRepositoryUtilities.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -373,16 +373,7 @@ $needsInflation = true; } - static $apiQueryParams; - if (empty($apiQueryParams)) { - GalleryCoreApi::requireOnce('modules/core/classes/GalleryTheme.class'); - $apiQueryParams = sprintf('coreApi=%s&moduleApi=%s&themeApi=%s', - join('.', GalleryCoreApi::getApiVersion()), - join('.', GalleryModule::getApiVersion()), - join('.', GalleryTheme::getApiVersion())); - } - - $url .= '?' . $apiQueryParams; + $url .= '?' . $this->_getApiQueryParams(); list ($successful, $contents, $response, $headers, $actualUrl) = GalleryCoreApi::fetchWebPage($url); if (empty($contents) || !$successful) { @@ -451,18 +442,18 @@ * Verify that a package will install cleanly by examining all of its paths and making sure * that any file operations that we intend to make will be successful. * + * @param string $pluginType the plugin type (eg. module, theme) + * @param string $pluginId the plugin id * @param string $packageName name of the package to check * @param array $descriptor descriptor of the plugin the package belongs to * @return array of files that can't be overwritten (empty array if everything is ok) */ - function preVerifyPackage($packageName, $descriptor) { + function preVerifyPackage($pluginType, $pluginId, $packageName, $descriptor) { global $gallery; $platform =& $gallery->getPlatform(); $errorMessages = array(); - $pluginType = $descriptor['pluginType']; - $pluginId = $descriptor['pluginId']; $pluginOutputDir = sprintf( '%s%ss/%s/', GalleryCoreApi::getCodeBasePath(), $pluginType, $pluginId); @@ -475,7 +466,7 @@ return array(); } - foreach ($descriptor['contents']['files'] as $relativePath => $metaData) { + foreach ($descriptor['files'] as $relativePath => $metaData) { foreach ($metaData['packages'] as $descriptorPackage) { $gallery->guaranteeTimeLimit(10); @@ -569,6 +560,107 @@ return null; } + /** + * This method reads the aggregate download file and extracts the package files. + * The format of the file is: + * file: relative filename(.gz) lengthCRLF + * binary data if compressed or text if not compressed + * + * file: relative filename(.gz) lengthCRLF + * binary data if compressed or text if not compressed + * + * @param string $source name of the repository to be accessed + * @param string $outputFile name of the temporary file containing the downloaded packages + * @param array $callback progress notification callback + * @return array GalleryStatus a status code + * array of packages that were downloaded + */ + function splitAggregatePackage($source, $outputFile, &$callback) { + global $gallery; + $platform =& $gallery->getPlatform(); + $phpVm = $gallery->getPhpVm(); + + $packages = array('module' => array(), 'theme' => array()); + + /* Sample: file: modules/albumselect-lang-en_GB-12345-12345.package.gz 12345 */ + $languagePackPattern = '#^file:\s+((module|theme)s/([a-zA-Z0-9]+)-' + . '(?:(lang-[a-z]{2}(?:_[A-Z]{2})?)(?:-\d+){2})\.package)(\.gz)?\s+(\d+)$#'; + + /* Sample: file: modules/albumselect-1.0.10-12345-base.package.gz 12345 */ + $basePattern = '#^file:\s+((module|theme)s/([a-zA-Z0-9]+)-(?:\.?\d+){2,}-\d+-' + . 'base\.package)(\.gz)?\s+(\d+)$#'; + + /* Sample: file: modules/albumselect-1.0.10-12345.descriptor.gz 12345 */ + $descriptorPattern = '#^file:\s+((module|theme)s/([a-zA-Z0-9]+)-(?:\.?\d+){2,}-\d+' + . '\.descriptor)(\.gz)?\s+(\d+)$#'; + + $handle = $platform->fopen($outputFile, 'r'); + if (empty($handle)) { + return array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__, + 'Couldn\'t open aggregate package file'), null); + } + $cacheDir = $gallery->getConfig('repository.cache') . $source . '/'; + while (($line = $platform->fgets($handle, 4096)) !== false) { + $gallery->guaranteeTimeLimit(30); + + $line = trim($line); + if (preg_match($languagePackPattern, $line, $matches)) { + list ($value, $file, $pluginType, $pluginId, $packageName, $needsInflation, + $byteCount) = $matches; + $isDescriptor = false; + } else if (preg_match($basePattern, $line, $matches)) { + list ($value, $file, $pluginType, $pluginId, $needsInflation, $byteCount) = + $matches; + $packageName = 'base'; + $isDescriptor = false; + } else if (preg_match($descriptorPattern, $line, $matches)) { + list ($value, $file, $pluginType, $pluginId, $needsInflation, $byteCount) = + $matches; + $packageName = null; + $isDescriptor = true; + } else { + $platform->fclose($handle); + return array(GalleryCoreApi::error(ERROR_UNSUPPORTED_FILE_TYPE, null, null, + "Unexpected data encountered on download \"$line\""), null); + } + + $contents = $platform->fread($handle, $byteCount); + + if (!empty($needsInflation)) { + if ($phpVm->function_exists('gzinflate')) { + $contents = $phpVm->gzinflate($contents); + } else { + $platform->fclose($handle); + return array(GalleryCoreApi::error(ERROR_UNSUPPORTED_FILE_TYPE, null, null, + "gzinflate not installed and is required to inflate: $file"), null); + } + } + + if (empty($packages[$pluginType][$pluginId])) { + $packages[$pluginType][$pluginId] = array('files' => array()); + } + + /* Write package to the local repository cache directory */ + $absolutePackagePath = $cacheDir . $file; + if ($platform->file_put_contents($absolutePackagePath, $contents) === false) { + $platform->fclose($handle); + return array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, null, null, + "Error writing package: $absolutePackagePath"), null); + } + + if ($isDescriptor) { + $packages[$pluginType][$pluginId]['descriptor'] = unserialize($contents); + } else { + $packages[$pluginType][$pluginId]['files'][] = array($packageName, $file); + } + + call_user_func($callback['method'], $callback['title'], '', + ++$callback['current'] / $callback['total']); + } + $platform->fclose($handle); + return array(null, $packages); + } + /* * Unpack and install a downloaded package file. * This is primarily to allow unit testing. @@ -579,5 +671,67 @@ include($packageFile); call_user_func($unpackFunction, $outputDirecory); } + + /** + * Retrieve the core, module and theme API versions. + * @return string the API version numbers in http query format. + * @access private + */ + function _getApiQueryParams() { + static $apiQueryParams; + if (empty($apiQueryParams)) { + GalleryCoreApi::requireOnce('modules/core/classes/GalleryTheme.class'); + $apiQueryParams = sprintf('coreApi=%s&moduleApi=%s&themeApi=%s', + join('.', GalleryCoreApi::getApiVersion()), + join('.', GalleryModule::getApiVersion()), + join('.', GalleryTheme::getApiVersion())); + } + + return $apiQueryParams; + } + + /** + * Contact the repository and download the specified files with one request. + * + * @param string $source repository source + * @param array $filesToDownload list of files to download + * @return array GalleryStatus a status code + * string name of the temporary file containing the aggregated download + */ + function downloadAggregatePackages($source, $filesToDownload) { + global $gallery; + $platform =& $gallery->getPlatform(); + $phpVm = $gallery->getPhpVm(); + + /* Create a temporary file for the multipart download file */ + $tmpDir = $gallery->getConfig('data.gallery.tmp'); + $outputFile = $platform->tempnam($tmpDir, 'multipart'); + if (!$platform->file_exists($outputFile)) { + return array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__, + 'Couldn\'t create temporary file'), null); + } + + $postDataArray = array(); + $useCompression = $phpVm->function_exists('gzinflate'); + + foreach ($filesToDownload as $key => $file) { + $postDataArray["files[$key]"] = $file . ($useCompression ? '.gz' : ''); + } + + $url = $gallery->getConfig('repository.url') . $source . '/multipart/'; + $url .= '?' . $this->_getApiQueryParams(); + + $gallery->guaranteeTimeLimit(60); + + list ($success, $response, $headers, $location) = + GalleryCoreApi::fetchWebFile($url, $outputFile, array(), $postDataArray); + + if (empty($success)) { + $platform->unlink($outputFile); + return array(GalleryCoreApi::error(ERROR_BAD_PATH, null, null, + "Failed to download packages: \"$response\"."), null); + } + return array(null, $outputFile); + } } ?> Modified: trunk/gallery2/modules/core/module.inc =================================================================== --- trunk/gallery2/modules/core/module.inc 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/module.inc 2008-03-12 05:52:22 UTC (rev 17514) @@ -34,14 +34,14 @@ $this->setGalleryVersion('2.3-svn'); /* Don't forget to update CoreModuleExtras::upgrade and _prepareConfigUpgrade too! */ - $this->setVersion('1.2.30'); + $this->setVersion('1.2.31'); $this->_templateVersion = 1; $this->setDescription($gallery->i18n('Gallery 2 Core Module')); $this->setGroup('gallery', $gallery->i18n('Gallery')); $this->setCallbacks( 'getItemLinks|getSystemLinks|getItemAdminViews|getSiteAdminViews|getUserAdminViews'); - $this->setRequiredCoreApi(array(7, 48)); + $this->setRequiredCoreApi(array(7, 50)); $this->setRequiredModuleApi(array(3, 8)); } Modified: trunk/gallery2/modules/core/test/phpunit/RepositoryTest.class =================================================================== --- trunk/gallery2/modules/core/test/phpunit/RepositoryTest.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/test/phpunit/RepositoryTest.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -1404,6 +1404,47 @@ $this->assert(!GalleryDataCache::containsKey($cacheKey), 'key should be deleted'); } + function _prepareForGetPluginUpgradeInfo($isNewer=false) { + $repository = new GalleryRepository(); + $repository->_index = $this->_index; + $utilities = new UnitTestRepositoryUtilities(); + $installedPackages = + array('base' => array('locked' => false, 'version' => '1.1', 'build' => '1'), + 'lang-en_GB' => array('locked' => 0, 'version' => '1.1', 'build' => '1')); + $utilities->setReply('getPluginPackages', array('module', 'testModule'), + array(null, $installedPackages)); + $utilities->setReply('isPluginCompatible', + array('module', GalleryCoreApi::getApiVersion(), GalleryModule::getApiVersion(), null), + true); + $utilities->setReply('compareVersions', array('1.1', '1.0.0', 1, '44444'), + array(null, 'newer')); + $languages = array(); + foreach (array('en_US', 'en_GB', 'pt_PT', 'pt_BR') as $lang) { + $currentBuild = $lang == 'en_GB' ? '1' : null; + $languages[$lang] = array('name' => $lang, 'currentBuild' => $currentBuild, + 'newBuild' => '33333', 'relation' => 'older', 'locked' => 0); + GalleryDataCache::put("GalleryTranslator::LanguageDescription::$lang", $lang); + if (!$isNewer) { + $utilities->setReply('compareRevisions', array($currentBuild, '33333'), 'older'); + } + } + $repository->_utilities =& $utilities; + + $cacheKey = 'GalleryTranslator::SupportedLanguages'; + $supportedLanguages = array(); + + /* English */ + $supportedLanguages['en']['US']['description'] = 'English (US)'; + $supportedLanguages['en']['GB']['description'] = 'English (UK)'; + + /* Portuguese */ + $supportedLanguages['pt']['BR']['description'] = 'Português Brasileiro'; + $supportedLanguages['pt']['PT']['description'] = 'Português'; + GalleryDataCache::put($cacheKey, $supportedLanguages); + + return array($repository, $languages); + } + function testGetPluginUpgradeInfoForBasePackageUpgrade() { list ($repository, $languages) = $this->_prepareForGetPluginUpgradeInfo(); @@ -1448,46 +1489,322 @@ $info); } - function _prepareForGetPluginUpgradeInfo($isNewer=false) { - $repository = new GalleryRepository(); + function _setDownloadAndUnpackPackagesResponses($testData, &$callback) { + global $gallery; + $platform =& $gallery->getPlatform(); + + $platform->setReply('unlink', array('tempFile'), null); + + $utilities = new UnitTestRepositoryUtilities(); + $repository = new GalleryRepository(); + $repository->_source = 'test'; + $repository->_utilities =& $utilities; $repository->_index = $this->_index; - $utilities = new UnitTestRepositoryUtilities(); - $installedPackages = - array('base' => array('locked' => false, 'version' => '1.1', 'build' => '1'), - 'lang-en_GB' => array('locked' => 0, 'version' => '1.1', 'build' => '1')); - $utilities->setReply('getPluginPackages', array('module', 'testModule'), - array(null, $installedPackages)); - $utilities->setReply('isPluginCompatible', - array('module', GalleryCoreApi::getApiVersion(), GalleryModule::getApiVersion(), null), - true); - $utilities->setReply('compareVersions', array('1.1', '1.0.0', 1, '44444'), - array(null, 'newer')); - $languages = array(); - foreach (array('en_US', 'en_GB', 'pt_PT', 'pt_BR') as $lang) { - $currentBuild = $lang == 'en_GB' ? '1' : null; - $languages[$lang] = array('name' => $lang, 'currentBuild' => $currentBuild, - 'newBuild' => '33333', 'relation' => 'older', 'locked' => 0); - GalleryDataCache::put("GalleryTranslator::LanguageDescription::$lang", $lang); - if (!$isNewer) { - $utilities->setReply('compareRevisions', array($currentBuild, '33333'), 'older'); + + $cacheDir = $gallery->getConfig('repository.cache'); + + $pathes = array(); + foreach ($testData as $pluginType => $pluginFiles) { + foreach ($pluginFiles as $pluginId => $files) { + foreach ($files as $file => $fileData) { + $data = $file == 'descriptor' ? serialize($fileData['data']) + : $fileData['data']; + $path = sprintf('%ss/%s-%s-%s-%s', $pluginType, $pluginId, + $fileData['revision'], $fileData['build'], $file); + $pathes[] = $path; + } } } - $repository->_utilities =& $utilities; - $cacheKey = 'GalleryTranslator::SupportedLanguages'; - $supportedLanguages = array(); + $utilities->setReply('downloadAggregatePackages', array('test', $pathes), + array(null, 'tempFile')); - /* English */ - $supportedLanguages['en']['US']['description'] = 'English (US)'; - $supportedLanguages['en']['GB']['description'] = 'English (UK)'; + $packages = array(); + foreach ($testData as $pluginType => $pluginFiles) { + foreach ($pluginFiles as $pluginId => $files) { + $outputDir = GalleryCoreApi::getCodeBasePath("{$pluginType}s/$pluginId/"); + foreach ($files as $file => $fileData) { + if ($file == 'descriptor') { + $packages[$pluginType][$pluginId]['descriptor'] = $fileData['data']; + } else { + $path = sprintf('%ss/%s-%s-%s-%s', $pluginType, $pluginId, + $fileData['revision'], $fileData['build'], $file); + $packages[$pluginType][$pluginId]['files'][] = array('base', $path); + } + } + } + } - /* Portuguese */ - $supportedLanguages['pt']['BR']['description'] = 'Português Brasileiro'; - $supportedLanguages['pt']['PT']['description'] = 'Português'; - GalleryDataCache::put($cacheKey, $supportedLanguages); + $utilities->setReply('splitAggregatePackage', array('test', 'tempFile', $callback), + array(null, $packages)); - return array($repository, $languages); + /* Responses for _preverifyAggregatePackages */ + foreach ($testData as $pluginType => $pluginFiles) { + foreach ($pluginFiles as $pluginId => $testFiles) { + $outputDir = GalleryCoreApi::getCodeBasePath("{$pluginType}s/$pluginId/"); + $platform->setReply('file_exists', array($outputDir), true); + $platform->setReply('is_dir', array($outputDir), true); + if (!empty($testFiles['descriptor'])) { + $files = $testFiles; + $descriptor = $files['descriptor']['data']; + unset($files['descriptor']); + foreach ($files as $file => $fileData) { + if (empty($fileData['locked'])) { + $utilities->setReply('preVerifyPackage', + array($pluginType, $pluginId, 'base', $descriptor), + array()); + } else { + $utilities->setReply('preVerifyPackage', + array($pluginType, $pluginId,'base', $descriptor), + array($file)); + } + } + } + } + } + + foreach ($testData as $pluginType => $pluginFiles) { + foreach ($pluginFiles as $pluginId => $testFiles) { + $outputDir = GalleryCoreApi::getCodeBasePath("{$pluginType}s/$pluginId/"); + $outputDir = GalleryCoreApi::getCodeBasePath("{$pluginType}s/$pluginId/"); + if (!empty($testFiles['descriptor'])) { + $files = $testFiles; + $descriptor = $files['descriptor']['data']; + unset($files['descriptor']); + foreach ($files as $file => $fileData) { + if (empty($fileData['locked'])) { + $path = sprintf('%stest/%ss/%s-%s-%s-%s', $cacheDir, $pluginType, + $pluginId, $fileData['revision'], $fileData['build'], $file); + $utilities->setReply('unpackPackage', array($path , $outputDir), null); + $utilities->setReply('verifyPackageIntegrity', array($pluginType, + $pluginId, 'base', $descriptor), null); + $utilities->setReply('updatePackageMetaData', array($pluginType, + $pluginId,'base', $fileData['revision'], $fileData['build'], 0), + null); + } + } + } + } + } + return array($repository, $pathes); } + + function _buildDescriptor($pluginData) { + /* Leave the files empty so we don't have to generate a lot of platform calls */ + return array ( + 'header' => array ( + 'id' => $pluginData['id'], + 'version' => '1.0.0', + 'requiredCoreApi' => GalleryCoreApi::getApiVersion(), + 'requiredPluginApi' => GalleryModule::getApiVersion(), + 'stringsRevision' => $pluginData['revision'], + 'buildTimestamp' => $pluginData['build']), + 'descriptions' => array ( + 'en_US' => array ( + 'name' => $pluginData['name'], + 'description' => 'This is a test ' . $pluginData['type'], + 'groupLabel' => 'Test Group')), + 'directories' => array ( + 'locale/' => array ( + 'packages' => array ('base')), + 'locale/en_US/' => array ( + 'packages' => array ('lang-en_US')), + 'locale/en_US/LC_MESSAGES/' => array ( + 'packages' => array ('lang-en_US')), + 'images/' => array ( + 'packages' => array ('base')), + 'po/' => array ( + 'packages' => array ('base'))), + 'files' => array (), + 'languages' => array ( + '22222' => array ('en_US' => '33333'))); + } + + function testDownloadAndUnpackPackages() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + + $testData = array( + 'module' => array( + 'testModule' => array( + 'descriptor' => array( + 'revision' => '1.0.0', 'build' => '44444', + 'data' => $this->_buildDescriptor(array('id' => 'testModule', + 'type' => 'module', 'name' => 'Test Module', + 'revision' => '1.0.0', 'build' => '44444'))), + 'base.package' => array( + 'revision' => '1.0.0', 'build' => '44444', 'data' => 'Module Base Data'))), + 'theme' => array( + 'testTheme' => array( + 'descriptor' => array( + 'revision' => '1.0.0', 'build' => '11111', + 'data' => $this->_buildDescriptor(array('id' => 'testTheme', + 'type' => 'theme', 'name' => 'Test Theme', + 'revision' => '1.0.0', 'build' => '11111'))), + 'base.package' => array( + 'revision' => '1.0.0', 'build' => '11111', 'data' => 'Theme Base Data')))); + + $gallery->setConfig('repository.url', 'http://example.com/'); + $gallery->setConfig('repository.cache', '/cache/'); + + $mockAdapter = new MockTemplateAdapter(); + $expectedCallback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 1, 'total' => 10); + list ($repository, $files) = + $this->_setDownloadAndUnpackPackagesResponses($testData, $expectedCallback); + + $callback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 0, 'total' => 10); + list ($ret, $status, $count) = $repository->downloadAndUnpackPackages($files, + $callback); + if ($ret) { + return $ret; + } + + $this->assertEquals(2, $count, 'Unexpected number of files'); + $this->assertEquals(array(), $status, 'Unexpected status messages'); + $this->assertEquals(3, $callback['current'], 'Callback didn\'t match'); + $this->assertEquals(array('0.1', '0.2', '0.3'), + $mockAdapter->_progress, 'Reported progress didn\'t match'); + $this->assert($platform->isComplete(), $platform->getRemaining()); + $this->assert($repository->_utilities->isComplete(), + $repository->_utilities->getRemaining()); + } + + function testDownloadAndUnpackPackagesLockedFiles() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + + $testData = array( + 'module' => array( + 'testModule' => array( + 'descriptor' => array( + 'revision' => '1.0.0', 'build' => '44444', + 'data' => $this->_buildDescriptor(array('id' => 'testModule', + 'type' => 'module', 'name' => 'Test Module', + 'revision' => '1.0.0', 'build' => '44444'))), + 'base.package' => array( + 'revision' => '1.0.0', 'build' => '44444', 'data' => 'Module Base Data', + 'locked' => 1))), + 'theme' => array( + 'testTheme' => array( + 'descriptor' => array( + 'revision' => '1.0.0', 'build' => '11111', + 'data' => $this->_buildDescriptor(array('id' => 'testTheme', + 'type' => 'theme', 'name' => 'Test Theme', + 'revision' => '1.0.0', 'build' => '11111'))), + 'base.package' => array( + 'revision' => '1.0.0', 'build' => '11111', 'data' => 'Theme Base Data')))); + + $gallery->setConfig('repository.url', 'http://example.com/'); + $gallery->setConfig('repository.cache', '/cache/'); + + $mockAdapter = new MockTemplateAdapter(); + $expectedCallback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 1, 'total' => 10); + list ($repository, $files) = + $this->_setDownloadAndUnpackPackagesResponses($testData, $expectedCallback); + + $callback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 0, 'total' => 10); + list ($ret, $status, $count) = $repository->downloadAndUnpackPackages($files, + $callback); + if ($ret) { + return $ret; + } + + $this->assertEquals(1, $count, 'Unexpected number of files'); + $expected['failedToInstall'] = array('module' => array( + 'testModule' => array('modules/testModule-1.0.0-44444-base.package'))); + $this->assertEquals($expected, $status, 'Unexpected status messages'); + $this->assertEquals(3, $callback['current'], 'Callback didn\'t match'); + $this->assertEquals(array('0.1', '0.2', '0.3'), + $mockAdapter->_progress, 'Reported progress didn\'t match'); + $this->assert($platform->isComplete(), $platform->getRemaining()); + $this->assert($repository->_utilities->isComplete(), + $repository->_utilities->getRemaining()); + } + + function testDownloadAndUnpackPackagesNoDescriptors() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + + $testData = array( + 'module' => array( + 'testModule' => array( + 'base.package' => array( + 'revision' => '11111', 'build' => '22222', 'data' => 'Module Base Data'))), + 'theme' => array( + 'testTheme' => array( + 'descriptor' => array( + 'revision' => '1.0.0', 'build' => '11111', + 'data' => $this->_buildDescriptor(array('id' => 'testTheme', + 'type' => 'theme', 'name' => 'Test Theme', + 'revision' => '1.0.0', 'build' => '11111'))), + 'base.package' => array( + 'revision' => '1.0.0', 'build' => '11111', 'data' => 'Theme Base Data')))); + + $gallery->setConfig('repository.url', 'http://example.com/'); + $gallery->setConfig('repository.cache', '/cache/'); + + $mockAdapter = new MockTemplateAdapter(); + $expectedCallback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 1, 'total' => 10); + list ($repository, $files) = + $this->_setDownloadAndUnpackPackagesResponses($testData, $expectedCallback); + + $callback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 0, 'total' => 10); + list ($ret, $status, $count) = $repository->downloadAndUnpackPackages($files, + $callback); + if ($ret) { + return $ret; + } + + $expected['failedToInstall'] = array('module' => array( + 'testModule' => array('modules/testModule-11111-22222-base.package'))); + + $this->assertEquals(1, $count, 'Unexpected number of files'); + $this->assertEquals($expected, $status, 'Unexpected status messages'); + $this->assertEquals(4, $callback['current'], 'Callback didn\'t match'); + $this->assertEquals(array('0.1', '0.2', '0.3', '0.4'), + $mockAdapter->_progress, 'Reported progress didn\'t match'); + $this->assert($platform->isComplete(), $platform->getRemaining()); + $this->assert($repository->_utilities->isComplete(), + $repository->_utilities->getRemaining()); + } + + function testDownloadAndUnpackPackagesFailed() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + + $files = array('modules/testModule-11111-22222.descriptor' => 'Module Base Data', + 'themes/testTheme-11111-22222.descriptor' => 'Theme Base Data'); + + $repository = new GalleryRepository(); + $repository->_source = 'test'; + $repository->_utilities = new UnitTestRepositoryUtilities(); + $repository->_index = $this->_index; + + $repository->_utilities->setReply('downloadAggregatePackages', array('test', + array_keys($files)), array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE), null)); + + $mockAdapter = new MockTemplateAdapter(); + $callback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 0, 'total' => 10); + + list ($ret, $status, $count) = $repository->downloadAndUnpackPackages(array_keys($files), + $callback); + $this->assertErrorEquals(ERROR_PLATFORM_FAILURE, $ret); + + $this->assert($platform->isComplete(), $platform->getRemaining()); + $this->assert($repository->_utilities->isComplete(), + $repository->_utilities->getRemaining()); + } } class RepositoryTest_GalleryRepository { Modified: trunk/gallery2/modules/core/test/phpunit/RepositoryTestStorage.class =================================================================== --- trunk/gallery2/modules/core/test/phpunit/RepositoryTestStorage.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/test/phpunit/RepositoryTestStorage.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -28,6 +28,7 @@ */ class RepositoryTestStorage { + /** @todo Convert this to use UnitTestStorage */ var $_addedMapData; var $_updatedMapData; var $_searchResults; @@ -97,6 +98,14 @@ function rollbackTransaction() { } + + function getUniqueId($sequence) { + return 1; + } + + function getAffectedRows($useNonTransactionalConnection) { + return 1; + } } class RepositoryTestSearchResults { Modified: trunk/gallery2/modules/core/test/phpunit/RepositoryUtilitiesTest.class =================================================================== --- trunk/gallery2/modules/core/test/phpunit/RepositoryUtilitiesTest.class 2008-03-11 23:55:05 UTC (rev 17513) +++ trunk/gallery2/modules/core/test/phpunit/RepositoryUtilitiesTest.class 2008-03-12 05:52:22 UTC (rev 17514) @@ -511,7 +511,7 @@ $gallery->setPlatform($platform); $utilties = new GalleryRepositoryUtilities(); - $errors = $utilties->preVerifyPackage('p1', $testDescriptor); + $errors = $utilties->preVerifyPackage('module', 'm1', 'p1', $testDescriptor); $this->assertEquals(array(), $errors); $this->assert($platform->isComplete(), $platform->getRemaining()); @@ -534,7 +534,7 @@ $gallery->setPlatform($platform); $utilties = new GalleryRepositoryUtilities(); - $errors = $utilties->preVerifyPackage('p1', $testDescriptor); + $errors = $utilties->preVerifyPackage('module', 'm1', 'p1', $testDescriptor); $this->assertEquals(array(), $errors); $this->assert($platform->isComplete(), $platform->getRemaining()); @@ -557,19 +557,17 @@ $gallery->setPlatform($platform); $utilties = new GalleryRepositoryUtilities(); - $errors = $utilties->preVerifyPackage('p1', $testDescriptor); + $errors = $utilties->preVerifyPackage('module', 'm1', 'p1', $testDescriptor); $this->assertEquals(array("$modules/m1/f1", "$modules/m1/d2/f2"), $errors); $this->assert($platform->isComplete(), $platform->getRemaining()); } function _getDescriptorForPreVerifyPackageTests() { - return array( - 'pluginType' => 'module', 'pluginId' => 'm1', - 'contents' => array('files' => array( + return array('files' => array( 'f1' => array('packages' => array('p1'), 'bytes' => 1, 'hash' => md5('f1')), 'd2/f2' => array('packages' => array('p1'), 'bytes' => 1, 'hash' => md5('f2')), - 'd3/f3' => array('packages' => array('p2'), 'bytes' => 1, 'hash' => md5('f3'))))); + 'd3/f3' => array('packages' => array('p2'), 'bytes' => 1, 'hash' => md5('f3')))); } function testPreVerifyPackageMissingOneDirectory() { @@ -589,7 +587,7 @@ $gallery->setPlatform($platform); $utilties = new GalleryRepositoryUtilities(); - $errors = $utilties->preVerifyPackage('p1', $testDescriptor); + $errors = $utilties->preVerifyPackage('module', 'm1', 'p1', $testDescriptor); $this->assertEquals(array(), $errors); $this->assert($platform->isComplete(), $platform->getRemaining()); @@ -614,7 +612,7 @@ $gallery->setPlatform($platform); $utilties = new GalleryRepositoryUtilities(); - $errors = $utilties->preVerifyPackage('p1', $testDescriptor); + $errors = $utilties->preVerifyPackage('module', 'm1', 'p1', $testDescriptor); $this->assertEquals(array(), $errors); $this->assert($platform->isComplete(), $platform->getRemaining()); @@ -639,7 +637,7 @@ $gallery->setPlatform($platform); $utilties = new GalleryRepositoryUtilities(); - $errors = $utilties->preVerifyPackage('p1', $testDescriptor); + $errors = $utilties->preVerifyPackage('module', 'm1', 'p1', $testDescriptor); $this->assertEquals(array("$modules/m1/d2/f2"), $errors); $this->assert($platform->isComplete(), $platform->getRemaining()); @@ -658,7 +656,7 @@ $gallery->setPlatform($platform); $utilties = new GalleryRepositoryUtilities(); - $errors = $utilties->preVerifyPackage('p1', $testDescriptor); + $errors = $utilties->preVerifyPackage('module', 'm1', 'p1', $testDescriptor); $this->assertEquals(array("$modules/m1/"), $errors); $this->assert($platform->isComplete(), $platform->getRemaining()); @@ -705,6 +703,290 @@ $this->assert($platform->isComplete(), $platform->getRemaining()); } + + function _setSplitPackagesResponses($file, $rawData, $error=array()) { + global $gallery; + $platform =& $gallery->getPlatform(); + $phpVm = $gallery->getPhpVm(); + + $repositoryCachePath = $gallery->getConfig('repository.cache'); + + $data = is_array($rawData) ? serialize($rawData) : serialize(array($rawData)); + $dataLength = strlen($data); + if (empty($error['invalid'])) { + $isGzip = substr($file, -3) == '.gz'; + $platform->setReply('fgets', array('handle', 4096), "file: $file {$dataLength}\r\n"); + $platform->setReply('fread', array('handle', $dataLength), $data); + if (empty($error['returnGzip'])) { + if ($isGzip) { + $phpVm->setReply('function_exists', array('gzinflate'), true); + $phpVm->setReply('gzinflate', array($data, null), $data); + $file = substr($file, 0, -3); + } + $platform->setReply('file_put_contents', + array("{$repositoryCachePath}test/$file", $data), true); + } else { + $phpVm->setReply('function_exists', array('gzinflate'), false); + } + } else { + $platform->setReply('fgets', array('handle', 4096), "file:$file {$dataLength}\r\n"); + } + } + + function testSplitAggregatePackage() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + $gallery->_phpVm = new UnitTestPhpVm(); + $phpVm = $gallery->getPhpVm(); + + $gallery->setConfig('repository.cache', '/cache/'); + + $platform->setReply('fopen', array('tempOut', 'r', null), 'handle'); + $this->_setSplitPackagesResponses('modules/testModule-1.0-22222.descriptor', + 'Module Descriptor Data'); + $this->_setSplitPackagesResponses('modules/testModule-1.0-22222-base.package', + 'Module Base Data'); + $this->_setSplitPackagesResponses('modules/testModule-lang-en_GB-11111-22222.package', + 'Module Language en_GB Data'); + $this->_setSplitPackagesResponses('themes/testTheme-1.0.1-22222.descriptor.gz', + 'Theme Descriptor Data'); + $this->_setSplitPackagesResponses('themes/testTheme-1.0.1.123-22222-base.package.gz', + 'Theme Base Data'); + $this->_setSplitPackagesResponses('themes/testTheme-lang-en_GB-11111-22222.package.gz', + 'Theme Language en_GB Data'); + $platform->setReply('fgets', array('handle', 4096), false); + $platform->setReply('fclose', array('handle'), true); + + $mockAdapter = new MockTemplateAdapter(); + $callback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 0, 'total' => 10); + + $utilities = new GalleryRepositoryUtilities(); + list ($ret, $packages) = $utilities->splitAggregatePackage('test', 'tempOut', $callback); + if ($ret) { + return $ret; + } + + $expected = array( + 'module' => array('testModule' => array( + 'files' => array( + array('base', 'modules/testModule-1.0-22222-base.package'), + array('lang-en_GB', 'modules/testModule-lang-en_GB-11111-22222.package')), + 'descriptor' => array('Module Descriptor Data'))), + 'theme' => array('testTheme' => array( + 'files' => array( + array('base', 'themes/testTheme-1.0.1.123-22222-base.package'), + array('lang-en_GB', 'themes/testTheme-lang-en_GB-11111-22222.package')), + 'descriptor' => array('Theme Descriptor Data')))); + + $this->assertEquals($expected, $packages, 'Unexpected Package list returned'); + $this->assertEquals(6, $callback['current'], 'Callback didn\'t match'); + $this->assertEquals(array('0.1', '0.2', '0.3', '0.4', '0.5', '0.6'), + $mockAdapter->_progress, 'Reported progress didn\'t match'); + $this->assert($platform->isComplete(), $platform->getRemaining()); + } + + function testSplitAggregatePackageInvalidInput() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + + $gallery->setConfig('repository.cache', '/cache/'); + + $platform->setReply('fopen', array('tempOut', 'r', null), 'handle'); + $this->_setSplitPackagesResponses('themes/testTheme-11111-22222.descriptor', + 'Descriptor Data', array('invalid' => 1)); + $platform->setReply('fclose', array('handle'), true); + + $mockAdapter = new MockTemplateAdapter(); + $callback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 0, 'total' => 10); + + $utilities = new GalleryRepositoryUtilities(); + list ($ret, $packages) = $utilities->splitAggregatePackage('test', 'tempOut', $callback); + $this->assertErrorEquals(ERROR_UNSUPPORTED_FILE_TYPE, $ret); + + $this->assert($platform->isComplete(), $platform->getRemaining()); + } + + function testSplitAggregatePackageUnexpectedGzipFile() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + $gallery->_phpVm = new UnitTestPhpVm(); + $phpVm = $gallery->getPhpVm(); + + $gallery->setConfig('repository.cache', '/cache/'); + + $platform->setReply('fopen', array('tempOut', 'r', null), 'handle'); + $this->_setSplitPackagesResponses('modules/testModule-1.0-22222.descriptor', + 'Module Descriptor Data'); + $this->_setSplitPackagesResponses('modules/testModule-1.0-22222-base.package.gz', + 'Module Base Data', array('returnGzip' => 1)); + $platform->setReply('fclose', array('handle'), true); + + $mockAdapter = new MockTemplateAdapter(); + $callback = array('method' => array($mockAdapter, 'updateProgressBar'), + 'title' => 'Test', 'current' => 0, 'total' => 10); + + $utilities = new GalleryRepositoryUtilities(); + list ($ret, $packages) = $utilities->splitAggregatePackage('test', 'tempOut', $callback); + + $this->assertErrorEquals(ERROR_UNSUPPORTED_FILE_TYPE, $ret); + + $this->assert($phpVm->isComplete(), $phpVm->getRemaining()); + $this->assert($platform->isComplete(), $platform->getRemaining()); + } + + function _setDownloadHeaders($handle, $failed=null) { + global $gallery; + $platform =& $gallery->getPlatform(); + + if (!empty($failed['download'])) { + $platform->setReply('fgets', array($handle, 4096), + "HTTP/1.1 {$failed['download']}\r\n"); + $platform->setReply('feof', array('fd'), true); + } else { + $platform->setReply('fgets', array($handle, 4096), "HTTP/1.1 200 OK\r\n"); + $platform->setReply('feof', array($handle), false); + $platform->setReply('fgets', array($handle, 4096), + "Expires: Sun, 19 Nov 1978 05:00:00 GMT\r\n"); + $platform->setReply('feof', array($handle), false); + $platform->setReply('fgets', array($handle, 4096), + "Content-Type: application/g2-multipart-pkg; charset=utf-8\r\n"); + $platform->setReply('feof', array($handle), false); + $platform->setReply('fgets', array($handle, 4096), "\r\n"); + } + } + + function _setAggregrateDownloadResponses($files, $errors=array()) { + global $gallery; + $platform =& $gallery->getPlatform(); + + /* Create a temporary file for the multipart download file */ + $tmpDir = $gallery->getConfig('data.gallery.tmp'); + $outputFile = $tmpDir . 'multipart1234'; + $platform->setReply('tempnam', array($tmpDir, 'multipart'), $outputFile); + $platform->setReply('file_exists', array($outputFile), empty($errors['tempDir'])); + if (!empty($errors['tempDir'])) { + return; + } + + $platform->setReply('fsockopen', array('gallery.menalto.com', 80, null, null, 5), 'fd'); + + $seperator = $requestData = $responseData = ''; + $counter = 0; + + foreach ($files as $file => $data) { + $encodedFile = urlencode($file); + /* Request data to remote Server */ + $requestData .= sprintf('%sfiles%%5B%d%%5D=%s', $seperator, $counter++, $encodedFile); + $seperator = '&'; + + if (empty($errors['download'])) { + /* Build expected Response */ + $responseData .= sprintf("file: %s %d\n%s", $encodedFile, strlen($data), $data); + } + } + + $requestDataLength = strlen($requestData); + $requestData = "POST /repository/test/multipart/?{$this->_apis} " + . "HTTP/1.0\r\nHost: gallery.menalto.com\r\n" + . "Content-Type: application/x-www-form-urlencoded\r\n" + . "Content-Length: {$requestDataLength}\r\n\r\n" . $requestData; + + $platform->setReply('fwrite',array('fd', $requestData, null), true); + $platform->setReply('fflush', array('fd'), null); + + $this->_setDownloadHeaders('fd', $errors); + $platform->setReply('fopen', array($outputFile, 'wb', null), 'handle'); + if (empty($errors['download'])) { + $platform->setReply('feof', array('fd'), false); + + $platform->setReply('fread', array('fd', 4096), $responseData); + $platform->setReply('fwrite', array('handle', $responseData, null), + strlen($responseData)); + } + + $platform->setReply('feof', array('fd'), true); + $platform->setReply('fclose', array('handle'), true); + $platform->setReply('fclose', array('fd'), true); + + if (!empty($errors['download'])) { + $platform->setReply('unlink', array($outputFile), true); + } + } + + function testDownloadAggregatePackages() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + $gallery->_phpVm = new UnitTestPhpVm(); + $phpVm = $gallery->getPhpVm(); + + $phpVm->setReply('function_exists', array('gzinflate'), false); + + $files = array('modules/testModule-1.0.9-22222.descriptor' => 'Descriptor Data', + 'modules/testModule-1.0.9-22222-base.package' => 'Base Package Data', + 'modules/testModule-lang-en_GB-11111-22222.package' => 'Language Pack Data'); + + $this->_setAggregrateDownloadResponses($files); + + $utilities = new GalleryRepositoryUtilities(); + list ($ret, $packages) = $utilities->downloadAggregatePackages('test', array_keys($files)); + if ($ret) { + return $ret; + } + + $this->assert($platform->isComplete(), $platform->getRemaining()); + $this->assert($phpVm->isComplete(), $phpVm->getRemaining()); + } + + function testDownloadAggregatePackagesFailedDownload() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + $gallery->_phpVm = new UnitTestPhpVm(); + $phpVm = $gallery->getPhpVm(); + + $phpVm->setReply('function_exists', array('gzinflate'), false); + + $files = array('modules/testModule-1.0.9-22222.descriptor' => '0123456789', + 'modules/testModule-1.0.9-22222-base.package' => '0123456789', + 'modules/testModule-lang-en_GB-11111-22222.package' => '0123456789'); + + $this->_setAggregrateDownloadResponses($files, + array('download' => '500 Internal Server Error')); + + $utilities = new GalleryRepositoryUtilities(); + list ($ret, $packages) = $utilities->downloadAggregatePackages('test', array_keys($files)); + $this->assertErrorEquals(ERROR_BAD_PATH, $ret); + + $this->assert($platform->isComplete(), $platform->getRemaining()); + $this->assert($phpVm->isComplete(), $phpVm->getRemaining()); + } + + function testDownloadAggregatePackagesTempDirectoryMissing() { + global $gallery; + $gallery->setPlatform(new UnitTestPlatform()); + $platform =& $gallery->getPlatform(); + + $gallery->setConfig('repository.cache', '/cache/'); + + $tmpDir = $gallery->getConfig('data.gallery.tmp'); + + $files = array('modules/testModule-1.0.9-22222.descriptor' => '0123456789', + 'modules/testModule-1.0.9-22222-base.package' => '0123456789', + 'modules/testModule-lang-en_GB-11111-22222.package' => '0123456789'); + + $this->_setAggregrateDownloadResponses($files, array('tempDir' => 1)); + + $utilities = new GalleryRepositoryUtilities(); + list ($ret, $packages) = $utilities->downloadAggregatePackages('test', array_keys($files)); + $this->assertErrorEquals(ERROR_PLATFORM_FAILURE, $ret); + $this->assert($platform->isComplete(), $platform->getRemaining()); + } } class RepositoryUtilitiesTestPhpVm extends GalleryPhpVm { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |