cms/drupal/modules/simpletest/tests/bootstrap.test
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 class BootstrapIPAddressTestCase extends DrupalWebTestCase {
       
     4 
       
     5   public static function getInfo() {
       
     6     return array(
       
     7       'name' => 'IP address and HTTP_HOST test',
       
     8       'description' => 'Get the IP address from the current visitor from the server variables, check hostname validation.',
       
     9       'group' => 'Bootstrap'
       
    10     );
       
    11   }
       
    12 
       
    13   function setUp() {
       
    14     $this->oldserver = $_SERVER;
       
    15 
       
    16     $this->remote_ip = '127.0.0.1';
       
    17     $this->proxy_ip = '127.0.0.2';
       
    18     $this->proxy2_ip = '127.0.0.3';
       
    19     $this->forwarded_ip = '127.0.0.4';
       
    20     $this->cluster_ip = '127.0.0.5';
       
    21     $this->untrusted_ip = '0.0.0.0';
       
    22 
       
    23     drupal_static_reset('ip_address');
       
    24 
       
    25     $_SERVER['REMOTE_ADDR'] = $this->remote_ip;
       
    26     unset($_SERVER['HTTP_X_FORWARDED_FOR']);
       
    27     unset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']);
       
    28 
       
    29     parent::setUp();
       
    30   }
       
    31 
       
    32   function tearDown() {
       
    33     $_SERVER = $this->oldserver;
       
    34     drupal_static_reset('ip_address');
       
    35     parent::tearDown();
       
    36   }
       
    37 
       
    38   /**
       
    39    * test IP Address and hostname
       
    40    */
       
    41   function testIPAddressHost() {
       
    42     // Test the normal IP address.
       
    43     $this->assertTrue(
       
    44       ip_address() == $this->remote_ip,
       
    45       'Got remote IP address.'
       
    46     );
       
    47 
       
    48     // Proxy forwarding on but no proxy addresses defined.
       
    49     variable_set('reverse_proxy', 1);
       
    50     $this->assertTrue(
       
    51       ip_address() == $this->remote_ip,
       
    52       'Proxy forwarding without trusted proxies got remote IP address.'
       
    53     );
       
    54 
       
    55     // Proxy forwarding on and proxy address not trusted.
       
    56     variable_set('reverse_proxy_addresses', array($this->proxy_ip, $this->proxy2_ip));
       
    57     drupal_static_reset('ip_address');
       
    58     $_SERVER['REMOTE_ADDR'] = $this->untrusted_ip;
       
    59     $this->assertTrue(
       
    60       ip_address() == $this->untrusted_ip,
       
    61       'Proxy forwarding with untrusted proxy got remote IP address.'
       
    62     );
       
    63 
       
    64     // Proxy forwarding on and proxy address trusted.
       
    65     $_SERVER['REMOTE_ADDR'] = $this->proxy_ip;
       
    66     $_SERVER['HTTP_X_FORWARDED_FOR'] = $this->forwarded_ip;
       
    67     drupal_static_reset('ip_address');
       
    68     $this->assertTrue(
       
    69       ip_address() == $this->forwarded_ip,
       
    70       'Proxy forwarding with trusted proxy got forwarded IP address.'
       
    71     );
       
    72 
       
    73     // Proxy forwarding on and proxy address trusted and visiting from proxy.
       
    74     $_SERVER['REMOTE_ADDR'] = $this->proxy_ip;
       
    75     $_SERVER['HTTP_X_FORWARDED_FOR'] = $this->proxy_ip;
       
    76     drupal_static_reset('ip_address');
       
    77     $this->assertTrue(
       
    78       ip_address() == $this->proxy_ip,
       
    79       'Visiting from trusted proxy got proxy IP address.'
       
    80     );
       
    81 
       
    82     // Multi-tier architecture with comma separated values in header.
       
    83     $_SERVER['REMOTE_ADDR'] = $this->proxy_ip;
       
    84     $_SERVER['HTTP_X_FORWARDED_FOR'] = implode(', ', array($this->untrusted_ip, $this->forwarded_ip, $this->proxy2_ip));
       
    85     drupal_static_reset('ip_address');
       
    86     $this->assertTrue(
       
    87       ip_address() == $this->forwarded_ip,
       
    88       'Proxy forwarding with trusted 2-tier proxy got forwarded IP address.'
       
    89     );
       
    90 
       
    91     // Custom client-IP header.
       
    92     variable_set('reverse_proxy_header', 'HTTP_X_CLUSTER_CLIENT_IP');
       
    93     $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'] = $this->cluster_ip;
       
    94     drupal_static_reset('ip_address');
       
    95     $this->assertTrue(
       
    96       ip_address() == $this->cluster_ip,
       
    97       'Cluster environment got cluster client IP.'
       
    98     );
       
    99 
       
   100     // Verifies that drupal_valid_http_host() prevents invalid characters.
       
   101     $this->assertFalse(drupal_valid_http_host('security/.drupal.org:80'), 'HTTP_HOST with / is invalid');
       
   102     $this->assertFalse(drupal_valid_http_host('security\\.drupal.org:80'), 'HTTP_HOST with \\ is invalid');
       
   103     $this->assertFalse(drupal_valid_http_host('security<.drupal.org:80'), 'HTTP_HOST with &lt; is invalid');
       
   104     $this->assertFalse(drupal_valid_http_host('security..drupal.org:80'), 'HTTP_HOST with .. is invalid');
       
   105     // Verifies that host names are shorter than 1000 characters.
       
   106     $this->assertFalse(drupal_valid_http_host(str_repeat('x', 1001)), 'HTTP_HOST with more than 1000 characters is invalid.');
       
   107     $this->assertFalse(drupal_valid_http_host(str_repeat('.', 101)), 'HTTP_HOST with more than 100 subdomains is invalid.');
       
   108     $this->assertFalse(drupal_valid_http_host(str_repeat(':', 101)), 'HTTP_HOST with more than 100 portseparators is invalid.');
       
   109 
       
   110     // IPv6 loopback address
       
   111     $this->assertTrue(drupal_valid_http_host('[::1]:80'), 'HTTP_HOST containing IPv6 loopback is valid');
       
   112   }
       
   113 }
       
   114 
       
   115 class BootstrapPageCacheTestCase extends DrupalWebTestCase {
       
   116 
       
   117   public static function getInfo() {
       
   118     return array(
       
   119       'name' => 'Page cache test',
       
   120       'description' => 'Enable the page cache and test it with various HTTP requests.',
       
   121       'group' => 'Bootstrap'
       
   122     );
       
   123   }
       
   124 
       
   125   function setUp() {
       
   126     parent::setUp('system_test');
       
   127   }
       
   128 
       
   129   /**
       
   130    * Test support for requests containing If-Modified-Since and If-None-Match headers.
       
   131    */
       
   132   function testConditionalRequests() {
       
   133     variable_set('cache', 1);
       
   134 
       
   135     // Fill the cache.
       
   136     $this->drupalGet('');
       
   137 
       
   138     $this->drupalHead('');
       
   139     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
       
   140     $etag = $this->drupalGetHeader('ETag');
       
   141     $last_modified = $this->drupalGetHeader('Last-Modified');
       
   142 
       
   143     $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
       
   144     $this->assertResponse(304, 'Conditional request returned 304 Not Modified.');
       
   145 
       
   146     $this->drupalGet('', array(), array('If-Modified-Since: ' . gmdate(DATE_RFC822, strtotime($last_modified)), 'If-None-Match: ' . $etag));
       
   147     $this->assertResponse(304, 'Conditional request with obsolete If-Modified-Since date returned 304 Not Modified.');
       
   148 
       
   149     $this->drupalGet('', array(), array('If-Modified-Since: ' . gmdate(DATE_RFC850, strtotime($last_modified)), 'If-None-Match: ' . $etag));
       
   150     $this->assertResponse(304, 'Conditional request with obsolete If-Modified-Since date returned 304 Not Modified.');
       
   151 
       
   152     $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified));
       
   153     $this->assertResponse(200, 'Conditional request without If-None-Match returned 200 OK.');
       
   154     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
       
   155 
       
   156     $this->drupalGet('', array(), array('If-Modified-Since: ' . gmdate(DATE_RFC7231, strtotime($last_modified) + 1), 'If-None-Match: ' . $etag));
       
   157     $this->assertResponse(200, 'Conditional request with new a If-Modified-Since date newer than Last-Modified returned 200 OK.');
       
   158     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
       
   159 
       
   160     $user = $this->drupalCreateUser();
       
   161     $this->drupalLogin($user);
       
   162     $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
       
   163     $this->assertResponse(200, 'Conditional request returned 200 OK for authenticated user.');
       
   164     $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Absence of Page was not cached.');
       
   165     $this->assertFalse($this->drupalGetHeader('ETag'), 'ETag HTTP headers are not present for logged in users.');
       
   166     $this->assertFalse($this->drupalGetHeader('Last-Modified'), 'Last-Modified HTTP headers are not present for logged in users.');
       
   167   }
       
   168 
       
   169   /**
       
   170    * Test cache headers.
       
   171    */
       
   172   function testPageCache() {
       
   173     variable_set('cache', 1);
       
   174 
       
   175     // Fill the cache.
       
   176     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
       
   177     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.');
       
   178     $this->assertEqual($this->drupalGetHeader('Vary'), 'Cookie,Accept-Encoding', 'Vary header was sent.');
       
   179     $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'public, max-age=0', 'Cache-Control header was sent.');
       
   180     $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.');
       
   181     $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.');
       
   182 
       
   183     // Check cache.
       
   184     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
       
   185     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
       
   186     $this->assertEqual($this->drupalGetHeader('Vary'), 'Cookie,Accept-Encoding', 'Vary: Cookie header was sent.');
       
   187     $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'public, max-age=0', 'Cache-Control header was sent.');
       
   188     $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.');
       
   189     $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.');
       
   190 
       
   191     // Check replacing default headers.
       
   192     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Expires', 'value' => 'Fri, 19 Nov 2008 05:00:00 GMT')));
       
   193     $this->assertEqual($this->drupalGetHeader('Expires'), 'Fri, 19 Nov 2008 05:00:00 GMT', 'Default header was replaced.');
       
   194     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Vary', 'value' => 'User-Agent')));
       
   195     $this->assertEqual($this->drupalGetHeader('Vary'), 'User-Agent,Accept-Encoding', 'Default header was replaced.');
       
   196 
       
   197     // Check that authenticated users bypass the cache.
       
   198     $user = $this->drupalCreateUser();
       
   199     $this->drupalLogin($user);
       
   200     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
       
   201     $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Caching was bypassed.');
       
   202     $this->assertTrue(strpos($this->drupalGetHeader('Vary'), 'Cookie') === FALSE, 'Vary: Cookie header was not sent.');
       
   203     $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'no-cache, must-revalidate', 'Cache-Control header was sent.');
       
   204     $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.');
       
   205     $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.');
       
   206 
       
   207   }
       
   208 
       
   209   /**
       
   210    * Test page compression.
       
   211    *
       
   212    * The test should pass even if zlib.output_compression is enabled in php.ini,
       
   213    * .htaccess or similar, or if compression is done outside PHP, e.g. by the
       
   214    * mod_deflate Apache module.
       
   215    */
       
   216   function testPageCompression() {
       
   217     variable_set('cache', 1);
       
   218 
       
   219     // Fill the cache and verify that output is compressed.
       
   220     $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
       
   221     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.');
       
   222     $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
       
   223     $this->assertRaw('</html>', 'Page was gzip compressed.');
       
   224 
       
   225     // Verify that cached output is compressed.
       
   226     $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
       
   227     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
       
   228     $this->assertEqual($this->drupalGetHeader('Content-Encoding'), 'gzip', 'A Content-Encoding header was sent.');
       
   229     $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
       
   230     $this->assertRaw('</html>', 'Page was gzip compressed.');
       
   231 
       
   232     // Verify that a client without compression support gets an uncompressed page.
       
   233     $this->drupalGet('');
       
   234     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
       
   235     $this->assertFalse($this->drupalGetHeader('Content-Encoding'), 'A Content-Encoding header was not sent.');
       
   236     $this->assertTitle(t('Welcome to @site-name | @site-name', array('@site-name' => variable_get('site_name', 'Drupal'))), 'Site title matches.');
       
   237     $this->assertRaw('</html>', 'Page was not compressed.');
       
   238 
       
   239     // Disable compression mode.
       
   240     variable_set('page_compression', FALSE);
       
   241 
       
   242     // Verify if cached page is still available for a client with compression support.
       
   243     $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
       
   244     $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
       
   245     $this->assertRaw('</html>', 'Page was delivered after compression mode is changed (compression support enabled).');
       
   246 
       
   247     // Verify if cached page is still available for a client without compression support.
       
   248     $this->drupalGet('');
       
   249     $this->assertRaw('</html>', 'Page was delivered after compression mode is changed (compression support disabled).');
       
   250   }
       
   251 }
       
   252 
       
   253 class BootstrapVariableTestCase extends DrupalWebTestCase {
       
   254 
       
   255   function setUp() {
       
   256     parent::setUp('system_test');
       
   257   }
       
   258 
       
   259   public static function getInfo() {
       
   260     return array(
       
   261       'name' => 'Variable test',
       
   262       'description' => 'Make sure the variable system functions correctly.',
       
   263       'group' => 'Bootstrap'
       
   264     );
       
   265   }
       
   266 
       
   267   /**
       
   268    * testVariable
       
   269    */
       
   270   function testVariable() {
       
   271     // Setting and retrieving values.
       
   272     $variable = $this->randomName();
       
   273     variable_set('simpletest_bootstrap_variable_test', $variable);
       
   274     $this->assertIdentical($variable, variable_get('simpletest_bootstrap_variable_test'), 'Setting and retrieving values');
       
   275 
       
   276     // Make sure the variable persists across multiple requests.
       
   277     $this->drupalGet('system-test/variable-get');
       
   278     $this->assertText($variable, 'Variable persists across multiple requests');
       
   279 
       
   280     // Deleting variables.
       
   281     $default_value = $this->randomName();
       
   282     variable_del('simpletest_bootstrap_variable_test');
       
   283     $variable = variable_get('simpletest_bootstrap_variable_test', $default_value);
       
   284     $this->assertIdentical($variable, $default_value, 'Deleting variables');
       
   285   }
       
   286 
       
   287   /**
       
   288    * Makes sure that the default variable parameter is passed through okay.
       
   289    */
       
   290   function testVariableDefaults() {
       
   291     // Tests passing nothing through to the default.
       
   292     $this->assertIdentical(NULL, variable_get('simpletest_bootstrap_variable_test'), 'Variables are correctly defaulting to NULL.');
       
   293 
       
   294     // Tests passing 5 to the default parameter.
       
   295     $this->assertIdentical(5, variable_get('simpletest_bootstrap_variable_test', 5), 'The default variable parameter is passed through correctly.');
       
   296   }
       
   297 
       
   298 }
       
   299 
       
   300 /**
       
   301  * Tests the auto-loading behavior of the code registry.
       
   302  */
       
   303 class BootstrapAutoloadTestCase extends DrupalWebTestCase {
       
   304 
       
   305   public static function getInfo() {
       
   306     return array(
       
   307       'name' => 'Code registry',
       
   308       'description' => 'Test that the code registry functions correctly.',
       
   309       'group' => 'Bootstrap',
       
   310     );
       
   311   }
       
   312 
       
   313   function setUp() {
       
   314     parent::setUp('drupal_autoload_test');
       
   315   }
       
   316 
       
   317   /**
       
   318    * Tests that autoloader name matching is not case sensitive.
       
   319    */
       
   320   function testAutoloadCase() {
       
   321     // Test interface autoloader.
       
   322     $this->assertTrue(drupal_autoload_interface('drupalautoloadtestinterface'), 'drupal_autoload_interface() recognizes <em>DrupalAutoloadTestInterface</em> in lower case.');
       
   323     // Test class autoloader.
       
   324     $this->assertTrue(drupal_autoload_class('drupalautoloadtestclass'), 'drupal_autoload_class() recognizes <em>DrupalAutoloadTestClass</em> in lower case.');
       
   325     // Test trait autoloader.
       
   326     if (version_compare(PHP_VERSION, '5.4') >= 0) {
       
   327       $this->assertTrue(drupal_autoload_trait('drupalautoloadtesttrait'), 'drupal_autoload_trait() recognizes <em>DrupalAutoloadTestTrait</em> in lower case.');
       
   328     }
       
   329   }
       
   330 
       
   331 }
       
   332 
       
   333 /**
       
   334  * Test hook_boot() and hook_exit().
       
   335  */
       
   336 class HookBootExitTestCase extends DrupalWebTestCase {
       
   337 
       
   338   public static function getInfo() {
       
   339     return array(
       
   340       'name' => 'Boot and exit hook invocation',
       
   341       'description' => 'Test that hook_boot() and hook_exit() are called correctly.',
       
   342       'group' => 'Bootstrap',
       
   343     );
       
   344   }
       
   345 
       
   346   function setUp() {
       
   347     parent::setUp('system_test', 'dblog');
       
   348   }
       
   349 
       
   350   /**
       
   351    * Test calling of hook_boot() and hook_exit().
       
   352    */
       
   353   function testHookBootExit() {
       
   354     // Test with cache disabled. Boot and exit should always fire.
       
   355     variable_set('cache', 0);
       
   356     $this->drupalGet('');
       
   357     $calls = 1;
       
   358     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot called with disabled cache.'));
       
   359     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_exit'))->fetchField(), $calls, t('hook_exit called with disabled cache.'));
       
   360 
       
   361     // Test with normal cache. Boot and exit should be called.
       
   362     variable_set('cache', 1);
       
   363     $this->drupalGet('');
       
   364     $calls++;
       
   365     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot called with normal cache.'));
       
   366     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_exit'))->fetchField(), $calls, t('hook_exit called with normal cache.'));
       
   367 
       
   368     // Boot and exit should not fire since the page is cached.
       
   369     variable_set('page_cache_invoke_hooks', FALSE);
       
   370     $this->assertTrue(cache_get(url('', array('absolute' => TRUE)), 'cache_page'), t('Page has been cached.'));
       
   371     $this->drupalGet('');
       
   372     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot not called with aggressive cache and a cached page.'));
       
   373     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_exit'))->fetchField(), $calls, t('hook_exit not called with aggressive cache and a cached page.'));
       
   374 
       
   375     // Test with page cache cleared, boot and exit should be called.
       
   376     $this->assertTrue(db_delete('cache_page')->execute(), t('Page cache cleared.'));
       
   377     $this->drupalGet('');
       
   378     $calls++;
       
   379     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot called with aggressive cache and no cached page.'));
       
   380     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_exit'))->fetchField(), $calls, t('hook_exit called with aggressive cache and no cached page.'));
       
   381   }
       
   382 }
       
   383 
       
   384 /**
       
   385  * Test drupal_get_filename()'s availability.
       
   386  */
       
   387 class BootstrapGetFilenameTestCase extends DrupalUnitTestCase {
       
   388 
       
   389   public static function getInfo() {
       
   390     return array(
       
   391       'name' => 'Get filename test (without the system table)',
       
   392       'description' => 'Test that drupal_get_filename() works correctly when the database is not available.',
       
   393       'group' => 'Bootstrap',
       
   394     );
       
   395   }
       
   396 
       
   397   /**
       
   398    * The last file-related error message triggered by the filename test.
       
   399    *
       
   400    * Used by BootstrapGetFilenameTestCase::testDrupalGetFilename().
       
   401    */
       
   402   protected $getFilenameTestTriggeredError;
       
   403 
       
   404   /**
       
   405    * Test that drupal_get_filename() works correctly when the file is not found in the database.
       
   406    */
       
   407   function testDrupalGetFilename() {
       
   408     // Reset the static cache so we can test the "db is not active" code of
       
   409     // drupal_get_filename().
       
   410     drupal_static_reset('drupal_get_filename');
       
   411 
       
   412     // Retrieving the location of a module.
       
   413     $this->assertIdentical(drupal_get_filename('module', 'php'), 'modules/php/php.module', t('Retrieve module location.'));
       
   414 
       
   415     // Retrieving the location of a theme.
       
   416     $this->assertIdentical(drupal_get_filename('theme', 'stark'), 'themes/stark/stark.info', t('Retrieve theme location.'));
       
   417 
       
   418     // Retrieving the location of a theme engine.
       
   419     $this->assertIdentical(drupal_get_filename('theme_engine', 'phptemplate'), 'themes/engines/phptemplate/phptemplate.engine', t('Retrieve theme engine location.'));
       
   420 
       
   421     // Retrieving the location of a profile. Profiles are a special case with
       
   422     // a fixed location and naming.
       
   423     $this->assertIdentical(drupal_get_filename('profile', 'standard'), 'profiles/standard/standard.profile', t('Retrieve install profile location.'));
       
   424 
       
   425     // When a file is not found in the database cache, drupal_get_filename()
       
   426     // searches several locations on the filesystem, including the DRUPAL_ROOT
       
   427     // directory. We use the '.script' extension below because this is a
       
   428     // non-existent filetype that will definitely not exist in the database.
       
   429     // Since there is already a scripts directory, drupal_get_filename() will
       
   430     // automatically check there for 'script' files, just as it does for (e.g.)
       
   431     // 'module' files in modules.
       
   432     $this->assertIdentical(drupal_get_filename('script', 'test'), 'scripts/test.script', t('Retrieve test script location.'));
       
   433 
       
   434     // When searching for a module that does not exist, drupal_get_filename()
       
   435     // should return NULL and trigger an appropriate error message.
       
   436     $this->getFilenameTestTriggeredError = NULL;
       
   437     set_error_handler(array($this, 'fileNotFoundErrorHandler'));
       
   438     $non_existing_module = $this->randomName();
       
   439     $this->assertNull(drupal_get_filename('module', $non_existing_module), 'Searching for a module that does not exist returns NULL.');
       
   440     $this->assertTrue(strpos($this->getFilenameTestTriggeredError, format_string('The following module is missing from the file system: %name', array('%name' => $non_existing_module))) === 0, 'Searching for an item that does not exist triggers the correct error.');
       
   441     restore_error_handler();
       
   442 
       
   443     // Check that the result is stored in the file system scan cache.
       
   444     $file_scans = _drupal_file_scan_cache();
       
   445     $this->assertIdentical($file_scans['module'][$non_existing_module], FALSE, 'Searching for a module that does not exist creates a record in the missing and moved files static variable.');
       
   446 
       
   447     // Performing the search again in the same request still should not find
       
   448     // the file, but the error message should not be repeated (therefore we do
       
   449     // not override the error handler here).
       
   450     $this->assertNull(drupal_get_filename('module', $non_existing_module), 'Searching for a module that does not exist returns NULL during the second search.');
       
   451   }
       
   452 
       
   453   /**
       
   454    * Skips handling of "file not found" errors.
       
   455    */
       
   456   public function fileNotFoundErrorHandler($error_level, $message, $filename, $line, $context) {
       
   457     // Skip error handling if this is a "file not found" error.
       
   458     if (strpos($message, 'is missing from the file system:') !== FALSE || strpos($message, 'has moved within the file system:') !== FALSE) {
       
   459       $this->getFilenameTestTriggeredError = $message;
       
   460       return;
       
   461     }
       
   462     _drupal_error_handler($error_level, $message, $filename, $line, $context);
       
   463   }
       
   464 }
       
   465 
       
   466 /**
       
   467  * Test drupal_get_filename() in the context of a full Drupal installation.
       
   468  */
       
   469 class BootstrapGetFilenameWebTestCase extends DrupalWebTestCase {
       
   470 
       
   471   public static function getInfo() {
       
   472     return array(
       
   473       'name' => 'Get filename test (full installation)',
       
   474       'description' => 'Test that drupal_get_filename() works correctly in the context of a full Drupal installation.',
       
   475       'group' => 'Bootstrap',
       
   476     );
       
   477   }
       
   478 
       
   479   function setUp() {
       
   480     parent::setUp('system_test');
       
   481   }
       
   482 
       
   483   /**
       
   484    * The last file-related error message triggered by the filename test.
       
   485    *
       
   486    * Used by BootstrapGetFilenameWebTestCase::testDrupalGetFilename().
       
   487    */
       
   488   protected $getFilenameTestTriggeredError;
       
   489 
       
   490   /**
       
   491    * Test that drupal_get_filename() works correctly with a full Drupal site.
       
   492    */
       
   493   function testDrupalGetFilename() {
       
   494     // Search for a module that exists in the file system and the {system}
       
   495     // table and make sure that it is found.
       
   496     $this->assertIdentical(drupal_get_filename('module', 'node'), 'modules/node/node.module', 'Module found at expected location.');
       
   497 
       
   498     // Search for a module that does not exist in either the file system or the
       
   499     // {system} table. Make sure that an appropriate error is triggered and
       
   500     // that the module winds up in the static and persistent cache.
       
   501     $this->getFilenameTestTriggeredError = NULL;
       
   502     set_error_handler(array($this, 'fileNotFoundErrorHandler'));
       
   503     $non_existing_module = $this->randomName();
       
   504     $this->assertNull(drupal_get_filename('module', $non_existing_module), 'Searching for a module that does not exist returns NULL.');
       
   505     $this->assertTrue(strpos($this->getFilenameTestTriggeredError, format_string('The following module is missing from the file system: %name', array('%name' => $non_existing_module))) === 0, 'Searching for a module that does not exist triggers the correct error.');
       
   506     restore_error_handler();
       
   507     $file_scans = _drupal_file_scan_cache();
       
   508     $this->assertIdentical($file_scans['module'][$non_existing_module], FALSE, 'Searching for a module that does not exist creates a record in the missing and moved files static variable.');
       
   509     drupal_file_scan_write_cache();
       
   510     $cache = cache_get('_drupal_file_scan_cache', 'cache_bootstrap');
       
   511     $this->assertIdentical($cache->data['module'][$non_existing_module], FALSE, 'Searching for a module that does not exist creates a record in the missing and moved files persistent cache.');
       
   512 
       
   513     // Simulate moving a module to a location that does not match the location
       
   514     // in the {system} table and perform similar tests as above.
       
   515     db_update('system')
       
   516       ->fields(array('filename' => 'modules/simpletest/tests/fake_location/module_test.module'))
       
   517       ->condition('name', 'module_test')
       
   518       ->condition('type', 'module')
       
   519       ->execute();
       
   520     $this->getFilenameTestTriggeredError = NULL;
       
   521     set_error_handler(array($this, 'fileNotFoundErrorHandler'));
       
   522     $this->assertIdentical(drupal_get_filename('module', 'module_test'), 'modules/simpletest/tests/module_test.module', 'Searching for a module that has moved finds the module at its new location.');
       
   523     $this->assertTrue(strpos($this->getFilenameTestTriggeredError, format_string('The following module has moved within the file system: %name', array('%name' => 'module_test'))) === 0, 'Searching for a module that has moved triggers the correct error.');
       
   524     restore_error_handler();
       
   525     $file_scans = _drupal_file_scan_cache();
       
   526     $this->assertIdentical($file_scans['module']['module_test'], 'modules/simpletest/tests/module_test.module', 'Searching for a module that has moved creates a record in the missing and moved files static variable.');
       
   527     drupal_file_scan_write_cache();
       
   528     $cache = cache_get('_drupal_file_scan_cache', 'cache_bootstrap');
       
   529     $this->assertIdentical($cache->data['module']['module_test'], 'modules/simpletest/tests/module_test.module', 'Searching for a module that has moved creates a record in the missing and moved files persistent cache.');
       
   530 
       
   531     // Simulate a module that exists in the {system} table but does not exist
       
   532     // in the file system and perform similar tests as above.
       
   533     $non_existing_module = $this->randomName();
       
   534     db_update('system')
       
   535       ->fields(array('name' => $non_existing_module))
       
   536       ->condition('name', 'module_test')
       
   537       ->condition('type', 'module')
       
   538       ->execute();
       
   539     $this->getFilenameTestTriggeredError = NULL;
       
   540     set_error_handler(array($this, 'fileNotFoundErrorHandler'));
       
   541     $this->assertNull(drupal_get_filename('module', $non_existing_module), 'Searching for a module that exists in the system table but not in the file system returns NULL.');
       
   542     $this->assertTrue(strpos($this->getFilenameTestTriggeredError, format_string('The following module is missing from the file system: %name', array('%name' => $non_existing_module))) === 0, 'Searching for a module that exists in the system table but not in the file system triggers the correct error.');
       
   543     restore_error_handler();
       
   544     $file_scans = _drupal_file_scan_cache();
       
   545     $this->assertIdentical($file_scans['module'][$non_existing_module], FALSE, 'Searching for a module that exists in the system table but not in the file system creates a record in the missing and moved files static variable.');
       
   546     drupal_file_scan_write_cache();
       
   547     $cache = cache_get('_drupal_file_scan_cache', 'cache_bootstrap');
       
   548     $this->assertIdentical($cache->data['module'][$non_existing_module], FALSE, 'Searching for a module that exists in the system table but not in the file system creates a record in the missing and moved files persistent cache.');
       
   549 
       
   550     // Simulate a module that exists in the file system but not in the {system}
       
   551     // table and perform similar tests as above.
       
   552     db_delete('system')
       
   553       ->condition('name', 'common_test')
       
   554       ->condition('type', 'module')
       
   555       ->execute();
       
   556     system_list_reset();
       
   557     $this->getFilenameTestTriggeredError = NULL;
       
   558     set_error_handler(array($this, 'fileNotFoundErrorHandler'));
       
   559     $this->assertIdentical(drupal_get_filename('module', 'common_test'), 'modules/simpletest/tests/common_test.module', 'Searching for a module that does not exist in the system table finds the module at its actual location.');
       
   560     $this->assertTrue(strpos($this->getFilenameTestTriggeredError, format_string('The following module has moved within the file system: %name', array('%name' => 'common_test'))) === 0, 'Searching for a module that does not exist in the system table triggers the correct error.');
       
   561     restore_error_handler();
       
   562     $file_scans = _drupal_file_scan_cache();
       
   563     $this->assertIdentical($file_scans['module']['common_test'], 'modules/simpletest/tests/common_test.module', 'Searching for a module that does not exist in the system table creates a record in the missing and moved files static variable.');
       
   564     drupal_file_scan_write_cache();
       
   565     $cache = cache_get('_drupal_file_scan_cache', 'cache_bootstrap');
       
   566     $this->assertIdentical($cache->data['module']['common_test'], 'modules/simpletest/tests/common_test.module', 'Searching for a module that does not exist in the system table creates a record in the missing and moved files persistent cache.');
       
   567   }
       
   568 
       
   569   /**
       
   570    * Skips handling of "file not found" errors.
       
   571    */
       
   572   public function fileNotFoundErrorHandler($error_level, $message, $filename, $line, $context) {
       
   573     // Skip error handling if this is a "file not found" error.
       
   574     if (strpos($message, 'is missing from the file system:') !== FALSE || strpos($message, 'has moved within the file system:') !== FALSE) {
       
   575       $this->getFilenameTestTriggeredError = $message;
       
   576       return;
       
   577     }
       
   578     _drupal_error_handler($error_level, $message, $filename, $line, $context);
       
   579   }
       
   580 
       
   581   /**
       
   582    * Test that watchdog messages about missing files are correctly recorded.
       
   583    */
       
   584   public function testWatchdog() {
       
   585     // Search for a module that does not exist in either the file system or the
       
   586     // {system} table. Make sure that an appropriate warning is recorded in the
       
   587     // logs.
       
   588     $non_existing_module = $this->randomName();
       
   589     $query_parameters = array(
       
   590       ':type' => 'php',
       
   591       ':severity' => WATCHDOG_WARNING,
       
   592     );
       
   593     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND severity = :severity', $query_parameters)->fetchField(), 0, 'No warning message appears in the logs before searching for a module that does not exist.');
       
   594     // Trigger the drupal_get_filename() call. This must be done via a request
       
   595     // to a separate URL since the watchdog() will happen in a shutdown
       
   596     // function, and so that SimpleTest can be told to ignore (and not fail as
       
   597     // a result of) the expected PHP warnings generated during this process.
       
   598     variable_set('system_test_drupal_get_filename_test_module_name', $non_existing_module);
       
   599     $this->drupalGet('system-test/drupal-get-filename');
       
   600     $message_variables = db_query('SELECT variables FROM {watchdog} WHERE type = :type AND severity = :severity', $query_parameters)->fetchCol();
       
   601     $this->assertEqual(count($message_variables), 1, 'A single warning message appears in the logs after searching for a module that does not exist.');
       
   602     $variables = reset($message_variables);
       
   603     $variables = unserialize($variables);
       
   604     $this->assertTrue(isset($variables['!message']) && strpos($variables['!message'], format_string('The following module is missing from the file system: %name', array('%name' => $non_existing_module))) !== FALSE, 'The warning message that appears in the logs after searching for a module that does not exist contains the expected text.');
       
   605   }
       
   606 
       
   607   /**
       
   608    * Test that drupal_get_filename() does not break recursive rebuilds.
       
   609    */
       
   610   public function testRecursiveRebuilds() {
       
   611     // Ensure that the drupal_get_filename() call due to a missing module does
       
   612     // not break the data returned by an attempted recursive rebuild. The code
       
   613     // path which is tested is as follows:
       
   614     // - Call drupal_get_schema().
       
   615     // - Within a hook_schema() implementation, trigger a drupal_get_filename()
       
   616     //   search for a nonexistent module.
       
   617     // - In the watchdog() call that results from that, trigger
       
   618     //   drupal_get_schema() again.
       
   619     // Without some kind of recursion protection, this could cause the second
       
   620     // drupal_get_schema() call to return incomplete results. This test ensures
       
   621     // that does not happen.
       
   622     $non_existing_module = $this->randomName();
       
   623     variable_set('system_test_drupal_get_filename_test_module_name', $non_existing_module);
       
   624     $this->drupalGet('system-test/drupal-get-filename-with-schema-rebuild');
       
   625     $original_drupal_get_schema_tables = variable_get('system_test_drupal_get_filename_with_schema_rebuild_original_tables');
       
   626     $final_drupal_get_schema_tables = variable_get('system_test_drupal_get_filename_with_schema_rebuild_final_tables');
       
   627     $this->assertTrue(!empty($original_drupal_get_schema_tables));
       
   628     $this->assertTrue(!empty($final_drupal_get_schema_tables));
       
   629     $this->assertEqual($original_drupal_get_schema_tables, $final_drupal_get_schema_tables);
       
   630   }
       
   631 }
       
   632 
       
   633 class BootstrapTimerTestCase extends DrupalUnitTestCase {
       
   634 
       
   635   public static function getInfo() {
       
   636     return array(
       
   637       'name' => 'Timer test',
       
   638       'description' => 'Test that timer_read() works both when a timer is running and when a timer is stopped.',
       
   639       'group' => 'Bootstrap',
       
   640     );
       
   641   }
       
   642 
       
   643   /**
       
   644    * Test timer_read() to ensure it properly accumulates time when the timer
       
   645    * started and stopped multiple times.
       
   646    * @return
       
   647    */
       
   648   function testTimer() {
       
   649     timer_start('test');
       
   650     sleep(1);
       
   651     $this->assertTrue(timer_read('test') >= 1000, 'Timer measured 1 second of sleeping while running.');
       
   652     sleep(1);
       
   653     timer_stop('test');
       
   654     $this->assertTrue(timer_read('test') >= 2000, 'Timer measured 2 seconds of sleeping after being stopped.');
       
   655     timer_start('test');
       
   656     sleep(1);
       
   657     $this->assertTrue(timer_read('test') >= 3000, 'Timer measured 3 seconds of sleeping after being restarted.');
       
   658     sleep(1);
       
   659     $timer = timer_stop('test');
       
   660     $this->assertTrue(timer_read('test') >= 4000, 'Timer measured 4 seconds of sleeping after being stopped for a second time.');
       
   661     $this->assertEqual($timer['count'], 2, 'Timer counted 2 instances of being started.');
       
   662   }
       
   663 }
       
   664 
       
   665 /**
       
   666  * Test that resetting static variables works.
       
   667  */
       
   668 class BootstrapResettableStaticTestCase extends DrupalUnitTestCase {
       
   669 
       
   670   public static function getInfo() {
       
   671     return array(
       
   672       'name' => 'Resettable static variables test',
       
   673       'description' => 'Test that drupal_static() and drupal_static_reset() work.',
       
   674       'group' => 'Bootstrap',
       
   675     );
       
   676   }
       
   677 
       
   678   /**
       
   679    * Test that a variable reference returned by drupal_static() gets reset when
       
   680    * drupal_static_reset() is called.
       
   681    */
       
   682   function testDrupalStatic() {
       
   683     $name = __CLASS__ . '_' . __METHOD__;
       
   684     $var = &drupal_static($name, 'foo');
       
   685     $this->assertEqual($var, 'foo', 'Variable returned by drupal_static() was set to its default.');
       
   686 
       
   687     // Call the specific reset and the global reset each twice to ensure that
       
   688     // multiple resets can be issued without odd side effects.
       
   689     $var = 'bar';
       
   690     drupal_static_reset($name);
       
   691     $this->assertEqual($var, 'foo', 'Variable was reset after first invocation of name-specific reset.');
       
   692     $var = 'bar';
       
   693     drupal_static_reset($name);
       
   694     $this->assertEqual($var, 'foo', 'Variable was reset after second invocation of name-specific reset.');
       
   695     $var = 'bar';
       
   696     drupal_static_reset();
       
   697     $this->assertEqual($var, 'foo', 'Variable was reset after first invocation of global reset.');
       
   698     $var = 'bar';
       
   699     drupal_static_reset();
       
   700     $this->assertEqual($var, 'foo', 'Variable was reset after second invocation of global reset.');
       
   701   }
       
   702 }
       
   703 
       
   704 /**
       
   705  * Test miscellaneous functions in bootstrap.inc.
       
   706  */
       
   707 class BootstrapMiscTestCase extends DrupalUnitTestCase {
       
   708 
       
   709   public static function getInfo() {
       
   710     return array(
       
   711       'name' => 'Miscellaneous bootstrap unit tests',
       
   712       'description' => 'Test miscellaneous functions in bootstrap.inc.',
       
   713       'group' => 'Bootstrap',
       
   714     );
       
   715   }
       
   716 
       
   717   /**
       
   718    * Test miscellaneous functions in bootstrap.inc.
       
   719    */
       
   720   function testMisc() {
       
   721     // Test drupal_array_merge_deep().
       
   722     $link_options_1 = array('fragment' => 'x', 'attributes' => array('title' => 'X', 'class' => array('a', 'b')), 'language' => 'en');
       
   723     $link_options_2 = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('c', 'd')), 'html' => TRUE);
       
   724     $expected = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('a', 'b', 'c', 'd')), 'language' => 'en', 'html' => TRUE);
       
   725     $this->assertIdentical(drupal_array_merge_deep($link_options_1, $link_options_2), $expected, 'drupal_array_merge_deep() returned a properly merged array.');
       
   726   }
       
   727 
       
   728   /**
       
   729    * Tests that the drupal_check_memory_limit() function works as expected.
       
   730    */
       
   731   function testCheckMemoryLimit() {
       
   732     $memory_limit = ini_get('memory_limit');
       
   733     // Test that a very reasonable amount of memory is available.
       
   734     $this->assertTrue(drupal_check_memory_limit('30MB'), '30MB of memory tested available.');
       
   735 
       
   736     // Get the available memory and multiply it by two to make it unreasonably
       
   737     // high.
       
   738     $twice_avail_memory = ($memory_limit * 2) . 'MB';
       
   739 
       
   740     // The function should always return true if the memory limit is set to -1.
       
   741     $this->assertTrue(drupal_check_memory_limit($twice_avail_memory, -1), 'drupal_check_memory_limit() returns TRUE when a limit of -1 (none) is supplied');
       
   742 
       
   743     // Test that even though we have 30MB of memory available - the function
       
   744     // returns FALSE when given an upper limit for how much memory can be used.
       
   745     $this->assertFalse(drupal_check_memory_limit('30MB', '16MB'), 'drupal_check_memory_limit() returns FALSE with a 16MB upper limit on a 30MB requirement.');
       
   746 
       
   747     // Test that an equal amount of memory to the amount requested returns TRUE.
       
   748     $this->assertTrue(drupal_check_memory_limit('30MB', '30MB'), 'drupal_check_memory_limit() returns TRUE when requesting 30MB on a 30MB requirement.');
       
   749   }
       
   750 }
       
   751 
       
   752 /**
       
   753  * Tests for overriding server variables via the API.
       
   754  */
       
   755 class BootstrapOverrideServerVariablesTestCase extends DrupalUnitTestCase {
       
   756   public static function getInfo() {
       
   757     return array(
       
   758       'name' => 'Overriding server variables',
       
   759       'description' => 'Test that drupal_override_server_variables() works correctly.',
       
   760       'group' => 'Bootstrap',
       
   761     );
       
   762   }
       
   763 
       
   764   /**
       
   765    * Test providing a direct URL to to drupal_override_server_variables().
       
   766    */
       
   767   function testDrupalOverrideServerVariablesProvidedURL() {
       
   768     $tests = array(
       
   769       'http://example.com' => array(
       
   770         'HTTP_HOST' => 'example.com',
       
   771         'SCRIPT_NAME' => isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : NULL,
       
   772       ),
       
   773       'http://example.com/index.php' => array(
       
   774         'HTTP_HOST' => 'example.com',
       
   775         'SCRIPT_NAME' => '/index.php',
       
   776       ),
       
   777       'http://example.com/subdirectory/index.php' => array(
       
   778         'HTTP_HOST' => 'example.com',
       
   779         'SCRIPT_NAME' => '/subdirectory/index.php',
       
   780       ),
       
   781     );
       
   782     foreach ($tests as $url => $expected_server_values) {
       
   783       // Remember the original value of $_SERVER, since the function call below
       
   784       // will modify it.
       
   785       $original_server = $_SERVER;
       
   786       // Call drupal_override_server_variables() and ensure that all expected
       
   787       // $_SERVER variables were modified correctly.
       
   788       drupal_override_server_variables(array('url' => $url));
       
   789       foreach ($expected_server_values as $key => $value) {
       
   790         $this->assertIdentical($_SERVER[$key], $value);
       
   791       }
       
   792       // Restore the original value of $_SERVER.
       
   793       $_SERVER = $original_server;
       
   794     }
       
   795   }
       
   796 }
       
   797 
       
   798 /**
       
   799  * Tests for $_GET['destination'] and $_REQUEST['destination'] validation.
       
   800  */
       
   801 class BootstrapDestinationTestCase extends DrupalWebTestCase {
       
   802 
       
   803   public static function getInfo() {
       
   804     return array(
       
   805       'name' => 'URL destination validation',
       
   806       'description' => 'Test that $_GET[\'destination\'] and $_REQUEST[\'destination\'] cannot contain external URLs.',
       
   807       'group' => 'Bootstrap',
       
   808     );
       
   809   }
       
   810 
       
   811   function setUp() {
       
   812     parent::setUp('system_test');
       
   813   }
       
   814 
       
   815   /**
       
   816    * Tests that $_GET/$_REQUEST['destination'] only contain internal URLs.
       
   817    *
       
   818    * @see _drupal_bootstrap_variables()
       
   819    * @see system_test_get_destination()
       
   820    * @see system_test_request_destination()
       
   821    */
       
   822   public function testDestination() {
       
   823     $test_cases = array(
       
   824       array(
       
   825         'input' => 'node',
       
   826         'output' => 'node',
       
   827         'message' => "Standard internal example node path is present in the 'destination' parameter.",
       
   828       ),
       
   829       array(
       
   830         'input' => '/example.com',
       
   831         'output' => '/example.com',
       
   832         'message' => 'Internal path with one leading slash is allowed.',
       
   833       ),
       
   834       array(
       
   835         'input' => '//example.com/test',
       
   836         'output' => '',
       
   837         'message' => 'External URL without scheme is not allowed.',
       
   838       ),
       
   839       array(
       
   840         'input' => 'example:test',
       
   841         'output' => 'example:test',
       
   842         'message' => 'Internal URL using a colon is allowed.',
       
   843       ),
       
   844       array(
       
   845         'input' => 'http://example.com',
       
   846         'output' => '',
       
   847         'message' => 'External URL is not allowed.',
       
   848       ),
       
   849       array(
       
   850         'input' => 'javascript:alert(0)',
       
   851         'output' => 'javascript:alert(0)',
       
   852         'message' => 'Javascript URL is allowed because it is treated as an internal URL.',
       
   853       ),
       
   854     );
       
   855     foreach ($test_cases as $test_case) {
       
   856       // Test $_GET['destination'].
       
   857       $this->drupalGet('system-test/get-destination', array('query' => array('destination' => $test_case['input'])));
       
   858       $this->assertIdentical($test_case['output'], $this->drupalGetContent(), $test_case['message']);
       
   859       // Test $_REQUEST['destination']. There's no form to submit to, so
       
   860       // drupalPost() won't work here; this just tests a direct $_POST request
       
   861       // instead.
       
   862       $curl_parameters = array(
       
   863         CURLOPT_URL => $this->getAbsoluteUrl('system-test/request-destination'),
       
   864         CURLOPT_POST => TRUE,
       
   865         CURLOPT_POSTFIELDS => 'destination=' . urlencode($test_case['input']),
       
   866         CURLOPT_HTTPHEADER => array(),
       
   867       );
       
   868       $post_output = $this->curlExec($curl_parameters);
       
   869       $this->assertIdentical($test_case['output'], $post_output, $test_case['message']);
       
   870     }
       
   871 
       
   872     // Make sure that 404 pages do not populate $_GET['destination'] with
       
   873     // external URLs.
       
   874     variable_set('site_404', 'system-test/get-destination');
       
   875     $this->drupalGet('http://example.com', array('external' => FALSE));
       
   876     $this->assertIdentical('', $this->drupalGetContent(), 'External URL is not allowed on 404 pages.');
       
   877   }
       
   878 }