/**
   * Tests FileURL's getters and setters.
   *
   * @throws MalformedURLException should not happen
   */
  @Test
  public void testAccessors() throws MalformedURLException {
    FileURL url = getRootURL();

    String scheme = getScheme();
    Credentials credentials = new Credentials("login", "password");
    String host = "host";
    int port = 10000;
    String path = getSchemePath("/path/to");
    String query = "query";

    url.setScheme(scheme);
    url.setCredentials(credentials);
    url.setHost(host);
    url.setPort(port);
    url.setPath(path);
    url.setQuery(query);
    url.setProperty("name", "value");

    assert scheme.equals(url.getScheme());
    assert credentials.equals(url.getCredentials(), true);
    assert host.equals(url.getHost());
    assert port == url.getPort();
    assert path.equals(url.getPath());
    assert query.equals(url.getQuery());
    assert "to".equals(url.getFilename());
    assert "value".equals(url.getProperty("name"));

    // Test null values

    url.setCredentials(null);
    url.setHost(null);
    url.setPort(-1);
    url.setPath("/");
    url.setQuery(null);
    url.setProperty("name", null);

    assert scheme.equals(url.getScheme());
    assert url.getCredentials() == null;
    assert !url.containsCredentials();
    assert url.getHost() == null;
    assert -1 == url.getPort();
    assert "/".equals(url.getPath());
    assert url.getQuery() == null;
    assert url.getFilename() == null;
    assert url.getProperty("name") == null;
    assert (scheme + "://").equals(url.toString(true, false));

    // Path cannot be null, the path is supposed to be "/" if a null or empty value is specified
    url.setPath(null);
    assert "/".equals(url.getPath());
    url.setPath("");
    assert "/".equals(url.getPath());

    // Path must always start with a leading '/', if the specified does not then a '/' is
    // automatically added
    url.setPath("path/to");
    assert "/path/to".equals(url.getPath());
  }
  /**
   * Tests {@link FileURL#clone()}.
   *
   * @throws MalformedURLException should not happen
   */
  @Test
  public void testClone() throws MalformedURLException {
    FileURL url = getURL("login", "password", "host", 10000, "/path/to", "query");
    url.setProperty("name", "value");

    FileURL clonedURL = (FileURL) url.clone();

    // Assert that both instances are equal according to FileURL#equals
    assertEquals(url, clonedURL);

    // Assert that both URL's string representations (with credentials) are equal
    assert url.toString(true).equals(clonedURL.toString(true));

    // Assert that both instances are not one and the same
    assert url != clonedURL;

    // Assert that the property has survived the cloning
    assert "value".equals(clonedURL.getProperty("name"));
  }
  @Override
  protected FileSystem getHadoopFileSystem(FileURL url) throws IOException {
    // Note: getRealm returns a fresh instance every time
    FileURL realm = url.getRealm();

    Configuration conf = new Configuration();

    // Import the user from the URL's authority, if set
    // TODO: for some reason, setting the group has no effect: files are still created with the
    // default supergroup
    conf.setStrings(UnixUserGroupInformation.UGI_PROPERTY_NAME, getUsername(url), getGroup(url));

    return FileSystem.get(URI.create(realm.toString(false)), conf);
  }
  /**
   * Ensure that non URL-safe characters in login and password parts are properly handled, both when
   * parsing and representing URLs as string.
   *
   * @throws MalformedURLException should not happen
   */
  @Test
  public void testCredentialsURLEncoding() throws MalformedURLException {
    FileURL url = getRootURL();

    String urlDecodedString = ":@&=+$,/?t%#[]";
    String urlEncodedString = "%3A%40%26%3D%2B%24%2C%2F%3Ft%25%23%5B%5D";

    url.setCredentials(new Credentials(urlDecodedString, urlDecodedString));
    String urlRep = url.getScheme() + "://" + urlEncodedString + ":" + urlEncodedString + "@";
    assert urlRep.equals(url.toString(true, false));

    url = FileURL.getFileURL(urlRep);
    Credentials credentials = url.getCredentials();
    assert credentials.getLogin().equals(urlDecodedString);
    assert credentials.getPassword().equals(urlDecodedString);
  }
  /**
   * Tests FileURL's <code>toString</code> methods.
   *
   * @throws MalformedURLException should not happen
   */
  @Test
  public void testStringRepresentation() throws MalformedURLException {
    FileURL url = getURL("login", "password", "host", 10000, "/path", "query");
    String path = getSchemePath("/path");
    String urlString = getScheme() + "://host:10000" + path + "?query";

    assert urlString.equals(url.toString());
    assert urlString.equals(url.toString(false));
    assert urlString.equals(url.toString(false, false));

    urlString = getScheme() + "://login:password@host:10000" + path + "?query";
    assert urlString.equals(url.toString(true));
    assert urlString.equals(url.toString(true, false));

    urlString = getScheme() + "://login:********@host:10000" + path + "?query";
    assert urlString.equals(url.toString(true, true));
  }
  /**
   * Creates a URL from the given parts, ensuring that parsing it yields the given parts, and
   * returns it.
   *
   * @param login login part, may be <code>null</code>
   * @param password password part, may be <code>null</code>
   * @param host host part, may be <code>null</code>
   * @param port port part, <code>-1</code> for none
   * @param path path part
   * @param query query part, may be <code>null</code>
   * @return a URL corresponding to the given parts
   * @throws MalformedURLException if the URL cannot be parsed
   */
  protected FileURL getURL(
      String login, String password, String host, int port, String path, String query)
      throws MalformedURLException {
    String scheme = getScheme();
    StringBuffer sb = new StringBuffer(scheme + "://");

    if (host != null) {
      if (login != null) {
        sb.append(login);

        if (password != null) {
          sb.append(':');
          sb.append(password);
        }

        sb.append('@');
      }

      sb.append(host);

      if (port != -1) {
        sb.append(':');
        sb.append(port);
      }
    }

    path = getSchemePath(path);
    sb.append(path);

    if (query != null) {
      sb.append('?');
      sb.append(query);
    }

    // Assert that each of the url's parts match

    FileURL url = FileURL.getFileURL(sb.toString());

    assert scheme.equals(url.getScheme());

    if (host != null) {
      if (login != null) {
        assert login.equals(url.getLogin());
        assert url.containsCredentials();

        if (password != null) assert password.equals(url.getPassword());

        assert new Credentials(login, password).equals(url.getCredentials(), true);
      }

      assert host.equals(url.getHost());
      assert port == url.getPort();
    }

    if (query != null && !isQueryParsed()) {
      assert url.getQuery() == null;
      path = path + "?" + query;
    } else if (query == null) assert url.getQuery() == null;
    else assert query.equals(url.getQuery());

    assertPathEquals(path, url);

    // Test the URL's string representation
    assert url.equals(FileURL.getFileURL(url.toString(true, false)));
    assert url.equals(FileURL.getFileURL(url.toString(false, false)), false, false);

    return url;
  }