bootstrap.test 21.8 KB
Newer Older
1 2 3 4
<?php

class BootstrapIPAddressTestCase extends DrupalWebTestCase {

5
  public static function getInfo() {
6
    return array(
7 8 9
      'name' => 'IP address and HTTP_HOST test',
      'description' => 'Get the IP address from the current visitor from the server variables, check hostname validation.',
      'group' => 'Bootstrap'
10 11 12 13 14 15 16 17
    );
  }

  function setUp() {
    $this->oldserver = $_SERVER;

    $this->remote_ip = '127.0.0.1';
    $this->proxy_ip = '127.0.0.2';
18 19 20
    $this->proxy2_ip = '127.0.0.3';
    $this->forwarded_ip = '127.0.0.4';
    $this->cluster_ip = '127.0.0.5';
21
    $this->untrusted_ip = '0.0.0.0';
22

23 24
    drupal_static_reset('ip_address');

25 26 27
    $_SERVER['REMOTE_ADDR'] = $this->remote_ip;
    unset($_SERVER['HTTP_X_FORWARDED_FOR']);
    unset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']);
28

29 30
    parent::setUp();
  }
31

32 33
  function tearDown() {
    $_SERVER = $this->oldserver;
34
    drupal_static_reset('ip_address');
35 36 37 38
    parent::tearDown();
  }

  /**
39
   * test IP Address and hostname
40
   */
41
  function testIPAddressHost() {
42 43
    // Test the normal IP address.
    $this->assertTrue(
44 45 46
      ip_address() == $this->remote_ip,
      t('Got remote IP address.')
    );
47

48 49 50
    // Proxy forwarding on but no proxy addresses defined.
    variable_set('reverse_proxy', 1);
    $this->assertTrue(
51 52 53
      ip_address() == $this->remote_ip,
      t('Proxy forwarding without trusted proxies got remote IP address.')
    );
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 59
    $_SERVER['REMOTE_ADDR'] = $this->untrusted_ip;
    $this->assertTrue(
60 61 62
      ip_address() == $this->untrusted_ip,
      t('Proxy forwarding with untrusted proxy got remote IP address.')
    );
63 64 65 66

    // Proxy forwarding on and proxy address trusted.
    $_SERVER['REMOTE_ADDR'] = $this->proxy_ip;
    $_SERVER['HTTP_X_FORWARDED_FOR'] = $this->forwarded_ip;
67
    drupal_static_reset('ip_address');
68
    $this->assertTrue(
69 70 71
      ip_address() == $this->forwarded_ip,
      t('Proxy forwarding with trusted proxy got forwarded IP address.')
    );
72 73 74 75 76 77

    // Multi-tier architecture with comma separated values in header.
    $_SERVER['REMOTE_ADDR'] = $this->proxy_ip;
    $_SERVER['HTTP_X_FORWARDED_FOR'] = implode(', ', array($this->untrusted_ip, $this->forwarded_ip, $this->proxy2_ip));
    drupal_static_reset('ip_address');
    $this->assertTrue(
78 79 80
      ip_address() == $this->forwarded_ip,
      t('Proxy forwarding with trusted 2-tier proxy got forwarded IP address.')
    );
81

82 83
    // Custom client-IP header.
    variable_set('reverse_proxy_header', 'HTTP_X_CLUSTER_CLIENT_IP');
84
    $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'] = $this->cluster_ip;
85
    drupal_static_reset('ip_address');
86
    $this->assertTrue(
87 88 89
      ip_address() == $this->cluster_ip,
      t('Cluster environment got cluster client IP.')
    );
90 91

    // Verifies that drupal_valid_http_host() prevents invalid characters.
92 93 94 95
    $this->assertFalse(drupal_valid_http_host('security/.drupal.org:80'), t('HTTP_HOST with / is invalid'));
    $this->assertFalse(drupal_valid_http_host('security\\.drupal.org:80'), t('HTTP_HOST with \\ is invalid'));
    $this->assertFalse(drupal_valid_http_host('security<.drupal.org:80'), t('HTTP_HOST with &lt; is invalid'));
    $this->assertFalse(drupal_valid_http_host('security..drupal.org:80'), t('HTTP_HOST with .. is invalid'));
96
    // IPv6 loopback address
97
    $this->assertTrue(drupal_valid_http_host('[::1]:80'), t('HTTP_HOST containing IPv6 loopback is valid'));
98 99
  }
}
100 101 102

class BootstrapPageCacheTestCase extends DrupalWebTestCase {

103
  public static function getInfo() {
104
    return array(
105
      'name' => 'Page cache test',
106
      'description' => 'Enable the page cache and test it with various HTTP requests.',
107
      'group' => 'Bootstrap'
108 109 110
    );
  }

111 112 113 114
  function setUp() {
    parent::setUp('system_test');
  }

115
  /**
116
   * Test support for requests containing If-Modified-Since and If-None-Match headers.
117
   */
118
  function testConditionalRequests() {
119
    variable_set('cache', 1);
120

121
    // Fill the cache.
122 123 124
    $this->drupalGet('');

    $this->drupalHead('');
125
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', t('Page was cached.'));
126 127 128 129
    $etag = $this->drupalGetHeader('ETag');
    $last_modified = $this->drupalGetHeader('Last-Modified');

    $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
130
    $this->assertResponse(304, t('Conditional request returned 304 Not Modified.'));
131 132

    $this->drupalGet('', array(), array('If-Modified-Since: ' . gmdate(DATE_RFC822, strtotime($last_modified)), 'If-None-Match: ' . $etag));
133
    $this->assertResponse(304, t('Conditional request with obsolete If-Modified-Since date returned 304 Not Modified.'));
134 135

    $this->drupalGet('', array(), array('If-Modified-Since: ' . gmdate(DATE_RFC850, strtotime($last_modified)), 'If-None-Match: ' . $etag));
136
    $this->assertResponse(304, t('Conditional request with obsolete If-Modified-Since date returned 304 Not Modified.'));
137 138

    $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified));
139 140
    $this->assertResponse(200, t('Conditional request without If-None-Match returned 200 OK.'));
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', t('Page was cached.'));
141 142

    $this->drupalGet('', array(), array('If-Modified-Since: ' . gmdate(DATE_RFC1123, strtotime($last_modified) + 1), 'If-None-Match: ' . $etag));
143 144
    $this->assertResponse(200, t('Conditional request with new a If-Modified-Since date newer than Last-Modified returned 200 OK.'));
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', t('Page was cached.'));
145

146 147 148
    $user = $this->drupalCreateUser();
    $this->drupalLogin($user);
    $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
149 150
    $this->assertResponse(200, t('Conditional request returned 200 OK for authenticated user.'));
    $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), t('Absense of Page was not cached.'));
151 152
  }

153 154 155 156
  /**
   * Test cache headers.
   */
  function testPageCache() {
157
    variable_set('cache', 1);
158 159 160

    // Fill the cache.
    $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
161 162 163 164 165
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', t('Page was not cached.'));
    $this->assertEqual($this->drupalGetHeader('Vary'), 'Cookie,Accept-Encoding', t('Vary header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'public, max-age=0', t('Cache-Control header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', t('Expires header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', t('Custom header was sent.'));
166 167 168

    // Check cache.
    $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
169 170 171 172 173
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', t('Page was cached.'));
    $this->assertEqual($this->drupalGetHeader('Vary'), 'Cookie,Accept-Encoding', t('Vary: Cookie header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'public, max-age=0', t('Cache-Control header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', t('Expires header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', t('Custom header was sent.'));
174 175 176

    // Check replacing default headers.
    $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Expires', 'value' => 'Fri, 19 Nov 2008 05:00:00 GMT')));
177
    $this->assertEqual($this->drupalGetHeader('Expires'), 'Fri, 19 Nov 2008 05:00:00 GMT', t('Default header was replaced.'));
178
    $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Vary', 'value' => 'User-Agent')));
179
    $this->assertEqual($this->drupalGetHeader('Vary'), 'User-Agent,Accept-Encoding', t('Default header was replaced.'));
180 181 182 183 184

    // Check that authenticated users bypass the cache.
    $user = $this->drupalCreateUser();
    $this->drupalLogin($user);
    $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
185 186 187 188 189
    $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), t('Caching was bypassed.'));
    $this->assertTrue(strpos($this->drupalGetHeader('Vary'), 'Cookie') === FALSE, t('Vary: Cookie header was not sent.'));
    $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'no-cache, must-revalidate, post-check=0, pre-check=0', t('Cache-Control header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', t('Expires header was sent.'));
    $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', t('Custom header was sent.'));
190 191

  }
192 193 194

  /**
   * Test page compression.
195
   *
196 197 198 199 200
   * The test should pass even if zlib.output_compression is enabled in php.ini,
   * .htaccess or similar, or if compression is done outside PHP, e.g. by the
   * mod_deflate Apache module.
   */
  function testPageCompression() {
201
    variable_set('cache', 1);
202 203 204

    // Fill the cache and verify that output is compressed.
    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
205
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', t('Page was not cached.'));
206
    $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
207
    $this->assertRaw('</html>', t('Page was gzip compressed.'));
208 209 210

    // Verify that cached output is compressed.
    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
211 212
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', t('Page was cached.'));
    $this->assertEqual($this->drupalGetHeader('Content-Encoding'), 'gzip', t('A Content-Encoding header was sent.'));
213
    $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
214
    $this->assertRaw('</html>', t('Page was gzip compressed.'));
215 216 217

    // Verify that a client without compression support gets an uncompressed page.
    $this->drupalGet('');
218 219 220 221
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', t('Page was cached.'));
    $this->assertFalse($this->drupalGetHeader('Content-Encoding'), t('A Content-Encoding header was not sent.'));
    $this->assertTitle(t('Welcome to @site-name | @site-name', array('@site-name' => variable_get('site_name', 'Drupal'))), t('Site title matches.'));
    $this->assertRaw('</html>', t('Page was not compressed.'));
222
  }
223
}
224 225

class BootstrapVariableTestCase extends DrupalWebTestCase {
226

227 228 229 230
  function setUp() {
    parent::setUp('system_test');
  }

231
  public static function getInfo() {
232
    return array(
233 234 235
      'name' => 'Variable test',
      'description' => 'Make sure the variable system functions correctly.',
      'group' => 'Bootstrap'
236 237 238 239 240 241 242 243 244 245
    );
  }

  /**
   * testVariable
   */
  function testVariable() {
    // Setting and retrieving values.
    $variable = $this->randomName();
    variable_set('simpletest_bootstrap_variable_test', $variable);
246
    $this->assertIdentical($variable, variable_get('simpletest_bootstrap_variable_test'), t('Setting and retrieving values'));
247 248 249

    // Make sure the variable persists across multiple requests.
    $this->drupalGet('system-test/variable-get');
250
    $this->assertText($variable, t('Variable persists across multiple requests'));
251

252 253 254 255
    // Deleting variables.
    $default_value = $this->randomName();
    variable_del('simpletest_bootstrap_variable_test');
    $variable = variable_get('simpletest_bootstrap_variable_test', $default_value);
256
    $this->assertIdentical($variable, $default_value, t('Deleting variables'));
257 258
  }

259 260 261 262 263
  /**
   * Makes sure that the default variable parameter is passed through okay.
   */
  function testVariableDefaults() {
    // Tests passing nothing through to the default.
264
    $this->assertIdentical(NULL, variable_get('simpletest_bootstrap_variable_test'), t('Variables are correctly defaulting to NULL.'));
265 266

    // Tests passing 5 to the default parameter.
267
    $this->assertIdentical(5, variable_get('simpletest_bootstrap_variable_test', 5), t('The default variable parameter is passed through correctly.'));
268 269
  }

270
}
271 272

/**
273
 * Test hook_boot() and hook_exit().
274 275 276
 */
class HookBootExitTestCase extends DrupalWebTestCase {

277
  public static function getInfo() {
278
    return array(
279 280 281
      'name' => 'Boot and exit hook invocation',
      'description' => 'Test that hook_boot() and hook_exit() are called correctly.',
      'group' => 'Bootstrap',
282 283 284 285 286 287 288 289 290 291 292
    );
  }

  function setUp() {
    parent::setUp('system_test', 'dblog');
  }

  /**
   * Test calling of hook_boot() and hook_exit().
   */
  function testHookBootExit() {
293
    // Test with cache disabled. Boot and exit should always fire.
294
    variable_set('cache', 0);
295
    $this->drupalGet('');
296
    $calls = 1;
297 298
    $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.'));
    $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.'));
299 300

    // Test with normal cache. Boot and exit should be called.
301
    variable_set('cache', 1);
302 303
    $this->drupalGet('');
    $calls++;
304 305
    $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.'));
    $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.'));
306

307 308
    // Boot and exit should not fire since the page is cached.
    variable_set('page_cache_invoke_hooks', FALSE);
309
    $this->assertTrue(cache('page')->get(url('', array('absolute' => TRUE))), t('Page has been cached.'));
310
    $this->drupalGet('');
311 312
    $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.'));
    $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.'));
313

314
    // Test with page cache cleared, boot and exit should be called.
315
    $this->assertTrue(db_delete('cache_page')->execute(), t('Page cache cleared.'));
316 317
    $this->drupalGet('');
    $calls++;
318 319
    $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.'));
    $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.'));
320 321 322
  }
}

323 324 325 326 327 328 329
/**
 * Test drupal_get_filename()'s availability.
 */
class BootstrapGetFilenameTestCase extends DrupalUnitTestCase {

  public static function getInfo() {
    return array(
330 331 332
      'name' => 'Get filename test',
      'description' => 'Test that drupal_get_filename() works correctly when the file is not found in the database.',
      'group' => 'Bootstrap',
333 334 335 336 337 338 339 340 341 342 343 344
    );
  }

  /**
   * Test that drupal_get_filename() works correctly when the file is not found in the database.
   */
  function testDrupalGetFilename() {
    // Reset the static cache so we can test the "db is not active" code of
    // drupal_get_filename().
    drupal_static_reset('drupal_get_filename');

    // Retrieving the location of a module.
345
    $this->assertIdentical(drupal_get_filename('module', 'php'), 'modules/php/php.module', t('Retrieve module location.'));
346 347

    // Retrieving the location of a theme.
348
    $this->assertIdentical(drupal_get_filename('theme', 'stark'), 'themes/stark/stark.info', t('Retrieve theme location.'));
349 350

    // Retrieving the location of a theme engine.
351
    $this->assertIdentical(drupal_get_filename('theme_engine', 'phptemplate'), 'themes/engines/phptemplate/phptemplate.engine', t('Retrieve theme engine location.'));
352 353

    // Retrieving a file that is definitely not stored in the database.
354
    $this->assertIdentical(drupal_get_filename('profile', 'standard'), 'profiles/standard/standard.profile', t('Retrieve install profile location.'));
355 356
  }
}
357 358 359 360 361 362 363 364 365 366 367 368 369 370

class BootstrapTimerTestCase extends DrupalUnitTestCase {

  public static function getInfo() {
    return array(
      'name' => 'Timer test',
      'description' => 'Test that timer_read() works both when a timer is running and when a timer is stopped.',
      'group' => 'Bootstrap',
    );
  }

  /**
   * Test timer_read() to ensure it properly accumulates time when the timer
   * started and stopped multiple times.
371
   * @return
372 373 374 375
   */
  function testTimer() {
    timer_start('test');
    sleep(1);
376
    $this->assertTrue(timer_read('test') >= 1000, t('Timer measured 1 second of sleeping while running.'));
377 378
    sleep(1);
    timer_stop('test');
379
    $this->assertTrue(timer_read('test') >= 2000, t('Timer measured 2 seconds of sleeping after being stopped.'));
380 381
    timer_start('test');
    sleep(1);
382
    $this->assertTrue(timer_read('test') >= 3000, t('Timer measured 3 seconds of sleeping after being restarted.'));
383 384
    sleep(1);
    $timer = timer_stop('test');
385 386
    $this->assertTrue(timer_read('test') >= 4000, t('Timer measured 4 seconds of sleeping after being stopped for a second time.'));
    $this->assertEqual($timer['count'], 2, t('Timer counted 2 instances of being started.'));
387 388
  }
}
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404

/**
 * Test that resetting static variables works.
 */
class BootstrapResettableStaticTestCase extends DrupalUnitTestCase {

  public static function getInfo() {
    return array(
      'name' => 'Resettable static variables test',
      'description' => 'Test that drupal_static() and drupal_static_reset() work.',
      'group' => 'Bootstrap',
    );
  }

  /**
   * Test that a variable reference returned by drupal_static() gets reset when
405
   * drupal_static_reset() is called.
406 407 408 409
   */
  function testDrupalStatic() {
    $name = __CLASS__ . '_' . __METHOD__;
    $var = &drupal_static($name, 'foo');
410
    $this->assertEqual($var, 'foo', t('Variable returned by drupal_static() was set to its default.'));
411 412 413 414 415

    // Call the specific reset and the global reset each twice to ensure that
    // multiple resets can be issued without odd side effects.
    $var = 'bar';
    drupal_static_reset($name);
416
    $this->assertEqual($var, 'foo', t('Variable was reset after first invocation of name-specific reset.'));
417 418
    $var = 'bar';
    drupal_static_reset($name);
419
    $this->assertEqual($var, 'foo', t('Variable was reset after second invocation of name-specific reset.'));
420 421
    $var = 'bar';
    drupal_static_reset();
422
    $this->assertEqual($var, 'foo', t('Variable was reset after first invocation of global reset.'));
423 424
    $var = 'bar';
    drupal_static_reset();
425
    $this->assertEqual($var, 'foo', t('Variable was reset after second invocation of global reset.'));
426 427
  }
}
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452

/**
 * Test miscellaneous functions in bootstrap.inc.
 */
class BootstrapMiscTestCase extends DrupalUnitTestCase {

  public static function getInfo() {
    return array(
      'name' => 'Miscellaneous bootstrap unit tests',
      'description' => 'Test miscellaneous functions in bootstrap.inc.',
      'group' => 'Bootstrap',
    );
  }

  /**
   * Test miscellaneous functions in bootstrap.inc.
   */
  function testMisc() {
    // Test drupal_array_merge_deep().
    $link_options_1 = array('fragment' => 'x', 'attributes' => array('title' => 'X', 'class' => array('a', 'b')), 'language' => 'en');
    $link_options_2 = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('c', 'd')), 'html' => TRUE);
    $expected = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('a', 'b', 'c', 'd')), 'language' => 'en', 'html' => TRUE);
    $this->assertIdentical(drupal_array_merge_deep($link_options_1, $link_options_2), $expected, t('drupal_array_merge_deep() returned a properly merged array.'));
  }
}
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499

/**
 * Tests for overriding server variables via the API.
 */
class BootstrapOverrideServerVariablesTestCase extends DrupalUnitTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Overriding server variables',
      'description' => 'Test that drupal_override_server_variables() works correctly.',
      'group' => 'Bootstrap',
    );
  }

  /**
   * Test providing a direct URL to to drupal_override_server_variables().
   */
  function testDrupalOverrideServerVariablesProvidedURL() {
    $tests = array(
      'http://example.com' => array(
        'HTTP_HOST' => 'example.com',
        'SCRIPT_NAME' => isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : NULL,
      ),
      'http://example.com/index.php' => array(
        'HTTP_HOST' => 'example.com',
        'SCRIPT_NAME' => '/index.php',
      ),
      'http://example.com/subdirectory/index.php' => array(
        'HTTP_HOST' => 'example.com',
        'SCRIPT_NAME' => '/subdirectory/index.php',
      ),
    );
    foreach ($tests as $url => $expected_server_values) {
      // Remember the original value of $_SERVER, since the function call below
      // will modify it.
      $original_server = $_SERVER;
      // Call drupal_override_server_variables() and ensure that all expected
      // $_SERVER variables were modified correctly.
      drupal_override_server_variables(array('url' => $url));
      foreach ($expected_server_values as $key => $value) {
        $this->assertIdentical($_SERVER[$key], $value);
      }
      // Restore the original value of $_SERVER.
      $_SERVER = $original_server;
    }
  }
}