t('Size parsing test'), 'description' => t('Parse a predefined amount of bytes and compare the output with the expected value.'), 'group' => t('System') ); } /** * Implementation of setUp(). */ function setUp() { $kb = DRUPAL_KILOBYTE; $this->exact_test_cases = array( '1 byte' => 1, '1 KB' => $kb, '1 MB' => $kb * $kb, '1 GB' => $kb * $kb * $kb, '1 TB' => $kb * $kb * $kb * $kb, '1 PB' => $kb * $kb * $kb * $kb * $kb, '1 EB' => $kb * $kb * $kb * $kb * $kb * $kb, '1 ZB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb, '1 YB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb * $kb, ); $this->rounded_test_cases = array( '2 bytes' => 2, '1 MB' => ($kb * $kb) - 1, // rounded to 1 MB (not 1000 or 1024 kilobyte!) round(3623651 / ($this->exact_test_cases['1 MB']), 2) . ' MB' => 3623651, // megabytes round(67234178751368124 / ($this->exact_test_cases['1 PB']), 2) . ' PB' => 67234178751368124, // petabytes round(235346823821125814962843827 / ($this->exact_test_cases['1 YB']), 2) . ' YB' => 235346823821125814962843827, // yottabytes ); parent::setUp(); } /** * Check that format_size() returns the expected string. */ function testCommonFormatSize() { foreach (array($this->exact_test_cases, $this->rounded_test_cases) as $test_cases) { foreach ($test_cases as $expected => $input) { $this->assertEqual( ($result = format_size($input, NULL)), $expected, $expected . ' == ' . $result . ' (' . $input . ' bytes)' ); } } } /** * Check that parse_size() returns the proper byte sizes. */ function testCommonParseSize() { foreach ($this->exact_test_cases as $string => $size) { $this->assertEqual( $parsed_size = parse_size($string), $size, $size . ' == ' . $parsed_size . ' (' . $string . ')' ); } // Some custom parsing tests $string = '23476892 bytes'; $this->assertEqual( ($parsed_size = parse_size($string)), $size = 23476892, $string . ' == ' . $parsed_size . ' bytes' ); $string = '76MRandomStringThatShouldBeIgnoredByParseSize.'; // 76 MB $this->assertEqual( $parsed_size = parse_size($string), $size = 79691776, $string . ' == ' . $parsed_size . ' bytes' ); $string = '76.24 Giggabyte'; // Misspeld text -> 76.24 GB $this->assertEqual( $parsed_size = parse_size($string), $size = 81862076662, $string . ' == ' . $parsed_size . ' bytes' ); } /** * Cross-test parse_size() and format_size(). */ function testCommonParseSizeFormatSize() { foreach ($this->exact_test_cases as $size) { $this->assertEqual( $size, ($parsed_size = parse_size($string = format_size($size, NULL))), $size . ' == ' . $parsed_size . ' (' . $string . ')' ); } } } /** * Test drupal_explode_tags() and drupal_implode_tags(). */ class DrupalTagsHandlingTestCase extends DrupalWebTestCase { var $validTags = array( 'Drupal' => 'Drupal', 'Drupal with some spaces' => 'Drupal with some spaces', '"Legendary Drupal mascot of doom: ""Druplicon"""' => 'Legendary Drupal mascot of doom: "Druplicon"', '"Drupal, although it rhymes with sloopal, is as awesome as a troopal!"' => 'Drupal, although it rhymes with sloopal, is as awesome as a troopal!', ); /** * Implementation of getInfo(). */ function getInfo() { return array( 'name' => t('Drupal tags handling'), 'description' => t("Performs tests on Drupal's handling of tags, both explosion and implosion tactics used."), 'group' => t('System') ); } /** * Explode a series of tags. */ function testDrupalExplodeTags() { $string = implode(', ', array_keys($this->validTags)); $tags = drupal_explode_tags($string); $this->assertTags($tags); } /** * Implode a series of tags. */ function testDrupalImplodeTags() { $tags = array_values($this->validTags); // Let's explode and implode to our heart's content. for ($i = 0; $i < 10; $i++) { $string = drupal_implode_tags($tags); $tags = drupal_explode_tags($string); } $this->assertTags($tags); } /** * Helper function: asserts that the ending array of tags is what we wanted. */ function assertTags($tags) { $original = $this->validTags; foreach ($tags as $tag) { $key = array_search($tag, $original); $this->_assert($key !== FALSE, t('Make sure tag %tag shows up in the final tags array (originally %original)', array('%tag' => $tag, '%original' => $key))); unset($original[$key]); } foreach ($original as $leftover) { $this->_assert(FALSE, t('Leftover tag %leftover was left over.', array('%leftover' => $leftover))); } } } /** * Test the Drupal CSS system. */ class CascadingStylesheetsTestCase extends DrupalWebTestCase { /** * Implementation of getInfo(). */ function getInfo() { return array( 'name' => t('Cascading stylesheets'), 'description' => t('Tests adding various cascading stylesheets to the page.'), 'group' => t('System') ); } /** * Implementation of setUp(). */ function setUp() { parent::setUp(); // Reset drupal_add_css() before each test. drupal_add_css(NULL, NULL, TRUE); } /** * Check default stylesheets as empty. */ function testDefault() { $this->assertEqual(array(), drupal_add_css(), t('Default CSS is empty.')); } /** * Tests adding a file stylesheet. */ function testAddFile() { $path = drupal_get_path('module', 'simpletest') . '/simpletest.css'; $css = drupal_add_css($path); $this->assertEqual($css['all']['module'][$path], TRUE, t('Adding a CSS file caches it properly.')); } /** * Tests rendering the stylesheets. */ function testRenderFile() { $css = drupal_get_path('module', 'simpletest') . '/simpletest.css'; drupal_add_css($css); $this->assertTrue(strpos(drupal_get_css(), $css) > 0, t('Rendered CSS includes the added stylesheet.')); } } /** * Test drupal_http_request(). */ class DrupalHTTPRequestTestCase extends DrupalWebTestCase { /** * Implementation of getInfo(). */ function getInfo() { return array( 'name' => t('Drupal HTTP request'), 'description' => t("Performs tests on Drupal's HTTP request mechanism."), 'group' => t('System') ); } /** * Implementation of setUp(). */ function setUp() { parent::setUp('system_test'); } function testDrupalHTTPRequest() { // Parse URL schema. $missing_scheme = drupal_http_request('example.com/path'); $this->assertEqual($missing_scheme->error, 'missing schema', t('Returned with "missing schema" error.')); $unable_to_parse = drupal_http_request('http:///path'); $this->assertEqual($unable_to_parse->error, 'unable to parse URL', t('Returned with "unable to parse URL" error.')); // Fetch page. $result = drupal_http_request(url('node', array('absolute' => TRUE))); $this->assertEqual($result->code, 200, t('Fetched page successfully.')); $this->drupalSetContent($result->data); $this->assertTitle(variable_get('site_name', 'Drupal'), t('Site title matches.')); } function testDrupalHTTPRequestBasicAuth() { $username = $this->randomName(); $password = $this->randomName(); $url = url('system-test/auth', array('absolute' => TRUE)); $auth = str_replace('http://', 'http://' . $username . ':' . $password .'@', $url); $result = drupal_http_request($auth); // We use strpos directly. // assertRaw() cannot be used because we are getting the data // in a variable instead of $this->_content. $this->assertTrue(strpos($result->data, $username) !== FALSE, t('$_SERVER[\'PHP_AUTH_USER\'] is passed correctly.')); $this->assertTrue(strpos($result->data, $password) !== FALSE, t('$_SERVER[\'PHP_AUTH_PW\'] is passed correctly.')); } function testDrupalHTTPRequestRedirect() { $redirect_301 = drupal_http_request(url('system-test/redirect/301', array('absolute' => TRUE)), array(), 'GET', NULL, 1); $this->assertEqual($redirect_301->redirect_code, 301, t('drupal_http_request follows the 301 redirect.')); $redirect_301 = drupal_http_request(url('system-test/redirect/301', array('absolute' => TRUE)), array(), 'GET', NULL, 0); $this->assertFalse(isset($redirect_301->redirect_code), t('drupal_http_request does not follow 301 redirect if $retry = 0.')); $redirect_invalid = drupal_http_request(url('system-test/redirect-noscheme', array('absolute' => TRUE)), array(), 'GET', NULL, 1); $this->assertEqual($redirect_invalid->error, 'missing schema', t('301 redirect to invalid URL returned with error "!error".', array('!error' => $redirect_invalid->error))); $redirect_invalid = drupal_http_request(url('system-test/redirect-noparse', array('absolute' => TRUE)), array(), 'GET', NULL, 1); $this->assertEqual($redirect_invalid->error, 'unable to parse URL', t('301 redirect to invalid URL returned with error "!error".', array('!error' => $redirect_invalid->error))); $redirect_invalid = drupal_http_request(url('system-test/redirect-invalid-scheme', array('absolute' => TRUE)), array(), 'GET', NULL, 1); $this->assertEqual($redirect_invalid->error, 'invalid schema ftp', t('301 redirect to invalid URL returned with error "!error".', array('!error' => $redirect_invalid->error))); $redirect_302 = drupal_http_request(url('system-test/redirect/302', array('absolute' => TRUE)), array(), 'GET', NULL, 1); $this->assertEqual($redirect_302->redirect_code, 302, t('drupal_http_request follows the 302 redirect.')); $redirect_302 = drupal_http_request(url('system-test/redirect/302', array('absolute' => TRUE)), array(), 'GET', NULL, 0); $this->assertFalse(isset($redirect_302->redirect_code), t('drupal_http_request does not follow 302 redirect if $retry = 0.')); $redirect_307 = drupal_http_request(url('system-test/redirect/307', array('absolute' => TRUE)), array(), 'GET', NULL, 1); $this->assertEqual($redirect_307->redirect_code, 307, t('drupal_http_request follows the 307 redirect.')); $redirect_307 = drupal_http_request(url('system-test/redirect/307', array('absolute' => TRUE)), array(), 'GET', NULL, 0); $this->assertFalse(isset($redirect_307->redirect_code), t('drupal_http_request does not follow 307 redirect if $retry = 0.')); } function testDrupalGetDestination() { $query = $this->randomName(10); $url = url('system-test/destination', array('absolute' => TRUE, 'query' => $query)); $this->drupalGet($url); $this->assertText($query, t('The query passed to the page is correctly represented by drupal_get_detination().')); } } /** * Testing drupal_set_content and drupal_get_content. */ class DrupalSetContentTestCase extends DrupalWebTestCase { /** * Implementation of getInfo(). */ function getInfo() { return array( 'name' => t('Drupal set/get content'), 'description' => t("Performs tests on setting and retrieiving content from theme regions."), 'group' => t('System') ); } /** * Test setting and retrieving content for theme regions. */ function testRegions() { global $theme_key; $block_regions = array_keys(system_region_list($theme_key)); $delimiter = $this->randomName(32); $values = array(); // Set some random content for each region available. foreach ($block_regions as $region) { $first_chunk = $this->randomName(32); drupal_set_content($region, $first_chunk); $second_chunk = $this->randomName(32); drupal_set_content($region, $second_chunk); // Store the expected result for a drupal_get_content call for this region. $values[$region] = $first_chunk . $delimiter . $second_chunk; } // Ensure drupal_get_content returns expected results when fetching all regions. $content = drupal_get_content(NULL, $delimiter); foreach ($content as $region => $region_content) { $this->assertEqual($region_content, $values[$region], t('@region region text verified when fetching all regions', array('@region' => $region))); } // Ensure drupal_get_content returns expected results when fetching a single region. foreach ($block_regions as $region) { $region_content = drupal_get_content($region, $delimiter); $this->assertEqual($region_content, $values[$region], t('@region region text verified when fetching single region.', array('@region' => $region))); } } } /** * Tests for the JavaScript system. */ class JavaScriptTestCase extends DrupalWebTestCase { /** * Store configured value for JavaScript preprocessing. */ var $preprocess_js = NULL; /** * Implementation of getInfo(). */ function getInfo() { return array( 'name' => t('JavaScript'), 'description' => t("Tests the JavaScript system."), 'group' => t('System') ); } /** * Implementation of setUp(). */ function setUp() { // Enable locale in test environment. parent::setUp('locale'); // Disable preprocessing $this->preprocess_js = variable_get('preprocess_js', 0); variable_set('preprocess_js', 0); // Reset drupal_add_js() before each test. drupal_add_js(NULL, NULL, TRUE); } /** * Implementation of tearDown(). */ function tearDown() { // Restore configured value for JavaScript preprocessing. variable_set('preprocess_js', $this->preprocess_js); parent::tearDown(); } /** * Test default JavaScript is empty. */ function testDefault() { $this->assertEqual(array(), drupal_add_js(), t('Default JavaScript is empty.')); } /** * Test adding a JavaScript file. */ function testAddFile() { $javascript = drupal_add_js('misc/collapse.js'); $this->assertTrue(array_key_exists('misc/jquery.js', $javascript), t('jQuery is added when a file is added.')); $this->assertTrue(array_key_exists('misc/drupal.js', $javascript), t('Drupal.js is added when file is added.')); $this->assertTrue(array_key_exists('misc/collapse.js', $javascript), t('JavaScript files are correctly added.')); $this->assertEqual(base_path(), $javascript['settings']['data'][0]['basePath'], t('Base path JavaScript setting is correctly set.')); } /** * Test adding settings. */ function testAddSetting() { $javascript = drupal_add_js(array('drupal' => 'rocks', 'dries' => 280342800), 'setting'); $this->assertEqual(280342800, $javascript['settings']['data'][1]['dries'], t('JavaScript setting is set correctly.')); $this->assertEqual('rocks', $javascript['settings']['data'][1]['drupal'], t('The other JavaScript setting is set correctly.')); } /** * Test drupal_get_js() for JavaScript settings. */ function testHeaderSetting() { drupal_add_js(array('testSetting' => 'testValue'), 'setting'); $javascript = drupal_get_js('header'); $this->assertTrue(strpos($javascript, 'basePath') > 0, t('Rendered JavaScript header returns basePath setting.')); $this->assertTrue(strpos($javascript, 'testSetting') > 0, t('Rendered JavaScript header returns custom setting.')); $this->assertTrue(strpos($javascript, 'misc/jquery.js') > 0, t('Rendered JavaScript header includes jQuery.')); } /** * Test to see if resetting the JavaScript empties the cache. */ function testReset() { drupal_add_js('misc/collapse.js'); drupal_add_js(NULL, NULL, TRUE); $this->assertEqual(array(), drupal_add_js(), t('Resetting the JavaScript correctly empties the cache.')); } /** * Test adding inline scripts. */ function testAddInline() { $inline = '$(document).ready(function(){});'; $javascript = drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer')); $this->assertTrue(array_key_exists('misc/jquery.js', $javascript), t('jQuery is added when inline scripts are added.')); $data = end($javascript); $this->assertEqual($inline, $data['data'], t('Inline JavaScript is correctly added to the footer.')); } /** * Test drupal_get_js() with a footer scope. */ function testFooterHTML() { $inline = '$(document).ready(function(){});'; drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer')); $javascript = drupal_get_js('footer'); $this->assertTrue(strpos($javascript, $inline) > 0, t('Rendered JavaScript footer returns the inline code.')); } /** * Test drupal_add_js() sets preproccess to false when cache is set to false. */ function testNoCache() { $javascript = drupal_add_js('misc/collapse.js', array('cache' => FALSE)); $this->assertFalse($javascript['misc/collapse.js']['preprocess'], t('Setting cache to FALSE sets proprocess to FALSE when adding JavaScript.')); } /** * Test adding a JavaScript file with a different weight. */ function testDifferentWeight() { $javascript = drupal_add_js('misc/collapse.js', array('weight' => JS_THEME)); $this->assertEqual($javascript['misc/collapse.js']['weight'], JS_THEME, t('Adding a JavaScript file with a different weight caches the given weight.')); } /** * Test rendering the JavaScript with a file's weight above jQuery's. */ function testRenderDifferentWeight() { drupal_add_js('misc/collapse.js', array('weight' => JS_LIBRARY - 10)); $javascript = drupal_get_js(); $this->assertTrue(strpos($javascript, 'misc/collapse.js') < strpos($javascript, 'misc/jquery.js'), t('Rendering a JavaScript file above jQuery.')); } } /** * Tests Drupal error and exception handlers. */ class DrupalErrorHandlerUnitTest extends DrupalWebTestCase { function getInfo() { return array( 'name' => t('Drupal error handlers'), 'description' => t("Performs tests on the Drupal error and exception handler."), 'group' => t('System'), ); } function setUp() { parent::setUp('system_test'); } /** * Test the error handler. */ function testErrorHandler() { $this->drupalGet('system-test/generate-warnings'); $this->assertErrorMessage('Notice', 'system_test.module', 'system_test_generate_warnings() ', 'Undefined variable'); $this->assertErrorMessage('Warning', 'system_test.module', 'system_test_generate_warnings() ', 'Division by zero'); $this->assertErrorMessage('User notice', 'system_test.module', 'system_test_generate_warnings() ', 'Drupal is awesome'); } /** * Test the exception handler. */ function testExceptionHandler() { $this->drupalGet('system-test/trigger-exception'); $this->assertErrorMessage('Exception', 'system_test.module', 'system_test_trigger_exception()', 'Drupal is awesome'); $this->drupalGet('system-test/trigger-pdo-exception'); // We only check for SQLSTATE because the exact error reported varies from database to database. $this->assertErrorMessage('PDOException', 'system_test.module', 'system_test_trigger_pdo_exception()', 'SQLSTATE'); } /** * Helper function: assert that the logged message is correct. */ function assertErrorMessage($type, $file, $function, $message) { $this->assertText($type, t("Found '%type' in error page.", array('%type' => $type))); $this->assertText($file, t("Found '%file' in error page.", array('%file' => $file))); $this->assertText($function, t("Found '%function' in error page.", array('%function' => $function))); $this->assertText($message, t("Found '%message' in error page.", array('%message' => $message))); } }