blob: 3761cb76117602d29e34c693c0492a3db10267bf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.fs.s3native;
import org.apache.hadoop.fs.Path;
import org.junit.Assert;
import org.junit.Test;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Test how URIs and login details are extracted from URIs.
*/
public class TestS3xLoginHelper extends Assert {
public static final String BUCKET = "s3a://bucket";
private static final URI ENDPOINT = uri(BUCKET);
public static final String S = "%2f";
public static final String P = "%2b";
public static final String P_RAW = "+";
public static final String USER = "user";
public static final String PASS = "pass";
public static final String PASLASHSLASH = "pa" + S + S;
public static final String PAPLUS = "pa" + P;
public static final String PAPLUS_RAW = "pa" + P_RAW;
public static final URI WITH_USER_AND_PASS = uri("s3a://user:pass@bucket");
public static final Path PATH_WITH_LOGIN =
new Path(uri("s3a://user:pass@bucket/dest"));
public static final URI WITH_SLASH_IN_PASS = uri(
"s3a://user:" + PASLASHSLASH + "@bucket");
public static final URI WITH_PLUS_IN_PASS = uri(
"s3a://user:" + PAPLUS + "@bucket");
public static final URI WITH_PLUS_RAW_IN_PASS = uri(
"s3a://user:" + PAPLUS_RAW + "@bucket");
public static final URI USER_NO_PASS = uri("s3a://user@bucket");
public static final URI WITH_USER_AND_COLON = uri("s3a://user:@bucket");
public static final URI NO_USER = uri("s3a://:pass@bucket");
public static final URI NO_USER_NO_PASS = uri("s3a://:@bucket");
public static final URI NO_USER_NO_PASS_TWO_COLON = uri("s3a://::@bucket");
/**
* Construct a URI; raises an RTE if it won't parse.
* This allows it to be used in static constructors.
* @param s URI string
* @return the URI
* @throws RuntimeException on a URI syntax problem
*/
private static URI uri(String s) {
try {
return new URI(s);
} catch (URISyntaxException e) {
throw new RuntimeException(e.toString(), e);
}
}
/**
* Assert that a built up FS URI matches the endpoint.
* @param uri URI to build the FS UIR from
*/
private void assertMatchesEndpoint(URI uri) {
assertEquals("Source " + uri,
ENDPOINT, S3xLoginHelper.buildFSURI(uri));
}
/**
* Assert that the login/pass details from a URI match that expected.
* @param user username
* @param pass password
* @param uri URI to build login details from
* @return the login tuple
*/
private S3xLoginHelper.Login assertMatchesLogin(String user,
String pass, URI uri) {
S3xLoginHelper.Login expected = new S3xLoginHelper.Login(user,
pass);
S3xLoginHelper.Login actual = S3xLoginHelper.extractLoginDetails(
uri);
if (!expected.equals(actual)) {
Assert.fail("Source " + uri
+ " login expected=:" + toString(expected)
+ " actual=" + toString(actual));
}
return actual;
}
@Test
public void testSimpleFSURI() throws Throwable {
assertMatchesEndpoint(ENDPOINT);
}
@Test
public void testLoginSimple() throws Throwable {
S3xLoginHelper.Login login = assertMatchesLogin("", "", ENDPOINT);
assertFalse("Login of " + login, login.hasLogin());
}
@Test
public void testLoginWithUserAndPass() throws Throwable {
S3xLoginHelper.Login login = assertMatchesLogin(USER, PASS,
WITH_USER_AND_PASS);
assertTrue("Login of " + login, login.hasLogin());
}
@Test
public void testLoginWithSlashInPass() throws Throwable {
assertMatchesLogin(USER, "pa//", WITH_SLASH_IN_PASS);
}
@Test
public void testLoginWithPlusInPass() throws Throwable {
assertMatchesLogin(USER, "pa+", WITH_PLUS_IN_PASS);
}
@Test
public void testLoginWithPlusRawInPass() throws Throwable {
assertMatchesLogin(USER, "pa+", WITH_PLUS_RAW_IN_PASS);
}
@Test
public void testLoginWithUser() throws Throwable {
assertMatchesLogin(USER, "", USER_NO_PASS);
}
@Test
public void testLoginWithUserAndColon() throws Throwable {
assertMatchesLogin(USER, "", WITH_USER_AND_COLON);
}
@Test
public void testLoginNoUser() throws Throwable {
assertMatchesLogin("", "", NO_USER);
}
@Test
public void testLoginNoUserNoPass() throws Throwable {
assertMatchesLogin("", "", NO_USER_NO_PASS);
}
@Test
public void testLoginNoUserNoPassTwoColon() throws Throwable {
assertMatchesLogin("", "", NO_USER_NO_PASS_TWO_COLON);
}
@Test
public void testFsUriWithUserAndPass() throws Throwable {
assertMatchesEndpoint(WITH_USER_AND_PASS);
}
@Test
public void testFsUriWithSlashInPass() throws Throwable {
assertMatchesEndpoint(WITH_SLASH_IN_PASS);
}
@Test
public void testFsUriWithPlusInPass() throws Throwable {
assertMatchesEndpoint(WITH_PLUS_IN_PASS);
}
@Test
public void testFsUriWithPlusRawInPass() throws Throwable {
assertMatchesEndpoint(WITH_PLUS_RAW_IN_PASS);
}
@Test
public void testFsUriWithUser() throws Throwable {
assertMatchesEndpoint(USER_NO_PASS);
}
@Test
public void testFsUriWithUserAndColon() throws Throwable {
assertMatchesEndpoint(WITH_USER_AND_COLON);
}
@Test
public void testFsiNoUser() throws Throwable {
assertMatchesEndpoint(NO_USER);
}
@Test
public void testFsUriNoUserNoPass() throws Throwable {
assertMatchesEndpoint(NO_USER_NO_PASS);
}
@Test
public void testFsUriNoUserNoPassTwoColon() throws Throwable {
assertMatchesEndpoint(NO_USER_NO_PASS_TWO_COLON);
}
@Test
public void testPathURIFixup() throws Throwable {
}
/**
* Stringifier. Kept in the code to avoid accidental logging in production
* code.
* @return login details for assertions.
*/
public String toString(S3xLoginHelper.Login login) {
final StringBuilder sb = new StringBuilder("LoginTuple{");
sb.append("<'").append(login.getUser()).append('\'');
sb.append(", '").append(login.getPassword()).append('\'');
sb.append('>');
return sb.toString();
}
}