Index: modules/simpletest/tests/file.test
===================================================================
--- modules/simpletest/tests/file.test	(Revision 93)
+++ modules/simpletest/tests/file.test	(Arbeitskopie)
@@ -796,6 +796,142 @@
 
 
 /**
+ * Test file_create_url() in various scenarios where no actual files need
+ * to be stored.
+ */
+class FileCreateUrlTest extends FileTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('File URLs'),
+      'description' => t('Tests the creation of basic file URLs.'),
+      'group' => t('File'),
+    );
+  }
+
+  function setUp() {
+    // It seems like file_directory_path is just about the only thing that can
+    // mess up the original Drupal installation if it's not reset properly at
+    // the end of the test.
+    $this->originalFileDirectoryPath = variable_get('file_directory_path', conf_path() . '/files');
+    // Setting the clean_url variable is also delicate as it might lead to
+    // invalid URLs during the test run, with similarly unwanted consequences.
+    $this->originalCleanUrl = variable_get('clean_url', 0);
+
+    // These tests don't require the files directory to be writable, so we can
+    // have a fixed path instead of retrieving the actual one.
+    $this->file_directory_path = 'sites/default/files';
+    $this->destination = 'misc/xyz.txt';
+  }
+
+  function tearDown() {
+    // Recover the original variables that were stored by setUp().
+    variable_set('file_directory_path', $this->originalFileDirectoryPath);
+    variable_set('clean_url', $this->originalCleanUrl);
+  }
+
+  /**
+   * Test file_create_url() for basic file paths.
+   */
+  function testFileCreateUrl() {
+    $this->fileCreatePublicUrls(TRUE);
+    $this->fileCreatePublicUrls(FALSE);
+    $this->fileCreatePrivateUrls(TRUE);
+    $this->fileCreatePrivateUrls(FALSE);
+  }
+
+  /**
+   * Test file_create_url() in public download mode with clean URLs either
+   * enabled (@p $clean_url is TRUE) or disabled (@p $clean_url is FALSE).
+   *
+   * For public downloads, every path is exactly the base URL plus the
+   * file path relative to the Drupal root directory. It should not matter
+   * whether clean URLs are enabled or not, but we're still testing both cases.
+   */
+  function fileCreatePublicUrls($clean_url) {
+    global $base_url;
+    variable_set('clean_url', $clean_url);
+    variable_set('file_downloads', FILE_DOWNLOADS_PUBLIC);
+
+    // All of these should end up with the same public file download URL.
+    $expected_url = $base_url . '/' . $this->file_directory_path . '/misc/xyz.txt';
+    $replacements = array(
+      '%expected' => $expected_url,
+      '!clean-urls' => $clean_url ? t('clean URLs') : t('no clean URLs'),
+    );
+
+    // Most common case, with a simple relative file directory path.
+    variable_set('file_directory_path', $this->file_directory_path);
+    $path = file_create_url($this->destination);
+    $this->assertEqual($path, $expected_url, t('Created file URL %path equals %expected. (public downloads, !clean-urls, relative file directory path.)', $replacements + array('%path' => $path)), 'File');
+
+    // An absolute file directory path that is inside the Drupal root directory.
+    // file_create_url() should strip that root directory in order to return
+    // a valid URL.
+    variable_set('file_directory_path', DRUPAL_ROOT . '/' . $this->file_directory_path);
+    $path = file_create_url($this->destination);
+    $expected_url = $base_url . '/' . $this->file_directory_path . '/misc/xyz.txt';
+    $this->assertEqual($path, $expected_url, t('Created file URL %path equals %expected. (public downloads, !clean-urls, absolute file directory path.)', $replacements + array('%path' => $path)), 'File');
+
+    // An absolute file directory path and an absolute file path, too.
+    // Both of these must be stripped of the root directory.
+    $path = file_create_url(file_directory_path() . '/' . $this->destination);
+    $expected_url = $base_url . '/' . $this->file_directory_path . '/misc/xyz.txt';
+    $this->assertEqual($path, $expected_url, t('Created file URL %path equals %expected. (public downloads, !clean-urls, absolute file directory path and absolute file path.)', $replacements + array('%path' => $path)), 'File');
+
+    // URLs can't be correctly determined if public downloads are combined with
+    // an absolute file directory path outside of the Drupal root directory.
+    // The result might be whatever broken URL there is. (-> *not* equal)
+    variable_set('file_directory_path', dirname(DRUPAL_ROOT) . '/outside-path');
+    $path = file_create_url($this->destination);
+    $this->assertNotEqual($path, $expected_url, t('Created file URL %path does not equal %expected. (public downloads, !clean-urls, absolute file directory path outside of the Drupal root directory.)', $replacements + array('%path' => $path)), 'File');
+  }
+
+  /**
+   * Test file_create_url() in private download mode with clean URLs either
+   * enabled (@p $clean_url is TRUE) or disabled (@p $clean_url is FALSE).
+   * For private downloads, every path starts with "system/files" which will
+   * internally be translated to the file directory path. The remainder of the
+   * file path then constitutes the rest of the menu path.
+   */
+  function fileCreatePrivateUrls($clean_url) {
+    global $base_url;
+    variable_set('clean_url', $clean_url);
+    variable_set('file_downloads', FILE_DOWNLOADS_PRIVATE);
+
+    // All of these should end up with the same private file download URL.
+    $expected_url = $base_url . ($clean_url ? '/' : '/?q=') . 'system/files/misc/xyz.txt';
+    $replacements = array(
+      '%expected' => $expected_url,
+      '!clean-urls' => $clean_url ? t('clean URLs') : t('no clean URLs'),
+    );
+
+    // Most common case, with a simple relative file directory path.
+    variable_set('file_directory_path', $this->file_directory_path);
+    $path = file_create_url($this->destination);
+    $this->assertEqual($path, $expected_url, t('Created file URL %path equals %expected. (private downloads, !clean-urls, relative file directory path.)', $replacements + array('%path' => $path)), 'File');
+
+    // For private downloads, an absolute file directory path should not pose
+    // any difficulties as the URL starts with a simple "system/files" anyways.
+    variable_set('file_directory_path', DRUPAL_ROOT . '/' . $this->file_directory_path);
+    $path = file_create_url($this->destination);
+    $this->assertEqual($path, $expected_url, t('Created file URL %path equals %expected. (private downloads, !clean-urls, absolute file directory path.)', array('%path' => $path, '%expected' => $expected_url)), 'File');
+
+    // An absolute file directory path and an absolute file path, too.
+    // The file path should be stripped of the file directory so that it can
+    // be appended to "system/files".
+    $path = file_create_url(file_directory_path() . '/' . $this->destination);
+    $this->assertEqual($path, $expected_url, t('Created file URL %path equals %expected. (private downloads, !clean-urls, absolute file directory path and absolute file path.)', array('%path' => $path, '%expected' => $expected_url)), 'File');
+
+    // An absolute file directory path outside of the Drupal root directory.
+    // Unlike public downloads, even that should again result in the same URL.
+    variable_set('file_directory_path', dirname(DRUPAL_ROOT) . '/outside-path');
+    $path = file_create_url($this->destination);
+    $this->assertEqual($path, $expected_url, t('Created file URL %path equals %expected. (public downloads, !clean-urls, absolute file directory path outside of the Drupal root directory.)', array('%path' => $path, '%expected' => $expected_url)), 'File');
+  }
+}
+
+
+/**
  * Deletion related tests.
  */
 class FileUnmanagedDeleteTest extends FileTestCase {
