upgrade.test 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. <?php
  2. /**
  3. * Perform end-to-end tests of the upgrade path.
  4. */
  5. abstract class UpgradePathTestCase extends DrupalWebTestCase {
  6. /**
  7. * The file path(s) to the dumped database(s) to load into the child site.
  8. *
  9. * @var array
  10. */
  11. var $databaseDumpFiles = array();
  12. /**
  13. * Flag that indicates whether the child site has been upgraded.
  14. */
  15. var $upgradedSite = FALSE;
  16. /**
  17. * Array of errors triggered during the upgrade process.
  18. */
  19. var $upgradeErrors = array();
  20. /**
  21. * Array of modules loaded when the test starts.
  22. */
  23. var $loadedModules = array();
  24. /**
  25. * Flag to indicate whether zlib is installed or not.
  26. */
  27. var $zlibInstalled = TRUE;
  28. /**
  29. * Flag to indicate whether there are pending updates or not.
  30. */
  31. var $pendingUpdates = TRUE;
  32. /**
  33. * Flag to indicate whether to skip upgrade tests.
  34. */
  35. var $skipUpgradeTest = FALSE;
  36. /**
  37. * Constructs an UpgradePathTestCase object.
  38. *
  39. * @param $test_id
  40. * (optional) The ID of the test. Tests with the same id are reported
  41. * together.
  42. */
  43. function __construct($test_id = NULL) {
  44. parent::__construct($test_id);
  45. $connection_info = Database::getConnectionInfo();
  46. $this->skipUpgradeTest = (bool) ($connection_info['default']['driver'] == 'pgsql');
  47. $this->zlibInstalled = function_exists('gzopen');
  48. }
  49. /**
  50. * Prepares the appropriate session for the release of Drupal being upgraded.
  51. */
  52. protected function prepareD7Session() {
  53. // Generate and set a D6-compatible session cookie.
  54. $this->curlInitialize();
  55. $sid = drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55));
  56. $session_name = update_get_d6_session_name();
  57. curl_setopt($this->curlHandle, CURLOPT_COOKIE, rawurlencode($session_name) . '=' . rawurlencode($sid));
  58. // Force our way into the session of the child site.
  59. drupal_save_session(TRUE);
  60. // A session cannot be written without the ssid column which is missing on
  61. // Drupal 6 sites.
  62. db_add_field('sessions', 'ssid', array('description' => "Secure session ID. The value is generated by Drupal's session handlers.", 'type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''));
  63. _drupal_session_write($sid, '');
  64. // Remove the temporarily added ssid column.
  65. db_drop_field('sessions', 'ssid');
  66. drupal_save_session(FALSE);
  67. }
  68. /**
  69. * Overrides DrupalWebTestCase::setUp() for upgrade testing.
  70. *
  71. * @see DrupalWebTestCase::prepareDatabasePrefix()
  72. * @see DrupalWebTestCase::changeDatabasePrefix()
  73. * @see DrupalWebTestCase::prepareEnvironment()
  74. */
  75. protected function setUp() {
  76. // We are going to set a missing zlib requirement property for usage
  77. // during the performUpgrade() and tearDown() methods. Also set that the
  78. // tests failed.
  79. if (!$this->zlibInstalled) {
  80. parent::setUp();
  81. return;
  82. }
  83. global $user, $language, $conf;
  84. // Load the Update API.
  85. require_once DRUPAL_ROOT . '/includes/update.inc';
  86. // Reset flags.
  87. $this->upgradedSite = FALSE;
  88. $this->upgradeErrors = array();
  89. $this->loadedModules = module_list();
  90. // Create the database prefix for this test.
  91. $this->prepareDatabasePrefix();
  92. // Prepare the environment for running tests.
  93. $this->prepareEnvironment();
  94. if (!$this->setupEnvironment) {
  95. return FALSE;
  96. }
  97. // Reset all statics and variables to perform tests in a clean environment.
  98. $conf = array();
  99. drupal_static_reset();
  100. // Change the database prefix.
  101. // All static variables need to be reset before the database prefix is
  102. // changed, since DrupalCacheArray implementations attempt to
  103. // write back to persistent caches when they are destructed.
  104. $this->changeDatabasePrefix();
  105. if (!$this->setupDatabasePrefix) {
  106. return FALSE;
  107. }
  108. // Unregister the registry.
  109. // This is required to make sure that the database layer works properly.
  110. spl_autoload_unregister('drupal_autoload_class');
  111. spl_autoload_unregister('drupal_autoload_interface');
  112. // Load the database from the portable PHP dump.
  113. // The files may be gzipped.
  114. foreach ($this->databaseDumpFiles as $file) {
  115. if (substr($file, -3) == '.gz') {
  116. $file = "compress.zlib://$file";
  117. }
  118. require $file;
  119. }
  120. // Set path variables.
  121. $this->variable_set('file_public_path', $this->public_files_directory);
  122. $this->variable_set('file_private_path', $this->private_files_directory);
  123. $this->variable_set('file_temporary_path', $this->temp_files_directory);
  124. $this->pass('Finished loading the dump.');
  125. // Ensure that the session is not written to the new environment and replace
  126. // the global $user session with uid 1 from the new test site.
  127. drupal_save_session(FALSE);
  128. // Login as uid 1.
  129. $user = db_query('SELECT * FROM {users} WHERE uid = :uid', array(':uid' => 1))->fetchObject();
  130. // Generate and set a D6-compatible session cookie.
  131. $this->prepareD7Session();
  132. // Restore necessary variables.
  133. $this->variable_set('clean_url', $this->originalCleanUrl);
  134. $this->variable_set('site_mail', 'simpletest@example.com');
  135. drupal_set_time_limit($this->timeLimit);
  136. $this->setup = TRUE;
  137. }
  138. /**
  139. * Specialized variable_set() that works even if the child site is not upgraded.
  140. *
  141. * @param $name
  142. * The name of the variable to set.
  143. * @param $value
  144. * The value to set. This can be any PHP data type; these functions take care
  145. * of serialization as necessary.
  146. */
  147. protected function variable_set($name, $value) {
  148. db_delete('variable')
  149. ->condition('name', $name)
  150. ->execute();
  151. db_insert('variable')
  152. ->fields(array(
  153. 'name' => $name,
  154. 'value' => serialize($value),
  155. ))
  156. ->execute();
  157. try {
  158. cache_clear_all('variables', 'cache');
  159. cache_clear_all('variables', 'cache_bootstrap');
  160. }
  161. // Since cache_bootstrap won't exist in a Drupal 6 site, ignore the
  162. // exception if the above fails.
  163. catch (Exception $e) {}
  164. }
  165. /**
  166. * Specialized refreshVariables().
  167. */
  168. protected function refreshVariables() {
  169. // No operation if the child has not been upgraded yet.
  170. if (!$this->upgradedSite) {
  171. return parent::refreshVariables();
  172. }
  173. }
  174. /**
  175. * Perform the upgrade.
  176. *
  177. * @param $register_errors
  178. * Register the errors during the upgrade process as failures.
  179. * @return
  180. * TRUE if the upgrade succeeded, FALSE otherwise.
  181. */
  182. protected function performUpgrade($register_errors = TRUE) {
  183. if (!$this->zlibInstalled) {
  184. $this->fail(t('Missing zlib requirement for upgrade tests.'));
  185. return FALSE;
  186. }
  187. $update_url = $GLOBALS['base_url'] . '/update.php';
  188. // Load the first update screen.
  189. $this->drupalGet($update_url, array('external' => TRUE));
  190. if (!$this->assertResponse(200)) {
  191. return FALSE;
  192. }
  193. // Continue.
  194. $this->drupalPost(NULL, array(), t('Continue'));
  195. if (!$this->assertResponse(200)) {
  196. return FALSE;
  197. }
  198. // The test should pass if there are no pending updates.
  199. $content = $this->drupalGetContent();
  200. if (strpos($content, t('No pending updates.')) !== FALSE) {
  201. $this->pass(t('No pending updates and therefore no upgrade process to test.'));
  202. $this->pendingUpdates = FALSE;
  203. return TRUE;
  204. }
  205. // Go!
  206. $this->drupalPost(NULL, array(), t('Apply pending updates'));
  207. if (!$this->assertResponse(200)) {
  208. return FALSE;
  209. }
  210. // Check for errors during the update process.
  211. foreach ($this->xpath('//li[@class=:class]', array(':class' => 'failure')) as $element) {
  212. $message = strip_tags($element->asXML());
  213. $this->upgradeErrors[] = $message;
  214. if ($register_errors) {
  215. $this->fail($message);
  216. }
  217. }
  218. if (!empty($this->upgradeErrors)) {
  219. // Upgrade failed, the installation might be in an inconsistent state,
  220. // don't process.
  221. return FALSE;
  222. }
  223. // Check if there still are pending updates.
  224. $this->drupalGet($update_url, array('external' => TRUE));
  225. $this->drupalPost(NULL, array(), t('Continue'));
  226. if (!$this->assertText(t('No pending updates.'), 'No pending updates at the end of the update process.')) {
  227. return FALSE;
  228. }
  229. // Upgrade succeed, rebuild the environment so that we can call the API
  230. // of the child site directly from this request.
  231. $this->upgradedSite = TRUE;
  232. // Reload module list. For modules that are enabled in the test database,
  233. // but not on the test client, we need to load the code here.
  234. $new_modules = array_diff(module_list(TRUE), $this->loadedModules);
  235. foreach ($new_modules as $module) {
  236. drupal_load('module', $module);
  237. }
  238. // Reload hook implementations
  239. module_implements('', FALSE, TRUE);
  240. // Rebuild caches.
  241. drupal_static_reset();
  242. drupal_flush_all_caches();
  243. // Reload global $conf array and permissions.
  244. $this->refreshVariables();
  245. $this->checkPermissions(array(), TRUE);
  246. return TRUE;
  247. }
  248. /**
  249. * Force uninstall all modules from a test database, except those listed.
  250. *
  251. * @param $modules
  252. * The list of modules to keep installed. Required core modules will
  253. * always be kept.
  254. */
  255. protected function uninstallModulesExcept(array $modules) {
  256. $required_modules = array('block', 'dblog', 'filter', 'node', 'system', 'update', 'user');
  257. $modules = array_merge($required_modules, $modules);
  258. db_delete('system')
  259. ->condition('type', 'module')
  260. ->condition('name', $modules, 'NOT IN')
  261. ->execute();
  262. }
  263. }
  264. /**
  265. * Performs end-to-end point test of the release update path.
  266. */
  267. abstract class UpdatePathTestCase extends UpgradePathTestCase {
  268. /**
  269. * Overrides UpgradePathTestCase::prepareD7Session().
  270. */
  271. protected function prepareD7Session() {
  272. // Generate and set a D7-compatible session cookie.
  273. $this->curlInitialize();
  274. $sid = drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55));
  275. curl_setopt($this->curlHandle, CURLOPT_COOKIE, rawurlencode(session_name()) . '=' . rawurlencode($sid));
  276. // Force our way into the session of the child site.
  277. drupal_save_session(TRUE);
  278. _drupal_session_write($sid, '');
  279. drupal_save_session(FALSE);
  280. }
  281. }
  282. /**
  283. * Perform basic upgrade tests.
  284. *
  285. * Load a bare installation of Drupal 6 and run the upgrade process on it.
  286. *
  287. * The install only contains dblog (although it's optional, it's only so that
  288. * another hook_watchdog module can take its place, the site is not functional
  289. * without watchdog) and update.
  290. */
  291. class BasicUpgradePath extends UpgradePathTestCase {
  292. public static function getInfo() {
  293. return array(
  294. 'name' => 'Basic upgrade path',
  295. 'description' => 'Basic upgrade path tests.',
  296. 'group' => 'Upgrade path',
  297. );
  298. }
  299. public function setUp() {
  300. // Path to the database dump files.
  301. $this->databaseDumpFiles = array(
  302. drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.bare.database.php',
  303. );
  304. parent::setUp();
  305. }
  306. /**
  307. * Test a failed upgrade, and verify that the failure is reported.
  308. */
  309. public function testFailedUpgrade() {
  310. if ($this->skipUpgradeTest) {
  311. return;
  312. }
  313. // Destroy a table that the upgrade process needs.
  314. db_drop_table('access');
  315. // Assert that the upgrade fails.
  316. $this->assertFalse($this->performUpgrade(FALSE) && $this->pendingUpdates, 'A failed upgrade should return messages.');
  317. }
  318. /**
  319. * Test a successful upgrade.
  320. */
  321. public function testBasicUpgrade() {
  322. if ($this->skipUpgradeTest) {
  323. return;
  324. }
  325. $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
  326. // Hit the frontpage.
  327. $this->drupalGet('');
  328. $this->assertResponse(200);
  329. // Verify that we are still logged in.
  330. $this->drupalGet('user');
  331. $this->clickLink(t('Edit'));
  332. $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.');
  333. // Logout and verify that we can login back in with our initial password.
  334. $this->drupalLogout();
  335. $this->drupalLogin((object) array(
  336. 'uid' => 1,
  337. 'name' => 'admin',
  338. 'pass_raw' => 'admin',
  339. ));
  340. // The previous login should've triggered a password rehash, so login one
  341. // more time to make sure the new hash is readable.
  342. $this->drupalLogout();
  343. $this->drupalLogin((object) array(
  344. 'uid' => 1,
  345. 'name' => 'admin',
  346. 'pass_raw' => 'admin',
  347. ));
  348. // Test that the site name is correctly displayed.
  349. $this->assertText('Drupal 6', 'The site name is correctly displayed.');
  350. // Verify that the main admin sections are available.
  351. $this->drupalGet('admin');
  352. $this->assertText(t('Content'));
  353. $this->assertText(t('Appearance'));
  354. $this->assertText(t('People'));
  355. $this->assertText(t('Configuration'));
  356. $this->assertText(t('Reports'));
  357. $this->assertText(t('Structure'));
  358. $this->assertText(t('Modules'));
  359. // Confirm that no {menu_links} entry exists for user/autocomplete.
  360. $result = db_query('SELECT COUNT(*) FROM {menu_links} WHERE link_path = :user_autocomplete', array(':user_autocomplete' => 'user/autocomplete'))->fetchField();
  361. $this->assertFalse($result, 'No {menu_links} entry exists for user/autocomplete');
  362. // Test that the environment after the upgrade is in a consistent status.
  363. $update_d6 = variable_get('update_d6', FALSE);
  364. $this->assertFalse($update_d6, 'The D6 upgrade flag variable has been correctly disabled.');
  365. }
  366. }
  367. /**
  368. * Performs point release update tests on a bare database.
  369. *
  370. * Loads an installation of Drupal 7.0 and runs the update process on it.
  371. *
  372. * The install contains the standard profile (plus all optional) modules
  373. * without any content so that an update from any of the modules under this
  374. * profile installation can be wholly tested.
  375. */
  376. class BasicStandardUpdatePath extends UpdatePathTestCase {
  377. public static function getInfo() {
  378. return array(
  379. 'name' => 'Basic standard + all profile update path',
  380. 'description' => 'Basic update path tests for a standard profile install with all enabled modules.',
  381. 'group' => 'Upgrade path',
  382. );
  383. }
  384. public function setUp() {
  385. // Path to the database dump files.
  386. $this->databaseDumpFiles = array(
  387. drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz',
  388. );
  389. parent::setUp();
  390. }
  391. /**
  392. * Tests a successful point release update.
  393. */
  394. public function testBasicStandardUpdate() {
  395. $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
  396. // Hit the frontpage.
  397. $this->drupalGet('');
  398. $this->assertResponse(200);
  399. // Verify that we are still logged in.
  400. $this->drupalGet('user');
  401. $this->clickLink(t('Edit'));
  402. $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.');
  403. // Logout and verify that we can login back in with our initial password.
  404. $this->drupalLogout();
  405. $this->drupalLogin((object) array(
  406. 'uid' => 1,
  407. 'name' => 'admin',
  408. 'pass_raw' => 'admin',
  409. ));
  410. // The previous login should've triggered a password rehash, so login one
  411. // more time to make sure the new hash is readable.
  412. $this->drupalLogout();
  413. $this->drupalLogin((object) array(
  414. 'uid' => 1,
  415. 'name' => 'admin',
  416. 'pass_raw' => 'admin',
  417. ));
  418. // Test that the site name is correctly displayed.
  419. $this->assertText('Drupal', 'The site name is correctly displayed.');
  420. // Verify that the main admin sections are available.
  421. $this->drupalGet('admin');
  422. $this->assertText(t('Content'));
  423. $this->assertText(t('Appearance'));
  424. $this->assertText(t('People'));
  425. $this->assertText(t('Configuration'));
  426. $this->assertText(t('Reports'));
  427. $this->assertText(t('Structure'));
  428. $this->assertText(t('Modules'));
  429. // Confirm that no {menu_links} entry exists for user/autocomplete.
  430. $result = db_query('SELECT COUNT(*) FROM {menu_links} WHERE link_path = :user_autocomplete', array(':user_autocomplete' => 'user/autocomplete'))->fetchField();
  431. $this->assertFalse($result, 'No {menu_links} entry exists for user/autocomplete');
  432. }
  433. }
  434. /**
  435. * Performs point release update tests on a bare database.
  436. *
  437. * Loads an installation of Drupal 7.0 and runs the update process on it.
  438. *
  439. * The install contains the minimal profile modules (without any generated
  440. * content) so that an update from of a site under this profile may be tested.
  441. */
  442. class BasicMinimalUpdatePath extends UpdatePathTestCase {
  443. public static function getInfo() {
  444. return array(
  445. 'name' => 'Basic minimal profile update path',
  446. 'description' => 'Basic update path tests for a minimal profile install.',
  447. 'group' => 'Upgrade path',
  448. );
  449. }
  450. public function setUp() {
  451. // Path to the database dump files.
  452. $this->databaseDumpFiles = array(
  453. drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-7.bare.minimal.database.php.gz',
  454. );
  455. parent::setUp();
  456. }
  457. /**
  458. * Tests a successful point release update.
  459. */
  460. public function testBasicMinimalUpdate() {
  461. $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
  462. // Hit the frontpage.
  463. $this->drupalGet('');
  464. $this->assertResponse(200);
  465. // Verify that we are still logged in.
  466. $this->drupalGet('user');
  467. $this->clickLink(t('Edit'));
  468. $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.');
  469. // Logout and verify that we can login back in with our initial password.
  470. $this->drupalLogout();
  471. $this->drupalLogin((object) array(
  472. 'uid' => 1,
  473. 'name' => 'admin',
  474. 'pass_raw' => 'admin',
  475. ));
  476. // The previous login should've triggered a password rehash, so login one
  477. // more time to make sure the new hash is readable.
  478. $this->drupalLogout();
  479. $this->drupalLogin((object) array(
  480. 'uid' => 1,
  481. 'name' => 'admin',
  482. 'pass_raw' => 'admin',
  483. ));
  484. // Test that the site name is correctly displayed.
  485. $this->assertText('Drupal', 'The site name is correctly displayed.');
  486. // Verify that the main admin sections are available.
  487. $this->drupalGet('admin');
  488. $this->assertText(t('Content'));
  489. $this->assertText(t('Appearance'));
  490. $this->assertText(t('People'));
  491. $this->assertText(t('Configuration'));
  492. $this->assertText(t('Reports'));
  493. $this->assertText(t('Structure'));
  494. $this->assertText(t('Modules'));
  495. // Confirm that no {menu_links} entry exists for user/autocomplete.
  496. $result = db_query('SELECT COUNT(*) FROM {menu_links} WHERE link_path = :user_autocomplete', array(':user_autocomplete' => 'user/autocomplete'))->fetchField();
  497. $this->assertFalse($result, 'No {menu_links} entry exists for user/autocomplete');
  498. // Confirm that a date format that just differs in the case can be added.
  499. $admin_date_format = 'j M y';
  500. $edit = array('date_format' => $admin_date_format);
  501. $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
  502. // Add a new date format which just differs in the case.
  503. $admin_date_format_uppercase = 'j M Y';
  504. $edit = array('date_format' => $admin_date_format_uppercase);
  505. $this->drupalPost('admin/config/regional/date-time/formats/add', $edit, t('Add format'));
  506. $this->assertText(t('Custom date format added.'));
  507. // Verify that the unique key on {date_formats}.format still exists.
  508. try {
  509. // The PostgreSQL driver appends suffixes to keys/indexes according to
  510. // their types. A unique key is a key (not an index), so it has a _key
  511. // suffix. It is not possible to call db_index_exists() as this function
  512. // will check the index name with _idx suffix, so it will never succeed on
  513. // PostgreSQL. An attempt to create a new unique key when it exists should
  514. // fail and the thrown exception will confirm that the unique key exists.
  515. // MySQL and SQLite are not affected by this change, as they do not append
  516. // suffixes to keys/indexes names.
  517. db_add_unique_key('date_formats', 'formats', array('formats'));
  518. // This is executed if no exception has been thrown and the unique key
  519. // did not already exist.
  520. $this->fail('Unique key on {date_formats} does not exist');
  521. }
  522. catch (DatabaseSchemaObjectExistsException $e) {
  523. // Exception confirms that the unique key already existed.
  524. $this->pass('Unique key on {date_formats} exists');
  525. }
  526. }
  527. }
  528. /**
  529. * Performs point release update tests on a 'filled' database.
  530. *
  531. * Loads an installation of Drupal 7.0 and runs the update process on it.
  532. *
  533. * The install contains the standard profile (plus all optional) modules
  534. * with generated content so that an update from any of the modules under this
  535. * profile installation can be wholly tested.
  536. */
  537. class FilledStandardUpdatePath extends UpdatePathTestCase {
  538. public static function getInfo() {
  539. return array(
  540. 'name' => 'Basic standard + all profile update path, populated database',
  541. 'description' => 'Basic update path tests for a standard profile install with all enabled modules and a populated database.',
  542. 'group' => 'Upgrade path',
  543. );
  544. }
  545. public function setUp() {
  546. // Path to the database dump files.
  547. $this->databaseDumpFiles = array(
  548. drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-7.filled.standard_all.database.php.gz',
  549. );
  550. parent::setUp();
  551. }
  552. /**
  553. * Tests a successful point release update.
  554. */
  555. public function testFilledStandardUpdate() {
  556. $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
  557. // Hit the frontpage.
  558. $this->drupalGet('');
  559. $this->assertResponse(200);
  560. // Verify that we are still logged in.
  561. $this->drupalGet('user');
  562. $this->clickLink(t('Edit'));
  563. $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.');
  564. // Logout and verify that we can login back in with our initial password.
  565. $this->drupalLogout();
  566. $this->drupalLogin((object) array(
  567. 'uid' => 1,
  568. 'name' => 'admin',
  569. 'pass_raw' => 'admin',
  570. ));
  571. // The previous login should've triggered a password rehash, so login one
  572. // more time to make sure the new hash is readable.
  573. $this->drupalLogout();
  574. $this->drupalLogin((object) array(
  575. 'uid' => 1,
  576. 'name' => 'admin',
  577. 'pass_raw' => 'admin',
  578. ));
  579. // Test that the site name is correctly displayed.
  580. $this->assertText('Drupal', 'The site name is correctly displayed.');
  581. // Verify that the main admin sections are available.
  582. $this->drupalGet('admin');
  583. $this->assertText(t('Content'));
  584. $this->assertText(t('Appearance'));
  585. $this->assertText(t('People'));
  586. $this->assertText(t('Configuration'));
  587. $this->assertText(t('Reports'));
  588. $this->assertText(t('Structure'));
  589. $this->assertText(t('Modules'));
  590. // Confirm that no {menu_links} entry exists for user/autocomplete.
  591. $result = db_query('SELECT COUNT(*) FROM {menu_links} WHERE link_path = :user_autocomplete', array(':user_autocomplete' => 'user/autocomplete'))->fetchField();
  592. $this->assertFalse($result, 'No {menu_links} entry exists for user/autocomplete');
  593. }
  594. }
  595. /**
  596. * Performs point release update tests on a populated database.
  597. *
  598. * Loads an installation of Drupal 7.0 and runs the update process on it.
  599. *
  600. * The install contains the minimal profile modules (along with generated
  601. * content) so that an update from of a site under this profile may be tested.
  602. */
  603. class FilledMinimalUpdatePath extends UpdatePathTestCase {
  604. public static function getInfo() {
  605. return array(
  606. 'name' => 'Basic minimal profile update path, populated database',
  607. 'description' => 'Basic update path tests for a minimal profile install with a populated database.',
  608. 'group' => 'Upgrade path',
  609. );
  610. }
  611. public function setUp() {
  612. // Path to the database dump files.
  613. $this->databaseDumpFiles = array(
  614. drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-7.filled.minimal.database.php.gz',
  615. );
  616. parent::setUp();
  617. }
  618. /**
  619. * Tests a successful point release update.
  620. */
  621. public function testFilledStandardUpdate() {
  622. $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
  623. // Hit the frontpage.
  624. $this->drupalGet('');
  625. $this->assertResponse(200);
  626. // Verify that we are still logged in.
  627. $this->drupalGet('user');
  628. $this->clickLink(t('Edit'));
  629. $this->assertEqual($this->getUrl(), url('user/1/edit', array('absolute' => TRUE)), 'We are still logged in as admin at the end of the upgrade.');
  630. // Logout and verify that we can login back in with our initial password.
  631. $this->drupalLogout();
  632. $this->drupalLogin((object) array(
  633. 'uid' => 1,
  634. 'name' => 'admin',
  635. 'pass_raw' => 'admin',
  636. ));
  637. // The previous login should've triggered a password rehash, so login one
  638. // more time to make sure the new hash is readable.
  639. $this->drupalLogout();
  640. $this->drupalLogin((object) array(
  641. 'uid' => 1,
  642. 'name' => 'admin',
  643. 'pass_raw' => 'admin',
  644. ));
  645. // Test that the site name is correctly displayed.
  646. $this->assertText('Drupal', 'The site name is correctly displayed.');
  647. // Verify that the main admin sections are available.
  648. $this->drupalGet('admin');
  649. $this->assertText(t('Content'));
  650. $this->assertText(t('Appearance'));
  651. $this->assertText(t('People'));
  652. $this->assertText(t('Configuration'));
  653. $this->assertText(t('Reports'));
  654. $this->assertText(t('Structure'));
  655. $this->assertText(t('Modules'));
  656. // Confirm that no {menu_links} entry exists for user/autocomplete.
  657. $result = db_query('SELECT COUNT(*) FROM {menu_links} WHERE link_path = :user_autocomplete', array(':user_autocomplete' => 'user/autocomplete'))->fetchField();
  658. $this->assertFalse($result, 'No {menu_links} entry exists for user/autocomplete');
  659. }
  660. }