Projet

Général

Profil

Paste
Télécharger (28,9 ko) Statistiques
| Branche: | Révision:

root / drupal7 / modules / simpletest / tests / bootstrap.test @ 30d5b9c5

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

    
82
    // Custom client-IP header.
83
    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
      ip_address() == $this->cluster_ip,
88
      'Cluster environment got cluster client IP.'
89
    );
90

    
91
    // Verifies that drupal_valid_http_host() prevents invalid characters.
92
    $this->assertFalse(drupal_valid_http_host('security/.drupal.org:80'), 'HTTP_HOST with / is invalid');
93
    $this->assertFalse(drupal_valid_http_host('security\\.drupal.org:80'), 'HTTP_HOST with \\ is invalid');
94
    $this->assertFalse(drupal_valid_http_host('security<.drupal.org:80'), 'HTTP_HOST with &lt; is invalid');
95
    $this->assertFalse(drupal_valid_http_host('security..drupal.org:80'), 'HTTP_HOST with .. is invalid');
96
    // Verifies that host names are shorter than 1000 characters.
97
    $this->assertFalse(drupal_valid_http_host(str_repeat('x', 1001)), 'HTTP_HOST with more than 1000 characters is invalid.');
98
    $this->assertFalse(drupal_valid_http_host(str_repeat('.', 101)), 'HTTP_HOST with more than 100 subdomains is invalid.');
99
    $this->assertFalse(drupal_valid_http_host(str_repeat(':', 101)), 'HTTP_HOST with more than 100 portseparators is invalid.');
100

    
101
    // IPv6 loopback address
102
    $this->assertTrue(drupal_valid_http_host('[::1]:80'), 'HTTP_HOST containing IPv6 loopback is valid');
103
  }
104
}
105

    
106
class BootstrapPageCacheTestCase extends DrupalWebTestCase {
107

    
108
  public static function getInfo() {
109
    return array(
110
      'name' => 'Page cache test',
111
      'description' => 'Enable the page cache and test it with various HTTP requests.',
112
      'group' => 'Bootstrap'
113
    );
114
  }
115

    
116
  function setUp() {
117
    parent::setUp('system_test');
118
  }
119

    
120
  /**
121
   * Test support for requests containing If-Modified-Since and If-None-Match headers.
122
   */
123
  function testConditionalRequests() {
124
    variable_set('cache', 1);
125

    
126
    // Fill the cache.
127
    $this->drupalGet('');
128

    
129
    $this->drupalHead('');
130
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
131
    $etag = $this->drupalGetHeader('ETag');
132
    $last_modified = $this->drupalGetHeader('Last-Modified');
133

    
134
    $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
135
    $this->assertResponse(304, 'Conditional request returned 304 Not Modified.');
136

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

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

    
143
    $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified));
144
    $this->assertResponse(200, 'Conditional request without If-None-Match returned 200 OK.');
145
    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
146

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

    
151
    $user = $this->drupalCreateUser();
152
    $this->drupalLogin($user);
153
    $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
154
    $this->assertResponse(200, 'Conditional request returned 200 OK for authenticated user.');
155
    $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Absence of Page was not cached.');
156
    $this->assertFalse($this->drupalGetHeader('ETag'), 'ETag HTTP headers are not present for logged in users.');
157
    $this->assertFalse($this->drupalGetHeader('Last-Modified'), 'Last-Modified HTTP headers are not present for logged in users.');
158
  }
159

    
160
  /**
161
   * Test cache headers.
162
   */
163
  function testPageCache() {
164
    variable_set('cache', 1);
165

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

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

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

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

    
198
  }
199

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

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

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

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

    
230
    // Disable compression mode.
231
    variable_set('page_compression', FALSE);
232

    
233
    // Verify if cached page is still available for a client with compression support.
234
    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
235
    $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
236
    $this->assertRaw('</html>', 'Page was delivered after compression mode is changed (compression support enabled).');
237

    
238
    // Verify if cached page is still available for a client without compression support.
239
    $this->drupalGet('');
240
    $this->assertRaw('</html>', 'Page was delivered after compression mode is changed (compression support disabled).');
241
  }
242
}
243

    
244
class BootstrapVariableTestCase extends DrupalWebTestCase {
245

    
246
  function setUp() {
247
    parent::setUp('system_test');
248
  }
249

    
250
  public static function getInfo() {
251
    return array(
252
      'name' => 'Variable test',
253
      'description' => 'Make sure the variable system functions correctly.',
254
      'group' => 'Bootstrap'
255
    );
256
  }
257

    
258
  /**
259
   * testVariable
260
   */
261
  function testVariable() {
262
    // Setting and retrieving values.
263
    $variable = $this->randomName();
264
    variable_set('simpletest_bootstrap_variable_test', $variable);
265
    $this->assertIdentical($variable, variable_get('simpletest_bootstrap_variable_test'), 'Setting and retrieving values');
266

    
267
    // Make sure the variable persists across multiple requests.
268
    $this->drupalGet('system-test/variable-get');
269
    $this->assertText($variable, 'Variable persists across multiple requests');
270

    
271
    // Deleting variables.
272
    $default_value = $this->randomName();
273
    variable_del('simpletest_bootstrap_variable_test');
274
    $variable = variable_get('simpletest_bootstrap_variable_test', $default_value);
275
    $this->assertIdentical($variable, $default_value, 'Deleting variables');
276
  }
277

    
278
  /**
279
   * Makes sure that the default variable parameter is passed through okay.
280
   */
281
  function testVariableDefaults() {
282
    // Tests passing nothing through to the default.
283
    $this->assertIdentical(NULL, variable_get('simpletest_bootstrap_variable_test'), 'Variables are correctly defaulting to NULL.');
284

    
285
    // Tests passing 5 to the default parameter.
286
    $this->assertIdentical(5, variable_get('simpletest_bootstrap_variable_test', 5), 'The default variable parameter is passed through correctly.');
287
  }
288

    
289
}
290

    
291
/**
292
 * Tests the auto-loading behavior of the code registry.
293
 */
294
class BootstrapAutoloadTestCase extends DrupalWebTestCase {
295

    
296
  public static function getInfo() {
297
    return array(
298
      'name' => 'Code registry',
299
      'description' => 'Test that the code registry functions correctly.',
300
      'group' => 'Bootstrap',
301
    );
302
  }
303

    
304
  function setUp() {
305
    parent::setUp('drupal_autoload_test');
306
  }
307

    
308
  /**
309
   * Tests that autoloader name matching is not case sensitive.
310
   */
311
  function testAutoloadCase() {
312
    // Test interface autoloader.
313
    $this->assertTrue(drupal_autoload_interface('drupalautoloadtestinterface'), 'drupal_autoload_interface() recognizes <em>DrupalAutoloadTestInterface</em> in lower case.');
314
    // Test class autoloader.
315
    $this->assertTrue(drupal_autoload_class('drupalautoloadtestclass'), 'drupal_autoload_class() recognizes <em>DrupalAutoloadTestClass</em> in lower case.');
316
    // Test trait autoloader.
317
    if (version_compare(PHP_VERSION, '5.4') >= 0) {
318
      $this->assertTrue(drupal_autoload_trait('drupalautoloadtesttrait'), 'drupal_autoload_trait() recognizes <em>DrupalAutoloadTestTrait</em> in lower case.');
319
    }
320
  }
321

    
322
}
323

    
324
/**
325
 * Test hook_boot() and hook_exit().
326
 */
327
class HookBootExitTestCase extends DrupalWebTestCase {
328

    
329
  public static function getInfo() {
330
    return array(
331
      'name' => 'Boot and exit hook invocation',
332
      'description' => 'Test that hook_boot() and hook_exit() are called correctly.',
333
      'group' => 'Bootstrap',
334
    );
335
  }
336

    
337
  function setUp() {
338
    parent::setUp('system_test', 'dblog');
339
  }
340

    
341
  /**
342
   * Test calling of hook_boot() and hook_exit().
343
   */
344
  function testHookBootExit() {
345
    // Test with cache disabled. Boot and exit should always fire.
346
    variable_set('cache', 0);
347
    $this->drupalGet('');
348
    $calls = 1;
349
    $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.'));
350
    $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.'));
351

    
352
    // Test with normal cache. Boot and exit should be called.
353
    variable_set('cache', 1);
354
    $this->drupalGet('');
355
    $calls++;
356
    $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.'));
357
    $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.'));
358

    
359
    // Boot and exit should not fire since the page is cached.
360
    variable_set('page_cache_invoke_hooks', FALSE);
361
    $this->assertTrue(cache_get(url('', array('absolute' => TRUE)), 'cache_page'), t('Page has been cached.'));
362
    $this->drupalGet('');
363
    $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.'));
364
    $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.'));
365

    
366
    // Test with page cache cleared, boot and exit should be called.
367
    $this->assertTrue(db_delete('cache_page')->execute(), t('Page cache cleared.'));
368
    $this->drupalGet('');
369
    $calls++;
370
    $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.'));
371
    $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.'));
372
  }
373
}
374

    
375
/**
376
 * Test drupal_get_filename()'s availability.
377
 */
378
class BootstrapGetFilenameTestCase extends DrupalUnitTestCase {
379

    
380
  public static function getInfo() {
381
    return array(
382
      'name' => 'Get filename test',
383
      'description' => 'Test that drupal_get_filename() works correctly when the file is not found in the database.',
384
      'group' => 'Bootstrap',
385
    );
386
  }
387

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

    
396
    // Retrieving the location of a module.
397
    $this->assertIdentical(drupal_get_filename('module', 'php'), 'modules/php/php.module', t('Retrieve module location.'));
398

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

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

    
405
    // Retrieving the location of a profile. Profiles are a special case with
406
    // a fixed location and naming.
407
    $this->assertIdentical(drupal_get_filename('profile', 'standard'), 'profiles/standard/standard.profile', t('Retrieve install profile location.'));
408

    
409
    // When a file is not found in the database cache, drupal_get_filename()
410
    // searches several locations on the filesystem, including the DRUPAL_ROOT
411
    // directory. We use the '.script' extension below because this is a
412
    // non-existent filetype that will definitely not exist in the database.
413
    // Since there is already a scripts directory, drupal_get_filename() will
414
    // automatically check there for 'script' files, just as it does for (e.g.)
415
    // 'module' files in modules.
416
    $this->assertIdentical(drupal_get_filename('script', 'test'), 'scripts/test.script', t('Retrieve test script location.'));
417
  }
418
}
419

    
420
class BootstrapTimerTestCase extends DrupalUnitTestCase {
421

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

    
430
  /**
431
   * Test timer_read() to ensure it properly accumulates time when the timer
432
   * started and stopped multiple times.
433
   * @return
434
   */
435
  function testTimer() {
436
    timer_start('test');
437
    sleep(1);
438
    $this->assertTrue(timer_read('test') >= 1000, 'Timer measured 1 second of sleeping while running.');
439
    sleep(1);
440
    timer_stop('test');
441
    $this->assertTrue(timer_read('test') >= 2000, 'Timer measured 2 seconds of sleeping after being stopped.');
442
    timer_start('test');
443
    sleep(1);
444
    $this->assertTrue(timer_read('test') >= 3000, 'Timer measured 3 seconds of sleeping after being restarted.');
445
    sleep(1);
446
    $timer = timer_stop('test');
447
    $this->assertTrue(timer_read('test') >= 4000, 'Timer measured 4 seconds of sleeping after being stopped for a second time.');
448
    $this->assertEqual($timer['count'], 2, 'Timer counted 2 instances of being started.');
449
  }
450
}
451

    
452
/**
453
 * Test that resetting static variables works.
454
 */
455
class BootstrapResettableStaticTestCase extends DrupalUnitTestCase {
456

    
457
  public static function getInfo() {
458
    return array(
459
      'name' => 'Resettable static variables test',
460
      'description' => 'Test that drupal_static() and drupal_static_reset() work.',
461
      'group' => 'Bootstrap',
462
    );
463
  }
464

    
465
  /**
466
   * Test that a variable reference returned by drupal_static() gets reset when
467
   * drupal_static_reset() is called.
468
   */
469
  function testDrupalStatic() {
470
    $name = __CLASS__ . '_' . __METHOD__;
471
    $var = &drupal_static($name, 'foo');
472
    $this->assertEqual($var, 'foo', 'Variable returned by drupal_static() was set to its default.');
473

    
474
    // Call the specific reset and the global reset each twice to ensure that
475
    // multiple resets can be issued without odd side effects.
476
    $var = 'bar';
477
    drupal_static_reset($name);
478
    $this->assertEqual($var, 'foo', 'Variable was reset after first invocation of name-specific reset.');
479
    $var = 'bar';
480
    drupal_static_reset($name);
481
    $this->assertEqual($var, 'foo', 'Variable was reset after second invocation of name-specific reset.');
482
    $var = 'bar';
483
    drupal_static_reset();
484
    $this->assertEqual($var, 'foo', 'Variable was reset after first invocation of global reset.');
485
    $var = 'bar';
486
    drupal_static_reset();
487
    $this->assertEqual($var, 'foo', 'Variable was reset after second invocation of global reset.');
488
  }
489
}
490

    
491
/**
492
 * Test miscellaneous functions in bootstrap.inc.
493
 */
494
class BootstrapMiscTestCase extends DrupalUnitTestCase {
495

    
496
  public static function getInfo() {
497
    return array(
498
      'name' => 'Miscellaneous bootstrap unit tests',
499
      'description' => 'Test miscellaneous functions in bootstrap.inc.',
500
      'group' => 'Bootstrap',
501
    );
502
  }
503

    
504
  /**
505
   * Test miscellaneous functions in bootstrap.inc.
506
   */
507
  function testMisc() {
508
    // Test drupal_array_merge_deep().
509
    $link_options_1 = array('fragment' => 'x', 'attributes' => array('title' => 'X', 'class' => array('a', 'b')), 'language' => 'en');
510
    $link_options_2 = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('c', 'd')), 'html' => TRUE);
511
    $expected = array('fragment' => 'y', 'attributes' => array('title' => 'Y', 'class' => array('a', 'b', 'c', 'd')), 'language' => 'en', 'html' => TRUE);
512
    $this->assertIdentical(drupal_array_merge_deep($link_options_1, $link_options_2), $expected, 'drupal_array_merge_deep() returned a properly merged array.');
513
  }
514

    
515
  /**
516
   * Tests that the drupal_check_memory_limit() function works as expected.
517
   */
518
  function testCheckMemoryLimit() {
519
    $memory_limit = ini_get('memory_limit');
520
    // Test that a very reasonable amount of memory is available.
521
    $this->assertTrue(drupal_check_memory_limit('30MB'), '30MB of memory tested available.');
522

    
523
    // Get the available memory and multiply it by two to make it unreasonably
524
    // high.
525
    $twice_avail_memory = ($memory_limit * 2) . 'MB';
526

    
527
    // The function should always return true if the memory limit is set to -1.
528
    $this->assertTrue(drupal_check_memory_limit($twice_avail_memory, -1), 'drupal_check_memory_limit() returns TRUE when a limit of -1 (none) is supplied');
529

    
530
    // Test that even though we have 30MB of memory available - the function
531
    // returns FALSE when given an upper limit for how much memory can be used.
532
    $this->assertFalse(drupal_check_memory_limit('30MB', '16MB'), 'drupal_check_memory_limit() returns FALSE with a 16MB upper limit on a 30MB requirement.');
533

    
534
    // Test that an equal amount of memory to the amount requested returns TRUE.
535
    $this->assertTrue(drupal_check_memory_limit('30MB', '30MB'), 'drupal_check_memory_limit() returns TRUE when requesting 30MB on a 30MB requirement.');
536
  }
537
}
538

    
539
/**
540
 * Tests for overriding server variables via the API.
541
 */
542
class BootstrapOverrideServerVariablesTestCase extends DrupalUnitTestCase {
543
  public static function getInfo() {
544
    return array(
545
      'name' => 'Overriding server variables',
546
      'description' => 'Test that drupal_override_server_variables() works correctly.',
547
      'group' => 'Bootstrap',
548
    );
549
  }
550

    
551
  /**
552
   * Test providing a direct URL to to drupal_override_server_variables().
553
   */
554
  function testDrupalOverrideServerVariablesProvidedURL() {
555
    $tests = array(
556
      'http://example.com' => array(
557
        'HTTP_HOST' => 'example.com',
558
        'SCRIPT_NAME' => isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : NULL,
559
      ),
560
      'http://example.com/index.php' => array(
561
        'HTTP_HOST' => 'example.com',
562
        'SCRIPT_NAME' => '/index.php',
563
      ),
564
      'http://example.com/subdirectory/index.php' => array(
565
        'HTTP_HOST' => 'example.com',
566
        'SCRIPT_NAME' => '/subdirectory/index.php',
567
      ),
568
    );
569
    foreach ($tests as $url => $expected_server_values) {
570
      // Remember the original value of $_SERVER, since the function call below
571
      // will modify it.
572
      $original_server = $_SERVER;
573
      // Call drupal_override_server_variables() and ensure that all expected
574
      // $_SERVER variables were modified correctly.
575
      drupal_override_server_variables(array('url' => $url));
576
      foreach ($expected_server_values as $key => $value) {
577
        $this->assertIdentical($_SERVER[$key], $value);
578
      }
579
      // Restore the original value of $_SERVER.
580
      $_SERVER = $original_server;
581
    }
582
  }
583
}
584

    
585
/**
586
 * Tests for $_GET['destination'] and $_REQUEST['destination'] validation.
587
 */
588
class BootstrapDestinationTestCase extends DrupalWebTestCase {
589

    
590
  public static function getInfo() {
591
    return array(
592
      'name' => 'URL destination validation',
593
      'description' => 'Test that $_GET[\'destination\'] and $_REQUEST[\'destination\'] cannot contain external URLs.',
594
      'group' => 'Bootstrap',
595
    );
596
  }
597

    
598
  function setUp() {
599
    parent::setUp('system_test');
600
  }
601

    
602
  /**
603
   * Tests that $_GET/$_REQUEST['destination'] only contain internal URLs.
604
   *
605
   * @see _drupal_bootstrap_variables()
606
   * @see system_test_get_destination()
607
   * @see system_test_request_destination()
608
   */
609
  public function testDestination() {
610
    $test_cases = array(
611
      array(
612
        'input' => 'node',
613
        'output' => 'node',
614
        'message' => "Standard internal example node path is present in the 'destination' parameter.",
615
      ),
616
      array(
617
        'input' => '/example.com',
618
        'output' => '/example.com',
619
        'message' => 'Internal path with one leading slash is allowed.',
620
      ),
621
      array(
622
        'input' => '//example.com/test',
623
        'output' => '',
624
        'message' => 'External URL without scheme is not allowed.',
625
      ),
626
      array(
627
        'input' => 'example:test',
628
        'output' => 'example:test',
629
        'message' => 'Internal URL using a colon is allowed.',
630
      ),
631
      array(
632
        'input' => 'http://example.com',
633
        'output' => '',
634
        'message' => 'External URL is not allowed.',
635
      ),
636
      array(
637
        'input' => 'javascript:alert(0)',
638
        'output' => 'javascript:alert(0)',
639
        'message' => 'Javascript URL is allowed because it is treated as an internal URL.',
640
      ),
641
    );
642
    foreach ($test_cases as $test_case) {
643
      // Test $_GET['destination'].
644
      $this->drupalGet('system-test/get-destination', array('query' => array('destination' => $test_case['input'])));
645
      $this->assertIdentical($test_case['output'], $this->drupalGetContent(), $test_case['message']);
646
      // Test $_REQUEST['destination']. There's no form to submit to, so
647
      // drupalPost() won't work here; this just tests a direct $_POST request
648
      // instead.
649
      $curl_parameters = array(
650
        CURLOPT_URL => $this->getAbsoluteUrl('system-test/request-destination'),
651
        CURLOPT_POST => TRUE,
652
        CURLOPT_POSTFIELDS => 'destination=' . urlencode($test_case['input']),
653
        CURLOPT_HTTPHEADER => array(),
654
      );
655
      $post_output = $this->curlExec($curl_parameters);
656
      $this->assertIdentical($test_case['output'], $post_output, $test_case['message']);
657
    }
658

    
659
    // Make sure that 404 pages do not populate $_GET['destination'] with
660
    // external URLs.
661
    variable_set('site_404', 'system-test/get-destination');
662
    $this->drupalGet('http://example.com', array('external' => FALSE));
663
    $this->assertIdentical('', $this->drupalGetContent(), 'External URL is not allowed on 404 pages.');
664
  }
665
}