Issue #2002116 by damiankloip, jhedstrom, ParisLiakos, dawehner: Convert core/modules/update/lib/Drupal/update/Tests/UpdateCoreUnitTest.php to phpunit.

8.0.x
webchick 2013-10-08 22:36:58 -07:00
parent 4d6724c151
commit 332530474e
5 changed files with 268 additions and 167 deletions

View File

@ -1,77 +0,0 @@
<?php
/**
* @file
* Definition of Drupal\update\Tests\UpdateCoreUnitTest.
*/
namespace Drupal\update\Tests;
use Drupal\simpletest\UnitTestBase;
/**
* Tests update functionality unrelated to the database.
*/
class UpdateCoreUnitTest extends UnitTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('update');
public static function getInfo() {
return array(
'name' => "Unit tests",
'description' => 'Test update functionality unrelated to the database.',
'group' => 'Update',
);
}
function setUp() {
parent::setUp();
module_load_include('inc', 'update', 'update.fetch');
}
/**
* Tests that _update_build_fetch_url() builds the URL correctly.
*/
function testUpdateBuildFetchUrl() {
//first test that we didn't break the trivial case
$project['name'] = 'update_test';
$project['project_type'] = '';
$project['info']['version'] = '';
$project['info']['project status url'] = 'http://www.example.com';
$project['includes'] = array('module1' => 'Module 1', 'module2' => 'Module 2');
$site_key = '';
$expected = 'http://www.example.com/' . $project['name'] . '/' . \Drupal::CORE_COMPATIBILITY;
$url = _update_build_fetch_url($project, $site_key);
$this->assertEqual($url, $expected, "'$url' when no site_key provided should be '$expected'.");
//For disabled projects it shouldn't add the site key either.
$site_key = 'site_key';
$project['project_type'] = 'disabled';
$expected = 'http://www.example.com/' . $project['name'] . '/' . \Drupal::CORE_COMPATIBILITY;
$url = _update_build_fetch_url($project, $site_key);
$this->assertEqual($url, $expected, "'$url' should be '$expected' for disabled projects.");
//for enabled projects, adding the site key
$project['project_type'] = '';
$expected = 'http://www.example.com/' . $project['name'] . '/' . \Drupal::CORE_COMPATIBILITY;
$expected .= '?site_key=site_key';
$expected .= '&list=' . rawurlencode('module1,module2');
$url = _update_build_fetch_url($project, $site_key);
$this->assertEqual($url, $expected, "When site_key provided, '$url' should be '$expected'.");
// http://drupal.org/node/1481156 test incorrect logic when URL contains
// a question mark.
$project['info']['project status url'] = 'http://www.example.com/?project=';
$expected = 'http://www.example.com/?project=/' . $project['name'] . '/' . \Drupal::CORE_COMPATIBILITY;
$expected .= '&site_key=site_key';
$expected .= '&list=' . rawurlencode('module1,module2');
$url = _update_build_fetch_url($project, $site_key);
$this->assertEqual($url, $expected, "When ? is present, '$url' should be '$expected'.");
}
}

View File

@ -0,0 +1,149 @@
<?php
/**
* @file
* Contains \Drupal\update\UpdateFetcher.
*/
namespace Drupal\update;
use Drupal\Core\Config\ConfigFactory;
use Guzzle\Http\ClientInterface;
use Guzzle\Http\Exception\RequestException;
/**
* Fetches project information from remote locations.
*/
class UpdateFetcher {
/**
* URL to check for updates, if a given project doesn't define its own.
*/
const UPDATE_DEFAULT_URL = 'http://updates.drupal.org/release-history';
/**
* The fetch url configured in the update settings.
*
* @var string
*/
protected $fetchUrl;
/**
* The HTTP client to fetch the feed data with.
*
* @var \Guzzle\Http\ClientInterface
*/
protected $httpClient;
/**
* Constructs a UpdateFetcher.
*
* @param \Drupal\Core\Config\ConfigFactory $config_factory
* The config factory.
* @param \Guzzle\Http\ClientInterface $http_client
* A Guzzle client object.
*/
public function __construct(ConfigFactory $config_factory, ClientInterface $http_client) {
$this->fetchUrl = $config_factory->get('update.settings')->get('fetch.url');
$this->httpClient = $http_client;
}
/**
* Retrieves the project information.
*
* @param array $project
* The array of project information from update_get_projects().
* @param string $site_key
* (optional) The anonymous site key hash. Defaults to an empty string.
*
* @return string
* The project information fetched as string. Empty string upon failure.
*/
public function fetchProjectData(array $project, $site_key = '') {
$url = $this->buildFetchUrl($project, $site_key);
$data = '';
try {
$data = $this->httpClient
->get($url, array('Accept' => 'text/xml'))
->send()
->getBody(TRUE);
}
catch (RequestException $exception) {
watchdog_exception('update', $exception);
}
return $data;
}
/**
* Generates the URL to fetch information about project updates.
*
* This figures out the right URL to use, based on the project's .info.yml file
* and the global defaults. Appends optional query arguments when the site is
* configured to report usage stats.
*
* @param array $project
* The array of project information from update_get_projects().
* @param string $site_key
* (optional) The anonymous site key hash. Defaults to an empty string.
*
* @return string
* The URL for fetching information about updates to the specified project.
*
* @see update_fetch_data()
* @see _update_process_fetch_task()
* @see update_get_projects()
*/
public function buildFetchUrl(array $project, $site_key = '') {
$name = $project['name'];
$url = $this->getFetchBaseUrl($project);
$url .= '/' . $name . '/' . \Drupal::CORE_COMPATIBILITY;
// Only append usage infomation if we have a site key and the project is
// enabled. We do not want to record usage statistics for disabled projects.
if (!empty($site_key) && (strpos($project['project_type'], 'disabled') === FALSE)) {
// Append the site key.
$url .= (strpos($url, '?') !== FALSE) ? '&' : '?';
$url .= 'site_key=';
$url .= rawurlencode($site_key);
// Append the version.
if (!empty($project['info']['version'])) {
$url .= '&version=';
$url .= rawurlencode($project['info']['version']);
}
// Append the list of modules or themes enabled.
$list = array_keys($project['includes']);
$url .= '&list=';
$url .= rawurlencode(implode(',', $list));
}
return $url;
}
/**
* Returns the base of the URL to fetch available update data for a project.
*
* @param array $project
* The array of project information from update_get_projects().
*
* @return string
* The base of the URL used for fetching available update data. This does
* not include the path elements to specify a particular project, version,
* site_key, etc.
*
* @see \Drupal\update\UpdateFetcher::getFetchBaseUrl()
*/
public function getFetchBaseUrl($project) {
if (isset($project['info']['project status url'])) {
$url = $project['info']['project status url'];
}
else {
$url = $this->fetchUrl;
if (empty($url)) {
$url = static::UPDATE_DEFAULT_URL;
}
}
return $url;
}
}

View File

@ -0,0 +1,114 @@
<?php
/**
* @file
* Contains \Drupal\update\Tests\UpdateFetcherTest.
*/
namespace Drupal\update\Tests;
use Drupal\Tests\UnitTestCase;
use Drupal\update\UpdateFetcher;
if (!defined('DRUPAL_CORE_COMPATIBILITY')) {
define('DRUPAL_CORE_COMPATIBILITY', '8.x');
}
/**
* Tests update functionality unrelated to the database.
*/
class UpdateFetcherTest extends UnitTestCase {
/**
* The update fetcher to use.
*
* @var \Drupal\update\UpdateFetcher
*/
protected $updateFetcher;
public static function getInfo() {
return array(
'name' => 'Core update tests',
'description' => 'Test update functionality unrelated to the database.',
'group' => 'Update',
);
}
/**
* {@inheritdoc}
*/
protected function setUp() {
$config_factory = $this->getConfigFactoryStub(array('update.settings' => array('fetch_url' => 'http://www.example.com')));
$this->updateFetcher = new UpdateFetcher($config_factory, $this->getMock('Guzzle\Http\Client'));
}
/**
* Tests that buildFetchUrl() builds the URL correctly.
*
* @param array $project
* A keyed array of project information matching results from update_get_projects().
* @param string $site_key
* A string to mimic an anonymous site key hash.
* @param string $expected
* The expected url returned from UpdateFetcher::buildFetchUrl()
*
* @dataProvider providerTestUpdateBuildFetchUrl
*
* @see \Drupal\update\UpdateFetcher::buildFetchUrl()
*/
public function testUpdateBuildFetchUrl(array $project, $site_key, $expected) {
$url = $this->updateFetcher->buildFetchUrl($project, $site_key);
$this->assertEquals($url, $expected);
}
/**
* Provide test data for self::testUpdateBuildFetchUrl().
*
* @return array
* An array of arrays, each containing:
* - 'project' - An array matching a project's .info file structure.
* - 'site_key' - An arbitrary site key.
* - 'expected' - The expected url from UpdateFetcher::buildFetchUrl().
*/
public function providerTestUpdateBuildFetchUrl() {
$data = array();
// First test that we didn't break the trivial case.
$project['name'] = 'update_test';
$project['project_type'] = '';
$project['info']['version'] = '';
$project['info']['project status url'] = 'http://www.example.com';
$project['includes'] = array('module1' => 'Module 1', 'module2' => 'Module 2');
$site_key = '';
$expected = 'http://www.example.com/' . $project['name'] . '/' . DRUPAL_CORE_COMPATIBILITY;
$data[] = array($project, $site_key, $expected);
// For disabled projects it shouldn't add the site key either.
$site_key = 'site_key';
$project['project_type'] = 'disabled';
$expected = 'http://www.example.com/' . $project['name'] . '/' . DRUPAL_CORE_COMPATIBILITY;
$data[] = array($project, $site_key, $expected);
// For enabled projects, adding the site key
$project['project_type'] = '';
$expected = 'http://www.example.com/' . $project['name'] . '/' . DRUPAL_CORE_COMPATIBILITY;
$expected .= '?site_key=site_key';
$expected .= '&list=' . rawurlencode('module1,module2');
$data[] = array($project, $site_key, $expected);
// http://drupal.org/node/1481156 test incorrect logic when URL contains
// a question mark.
$project['info']['project status url'] = 'http://www.example.com/?project=';
$expected = 'http://www.example.com/?project=/' . $project['name'] . '/' . DRUPAL_CORE_COMPATIBILITY;
$expected .= '&site_key=site_key';
$expected .= '&list=' . rawurlencode('module1,module2');
$data[] = array($project, $site_key, $expected);
return $data;
}
}

View File

@ -5,8 +5,8 @@
* Code required only when fetching information about available updates.
*/
use Guzzle\Http\Exception\RequestException;
use Drupal\Component\Utility\Crypt;
use Drupal\update\UpdateFetcher;
/**
* Page callback: Checks for updates and displays the update status report.
@ -148,21 +148,13 @@ function _update_process_fetch_task($project) {
$success = FALSE;
$available = array();
$site_key = Crypt::hmacBase64($base_url, drupal_get_private_key());
$url = _update_build_fetch_url($project, $site_key);
$fetch_url_base = _update_get_fetch_url_base($project);
$site_key = Crypt::hmacBase64($base_url, \Drupal::service('private_key')->get());
$update_fetcher = new UpdateFetcher(\Drupal::service('config.factory'), \Drupal::service('http_default_client'));
$fetch_url_base = $update_fetcher->getFetchBaseUrl($project);
$project_name = $project['name'];
if (empty($fail[$fetch_url_base]) || $fail[$fetch_url_base] < $max_fetch_attempts) {
try {
$data = \Drupal::httpClient()
->get($url, array('Accept' => 'text/xml'))
->send()
->getBody(TRUE);
}
catch (RequestException $exception) {
watchdog_exception('update', $exception);
}
$data = $update_fetcher->fetchProjectData($project, $site_key);
}
if (!empty($data)) {
@ -257,78 +249,6 @@ function _update_create_fetch_task($project) {
}
}
/**
* Generates the URL to fetch information about project updates.
*
* This figures out the right URL to use, based on the project's .info.yml file
* and the global defaults. Appends optional query arguments when the site is
* configured to report usage stats.
*
* @param $project
* The array of project information from update_get_projects().
* @param $site_key
* (optional) The anonymous site key hash. Defaults to an empty string.
*
* @return
* The URL for fetching information about updates to the specified project.
*
* @see update_fetch_data()
* @see _update_process_fetch_task()
* @see update_get_projects()
*/
function _update_build_fetch_url($project, $site_key = '') {
$name = $project['name'];
$url = _update_get_fetch_url_base($project);
$url .= '/' . $name . '/' . \Drupal::CORE_COMPATIBILITY;
// Only append usage infomation if we have a site key and the project is
// enabled. We do not want to record usage statistics for disabled projects.
if (!empty($site_key) && (strpos($project['project_type'], 'disabled') === FALSE)) {
// Append the site key.
$url .= (strpos($url, '?') !== FALSE) ? '&' : '?';
$url .= 'site_key=';
$url .= rawurlencode($site_key);
// Append the version.
if (!empty($project['info']['version'])) {
$url .= '&version=';
$url .= rawurlencode($project['info']['version']);
}
// Append the list of modules or themes enabled.
$list = array_keys($project['includes']);
$url .= '&list=';
$url .= rawurlencode(implode(',', $list));
}
return $url;
}
/**
* Returns the base of the URL to fetch available update data for a project.
*
* @param $project
* The array of project information from update_get_projects().
*
* @return
* The base of the URL used for fetching available update data. This does
* not include the path elements to specify a particular project, version,
* site_key, etc.
*
* @see _update_build_fetch_url()
*/
function _update_get_fetch_url_base($project) {
if (isset($project['info']['project status url'])) {
$url = $project['info']['project status url'];
}
else {
$url = \Drupal::config('update.settings')->get('fetch.url');
if (empty($url)) {
$url = UPDATE_DEFAULT_URL;
}
}
return $url;
}
/**
* Performs any notifications that should be done once cron fetches new data.
*

View File

@ -11,11 +11,6 @@
* ability to install contributed modules and themes via an user interface.
*/
/**
* URL to check for updates, if a given project doesn't define its own.
*/
const UPDATE_DEFAULT_URL = 'http://updates.drupal.org/release-history';
// These are internally used constants for this code, do not modify.
/**