I'm writing tests for xmlsitemap_engines:

This is the code that runs in xmlsitemap_engines_cron():

  foreach ($engines as $engine) {
    $url = xmlsitemap_engines_prepare_url(xmlsitemap_engines_get_engines($engine, 'url'));
    $request = drupal_http_request($url);
    watchdog('xmlsitemap', 'Submitted the sitemap to %url.', array('%url' => $url));
  }

And I have an xmlsitemap_engines_test.module that implements the following:

/**
 * Implementation of hook_menu().
 */
function xmlsitemap_engines_test_menu() {
  $items['ping'] = array(
    'page callback' => 'xmlsitemap_engines_test_pinged',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_xmlsitemap_engines_alter().
 */
function xmlsitemap_engines_test_xmlsitemap_engines_alter(&$engines) {
  $engines['simpletest'] = array(
    'name' => t('SimpleTest'),
    'url' => url('ping', array('absolute' => TRUE, 'query' => 'sitemap=[sitemap]')),
  );
}

function xmlsitemap_engines_test_pinged() {
  if (empty($_GET['sitemap'])) {
    watchdog('xmlsitemap', 'No sitemap parameter provided.', NULL, WATCHDOG_WARNING);
  }
  else {
    watchdog('xmlsitemap', 'Recieved ping for @sitemap.', array('@sitemap' => $_GET['sitemap']));
  }
}

And this is the code in xmlsitemap_engines.test:

  function testPing() {
    $edit = array('xmlsitemap_engines_engines[simpletest]' => TRUE);
    $this->drupalPost('admin/settings/xmlsitemap/engines', $edit, t('Save configuration'));
    $this->assertText(t('The configuration options have been saved.'));

    drupal_cron_run();
    $query = db_query("SELECT type, message, variables, severity, link FROM {watchdog} ORDER BY wid DESC");
    while ($watchdog = db_fetch_array($query)) {
      $this->assertTrue(TRUE, var_export($watchdog, TRUE));
    }
  }

The test results return the watchdog/dblog records that were called in xmlsitemap_engines_cron() but none of the watchdog records in xmlsitemap_engines_test_pinged(). I do verify that the code is being executed correctly because I added some log-file-writing calls in xmlsitemap_engines_test_pinged().

So the main problem is this: drupal_http_request() causes the $_SERVER['HTTP_USER_AGENT'] to be changed to Drupal (+http://drupal.org/). Now when the xmlsitemap_engines_test_pinged() code executes, the SimpleTest useragent is not found, and so the normal database is used, instead of the 'testing' database. I verified this by adding this line to settings.php and the result of the log file:

+ file_put_contents('./log.txt', request_uri() . ' ' . $_SERVER['HTTP_USER_AGENT'] . "\n", FILE_APPEND);
/admin/build/testing Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523 Linux Mint/6 (Felicia) Firefox/3.0.10
/batch?op=start&id=342 Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523 Linux Mint/6 (Felicia) Firefox/3.0.10
/batch?id=342&op=do Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523 Linux Mint/6 (Felicia) Firefox/3.0.10
/user simpletest881040
/user simpletest881040
/user/3 simpletest881040
/admin/settings/xmlsitemap/engines simpletest881040
/admin/settings/xmlsitemap/engines simpletest881040
/admin/settings/xmlsitemap/engines simpletest881040
/ping?sitemap=http://mysql.drupal6dev.local/sitemap.xml Drupal (+http://drupal.org/)
/ simpletest881040
/batch?id=342&op=finished Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523 Linux Mint/6 (Felicia) Firefox/3.0.10
/admin/build/testing Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523 Linux Mint/6 (Felicia) Firefox/3.0.10

Any ideas on how best to run these tests when I want to test that the drupal_http_request() is performed correctly? Should I just not try to test that the request was received and just test that it was sent properly? Help me boombatower and community! :)

CommentFileSizeAuthor
#2 0-simpletest-httprequest-D6.patch1.22 KBdave reid

Comments

dave reid’s picture

I just realized that this would require the modification made to drupal_http_request in Drupal 7 to pass the SimpleTest user agent string instead:

  // If the database prefix is being used by SimpleTest to run the tests in a copied
  // database then set the user-agent header to the database prefix so that any
  // calls to other Drupal pages will run the SimpleTest prefixed database. The
  // user-agent is used to ensure that multiple testing sessions running at the
  // same time won't interfere with each other as they would if the database
  // prefix were stored statically in a file or database variable.
  if (preg_match("/simpletest\d+/", $db_prefix, $matches)) {
    $options['headers']['User-Agent'] = $matches[0];
  }

Is there any way to backport this to D6 somehow? Add an optional patch? Still any ideas on how to best write these tests for Drupal 6?

dave reid’s picture

StatusFileSize
new1.22 KB

Here's the patch that would needed to be applied to D6.

boombatower’s picture

You can see if they will commit the patch to D6 core, but otherwise that is the only real option...or just apply it locally. I had the same problem until I wrote that patch for D7. :)

dave reid’s picture

For now I just added this section of code to xmlsitemap_engines_cron():

  $headers = array();
  if (preg_match("/simpletest\d+/", $GLOBALS['db_prefix'], $matches)) {
    $headers['User-Agent'] = $matches[0];
  }

And then use drupal_http_request($url, $headers); which works. What do you think the chances would be that the patch would be accepted for core?

boombatower’s picture

It isn't a bug, so I'm not sure. It is definitely useful, but is technically more of a feature.

dave reid’s picture

Status: Active » Closed (works as designed)

See #482646: Backport SimpleTest testing in drupal_http_request(). Marking this as by design for now here. Gah, I should have just posted the patch here and moved the project. Oh well.