diff -r 07239de796bb -r e756a8c72c3d cms/drupal/modules/simpletest/tests/common.test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/drupal/modules/simpletest/tests/common.test Fri Sep 08 12:04:06 2017 +0200
@@ -0,0 +1,3182 @@
+ 'drupal_alter() tests',
+ 'description' => 'Confirm that alteration of arguments passed to drupal_alter() works correctly.',
+ 'group' => 'System',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('common_test');
+ }
+
+ function testDrupalAlter() {
+ // This test depends on Bartik, so make sure that it is always the current
+ // active theme.
+ global $theme, $base_theme_info;
+ $theme = 'bartik';
+ $base_theme_info = array();
+
+ $array = array('foo' => 'bar');
+ $entity = new stdClass();
+ $entity->foo = 'bar';
+
+ // Verify alteration of a single argument.
+ $array_copy = $array;
+ $array_expected = array('foo' => 'Drupal theme');
+ drupal_alter('drupal_alter', $array_copy);
+ $this->assertEqual($array_copy, $array_expected, 'Single array was altered.');
+
+ $entity_copy = clone $entity;
+ $entity_expected = clone $entity;
+ $entity_expected->foo = 'Drupal theme';
+ drupal_alter('drupal_alter', $entity_copy);
+ $this->assertEqual($entity_copy, $entity_expected, 'Single object was altered.');
+
+ // Verify alteration of multiple arguments.
+ $array_copy = $array;
+ $array_expected = array('foo' => 'Drupal theme');
+ $entity_copy = clone $entity;
+ $entity_expected = clone $entity;
+ $entity_expected->foo = 'Drupal theme';
+ $array2_copy = $array;
+ $array2_expected = array('foo' => 'Drupal theme');
+ drupal_alter('drupal_alter', $array_copy, $entity_copy, $array2_copy);
+ $this->assertEqual($array_copy, $array_expected, 'First argument to drupal_alter() was altered.');
+ $this->assertEqual($entity_copy, $entity_expected, 'Second argument to drupal_alter() was altered.');
+ $this->assertEqual($array2_copy, $array2_expected, 'Third argument to drupal_alter() was altered.');
+
+ // Verify alteration order when passing an array of types to drupal_alter().
+ // common_test_module_implements_alter() places 'block' implementation after
+ // other modules.
+ $array_copy = $array;
+ $array_expected = array('foo' => 'Drupal block theme');
+ drupal_alter(array('drupal_alter', 'drupal_alter_foo'), $array_copy);
+ $this->assertEqual($array_copy, $array_expected, 'hook_TYPE_alter() implementations ran in correct order.');
+ }
+}
+
+/**
+ * Tests for URL generation functions.
+ *
+ * url() calls module_implements(), which may issue a db query, which requires
+ * inheriting from a web test case rather than a unit test case.
+ */
+class CommonURLUnitTest extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'URL generation tests',
+ 'description' => 'Confirm that url(), drupal_get_query_parameters(), drupal_http_build_query(), and l() work correctly with various input.',
+ 'group' => 'System',
+ );
+ }
+
+ /**
+ * Confirm that invalid text given as $path is filtered.
+ */
+ function testLXSS() {
+ $text = $this->randomName();
+ $path = "";
+ $link = l($text, $path);
+ $sanitized_path = check_url(url($path));
+ $this->assertTrue(strpos($link, $sanitized_path) !== FALSE, format_string('XSS attack @path was filtered', array('@path' => $path)));
+ }
+
+ /*
+ * Tests for active class in l() function.
+ */
+ function testLActiveClass() {
+ $link = l($this->randomName(), $_GET['q']);
+ $this->assertTrue($this->hasClass($link, 'active'), format_string('Class @class is present on link to the current page', array('@class' => 'active')));
+ }
+
+ /**
+ * Tests for custom class in l() function.
+ */
+ function testLCustomClass() {
+ $class = $this->randomName();
+ $link = l($this->randomName(), $_GET['q'], array('attributes' => array('class' => array($class))));
+ $this->assertTrue($this->hasClass($link, $class), format_string('Custom class @class is present on link when requested', array('@class' => $class)));
+ $this->assertTrue($this->hasClass($link, 'active'), format_string('Class @class is present on link to the current page', array('@class' => 'active')));
+ }
+
+ private function hasClass($link, $class) {
+ return preg_match('|class="([^\"\s]+\s+)*' . $class . '|', $link);
+ }
+
+ /**
+ * Test drupal_get_query_parameters().
+ */
+ function testDrupalGetQueryParameters() {
+ $original = array(
+ 'a' => 1,
+ 'b' => array(
+ 'd' => 4,
+ 'e' => array(
+ 'f' => 5,
+ ),
+ ),
+ 'c' => 3,
+ 'q' => 'foo/bar',
+ );
+
+ // Default arguments.
+ $result = $_GET;
+ unset($result['q']);
+ $this->assertEqual(drupal_get_query_parameters(), $result, "\$_GET['q'] was removed.");
+
+ // Default exclusion.
+ $result = $original;
+ unset($result['q']);
+ $this->assertEqual(drupal_get_query_parameters($original), $result, "'q' was removed.");
+
+ // First-level exclusion.
+ $result = $original;
+ unset($result['b']);
+ $this->assertEqual(drupal_get_query_parameters($original, array('b')), $result, "'b' was removed.");
+
+ // Second-level exclusion.
+ $result = $original;
+ unset($result['b']['d']);
+ $this->assertEqual(drupal_get_query_parameters($original, array('b[d]')), $result, "'b[d]' was removed.");
+
+ // Third-level exclusion.
+ $result = $original;
+ unset($result['b']['e']['f']);
+ $this->assertEqual(drupal_get_query_parameters($original, array('b[e][f]')), $result, "'b[e][f]' was removed.");
+
+ // Multiple exclusions.
+ $result = $original;
+ unset($result['a'], $result['b']['e'], $result['c']);
+ $this->assertEqual(drupal_get_query_parameters($original, array('a', 'b[e]', 'c')), $result, "'a', 'b[e]', 'c' were removed.");
+ }
+
+ /**
+ * Test drupal_http_build_query().
+ */
+ function testDrupalHttpBuildQuery() {
+ $this->assertEqual(drupal_http_build_query(array('a' => ' //+%20@۞')), 'a=%20%26%23//%2B%2520%40%DB%9E', 'Value was properly encoded.');
+ $this->assertEqual(drupal_http_build_query(array(' //+%20@۞' => 'a')), '%20%26%23%2F%2F%2B%2520%40%DB%9E=a', 'Key was properly encoded.');
+ $this->assertEqual(drupal_http_build_query(array('a' => '1', 'b' => '2', 'c' => '3')), 'a=1&b=2&c=3', 'Multiple values were properly concatenated.');
+ $this->assertEqual(drupal_http_build_query(array('a' => array('b' => '2', 'c' => '3'), 'd' => 'foo')), 'a%5Bb%5D=2&a%5Bc%5D=3&d=foo', 'Nested array was properly encoded.');
+ }
+
+ /**
+ * Test drupal_parse_url().
+ */
+ function testDrupalParseUrl() {
+ // Relative URL.
+ $url = 'foo/bar?foo=bar&bar=baz&baz#foo';
+ $result = array(
+ 'path' => 'foo/bar',
+ 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''),
+ 'fragment' => 'foo',
+ );
+ $this->assertEqual(drupal_parse_url($url), $result, 'Relative URL parsed correctly.');
+
+ // Relative URL that is known to confuse parse_url().
+ $url = 'foo/bar:1';
+ $result = array(
+ 'path' => 'foo/bar:1',
+ 'query' => array(),
+ 'fragment' => '',
+ );
+ $this->assertEqual(drupal_parse_url($url), $result, 'Relative URL parsed correctly.');
+
+ // Absolute URL.
+ $url = '/foo/bar?foo=bar&bar=baz&baz#foo';
+ $result = array(
+ 'path' => '/foo/bar',
+ 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''),
+ 'fragment' => 'foo',
+ );
+ $this->assertEqual(drupal_parse_url($url), $result, 'Absolute URL parsed correctly.');
+
+ // External URL testing.
+ $url = 'http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo';
+
+ // Test that drupal can recognize an absolute URL. Used to prevent attack vectors.
+ $this->assertTrue(url_is_external($url), 'Correctly identified an external URL.');
+
+ // External URL without an explicit protocol.
+ $url = '//drupal.org/foo/bar?foo=bar&bar=baz&baz#foo';
+ $this->assertTrue(url_is_external($url), 'Correctly identified an external URL without a protocol part.');
+
+ // Internal URL starting with a slash.
+ $url = '/drupal.org';
+ $this->assertFalse(url_is_external($url), 'Correctly identified an internal URL with a leading slash.');
+
+ // Test the parsing of absolute URLs.
+ $url = 'http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo';
+ $result = array(
+ 'path' => 'http://drupal.org/foo/bar',
+ 'query' => array('foo' => 'bar', 'bar' => 'baz', 'baz' => ''),
+ 'fragment' => 'foo',
+ );
+ $this->assertEqual(drupal_parse_url($url), $result, 'External URL parsed correctly.');
+
+ // Verify proper parsing of URLs when clean URLs are disabled.
+ $result = array(
+ 'path' => 'foo/bar',
+ 'query' => array('bar' => 'baz'),
+ 'fragment' => 'foo',
+ );
+ // Non-clean URLs #1: Absolute URL generated by url().
+ $url = $GLOBALS['base_url'] . '/?q=foo/bar&bar=baz#foo';
+ $this->assertEqual(drupal_parse_url($url), $result, 'Absolute URL with clean URLs disabled parsed correctly.');
+
+ // Non-clean URLs #2: Relative URL generated by url().
+ $url = '?q=foo/bar&bar=baz#foo';
+ $this->assertEqual(drupal_parse_url($url), $result, 'Relative URL with clean URLs disabled parsed correctly.');
+
+ // Non-clean URLs #3: URL generated by url() on non-Apache webserver.
+ $url = 'index.php?q=foo/bar&bar=baz#foo';
+ $this->assertEqual(drupal_parse_url($url), $result, 'Relative URL on non-Apache webserver with clean URLs disabled parsed correctly.');
+
+ // Test that drupal_parse_url() does not allow spoofing a URL to force a malicious redirect.
+ $parts = drupal_parse_url('forged:http://cwe.mitre.org/data/definitions/601.html');
+ $this->assertFalse(valid_url($parts['path'], TRUE), 'drupal_parse_url() correctly parsed a forged URL.');
+ }
+
+ /**
+ * Test url() with/without query, with/without fragment, absolute on/off and
+ * assert all that works when clean URLs are on and off.
+ */
+ function testUrl() {
+ global $base_url;
+
+ foreach (array(FALSE, TRUE) as $absolute) {
+ // Get the expected start of the path string.
+ $base = $absolute ? $base_url . '/' : base_path();
+ $absolute_string = $absolute ? 'absolute' : NULL;
+
+ // Disable Clean URLs.
+ $GLOBALS['conf']['clean_url'] = 0;
+
+ $url = $base . '?q=node/123';
+ $result = url('node/123', array('absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . '?q=node/123#foo';
+ $result = url('node/123', array('fragment' => 'foo', 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . '?q=node/123&foo';
+ $result = url('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . '?q=node/123&foo=bar&bar=baz';
+ $result = url('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . '?q=node/123&foo#bar';
+ $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . '?q=node/123&foo#0';
+ $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => '0', 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . '?q=node/123&foo';
+ $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => '', 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base;
+ $result = url('', array('absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ // Enable Clean URLs.
+ $GLOBALS['conf']['clean_url'] = 1;
+
+ $url = $base . 'node/123';
+ $result = url('node/123', array('absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . 'node/123#foo';
+ $result = url('node/123', array('fragment' => 'foo', 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . 'node/123?foo';
+ $result = url('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . 'node/123?foo=bar&bar=baz';
+ $result = url('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base . 'node/123?foo#bar';
+ $result = url('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+
+ $url = $base;
+ $result = url('', array('absolute' => $absolute));
+ $this->assertEqual($url, $result, "$url == $result");
+ }
+ }
+
+ /**
+ * Test external URL handling.
+ */
+ function testExternalUrls() {
+ $test_url = 'http://drupal.org/';
+
+ // Verify external URL can contain a fragment.
+ $url = $test_url . '#drupal';
+ $result = url($url);
+ $this->assertEqual($url, $result, 'External URL with fragment works without a fragment in $options.');
+
+ // Verify fragment can be overidden in an external URL.
+ $url = $test_url . '#drupal';
+ $fragment = $this->randomName(10);
+ $result = url($url, array('fragment' => $fragment));
+ $this->assertEqual($test_url . '#' . $fragment, $result, 'External URL fragment is overidden with a custom fragment in $options.');
+
+ // Verify external URL can contain a query string.
+ $url = $test_url . '?drupal=awesome';
+ $result = url($url);
+ $this->assertEqual($url, $result, 'External URL with query string works without a query string in $options.');
+
+ // Verify external URL can be extended with a query string.
+ $url = $test_url;
+ $query = array($this->randomName(5) => $this->randomName(5));
+ $result = url($url, array('query' => $query));
+ $this->assertEqual($url . '?' . http_build_query($query, '', '&'), $result, 'External URL can be extended with a query string in $options.');
+
+ // Verify query string can be extended in an external URL.
+ $url = $test_url . '?drupal=awesome';
+ $query = array($this->randomName(5) => $this->randomName(5));
+ $result = url($url, array('query' => $query));
+ $this->assertEqual($url . '&' . http_build_query($query, '', '&'), $result, 'External URL query string can be extended with a custom query string in $options.');
+
+ // Verify that an internal URL does not result in an external URL without
+ // protocol part.
+ $url = '/drupal.org';
+ $result = url($url);
+ $this->assertTrue(strpos($result, '//') === FALSE, 'Internal URL does not turn into an external URL.');
+
+ // Verify that an external URL without protocol part is recognized as such.
+ $url = '//drupal.org';
+ $result = url($url);
+ $this->assertEqual($url, $result, 'External URL without protocol is not altered.');
+ }
+}
+
+/**
+ * Tests url_is_external().
+ */
+class UrlIsExternalUnitTest extends DrupalUnitTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'External URL checking',
+ 'description' => 'Performs tests on url_is_external().',
+ 'group' => 'System',
+ );
+ }
+
+ /**
+ * Tests if each URL is external or not.
+ */
+ function testUrlIsExternal() {
+ foreach ($this->examples() as $path => $expected) {
+ $this->assertIdentical(url_is_external($path), $expected, $path);
+ }
+ }
+
+ /**
+ * Provides data for testUrlIsExternal().
+ *
+ * @return array
+ * An array of test data, keyed by a path, with the expected value where
+ * TRUE is external, and FALSE is not external.
+ */
+ protected function examples() {
+ return array(
+ // Simple external URLs.
+ 'http://example.com' => TRUE,
+ 'https://example.com' => TRUE,
+ 'http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo' => TRUE,
+ '//drupal.org' => TRUE,
+ // Some browsers ignore or strip leading control characters.
+ "\x00//www.example.com" => TRUE,
+ "\x08//www.example.com" => TRUE,
+ "\x1F//www.example.com" => TRUE,
+ "\n//www.example.com" => TRUE,
+ // JSON supports decoding directly from UTF-8 code points.
+ json_decode('"\u00AD"') . "//www.example.com" => TRUE,
+ json_decode('"\u200E"') . "//www.example.com" => TRUE,
+ json_decode('"\uE0020"') . "//www.example.com" => TRUE,
+ json_decode('"\uE000"') . "//www.example.com" => TRUE,
+ // Backslashes should be normalized to forward.
+ '\\\\example.com' => TRUE,
+ // Local URLs.
+ 'node' => FALSE,
+ '/system/ajax' => FALSE,
+ '?q=foo:bar' => FALSE,
+ 'node/edit:me' => FALSE,
+ '/drupal.org' => FALSE,
+ '' => FALSE,
+ );
+ }
+}
+
+/**
+ * Tests for check_plain(), filter_xss(), format_string(), and check_url().
+ */
+class CommonXssUnitTest extends DrupalUnitTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'String filtering tests',
+ 'description' => 'Confirm that check_plain(), filter_xss(), format_string() and check_url() work correctly, including invalid multi-byte sequences.',
+ 'group' => 'System',
+ );
+ }
+
+ /**
+ * Check that invalid multi-byte sequences are rejected.
+ */
+ function testInvalidMultiByte() {
+ // Ignore PHP 5.3+ invalid multibyte sequence warning.
+ $text = @check_plain("Foo\xC0barbaz");
+ $this->assertEqual($text, '', 'check_plain() rejects invalid sequence "Foo\xC0barbaz"');
+ // Ignore PHP 5.3+ invalid multibyte sequence warning.
+ $text = @check_plain("\xc2\"");
+ $this->assertEqual($text, '', 'check_plain() rejects invalid sequence "\xc2\""');
+ $text = check_plain("Fooÿñ");
+ $this->assertEqual($text, "Fooÿñ", 'check_plain() accepts valid sequence "Fooÿñ"');
+ $text = filter_xss("Foo\xC0barbaz");
+ $this->assertEqual($text, '', 'filter_xss() rejects invalid sequence "Foo\xC0barbaz"');
+ $text = filter_xss("Fooÿñ");
+ $this->assertEqual($text, "Fooÿñ", 'filter_xss() accepts valid sequence Fooÿñ');
+ }
+
+ /**
+ * Check that special characters are escaped.
+ */
+ function testEscaping() {
+ $text = check_plain("