/*******************************************************************************
* Copyright (c) 2012-2016 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.everrest.core.impl.uri;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import org.everrest.core.impl.MultivaluedMapImpl;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.PathSegment;
import java.net.URI;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static org.everrest.core.impl.uri.UriComponent.HOST;
import static org.everrest.core.impl.uri.UriComponent.PATH_SEGMENT;
import static org.everrest.core.impl.uri.UriComponent.checkHexCharacters;
import static org.everrest.core.impl.uri.UriComponent.decode;
import static org.everrest.core.impl.uri.UriComponent.encode;
import static org.everrest.core.impl.uri.UriComponent.parsePathSegments;
import static org.everrest.core.impl.uri.UriComponent.parseQueryString;
import static org.everrest.core.impl.uri.UriComponent.recognizeEncode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(DataProviderRunner.class)
public class UriComponentTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void checksHexCharacters() {
String str = "%20%23%a0%ag";
assertTrue(checkHexCharacters(str, 0));
assertFalse(checkHexCharacters(str, 1));
assertTrue(checkHexCharacters(str, 3));
assertTrue(checkHexCharacters(str, 6));
assertFalse(checkHexCharacters(str, 9));
assertFalse(checkHexCharacters(str, 11));
}
@Test
public void encodesString() {
String str = "\u041f?\u0440#\u0438 \u0432\u0456\u0442";
String encoded = "%D0%9F%3F%D1%80%23%D0%B8%20%D0%B2%D1%96%D1%82";
assertEquals(encoded, encode(str, HOST, false));
}
@Test
public void encodesStringDoesNotRespectEncoded() {
String str = "to be%23or not to%20be";
assertEquals("to%20be%2523or%20not%20to%2520be", encode(str, PATH_SEGMENT, false));
}
@Test
public void encodesStringRespectEncoded() {
String str = "to be%23or not to%20be";
assertEquals("to%20be%23or%20not%20to%20be", recognizeEncode(str, PATH_SEGMENT, false));
}
@Test
public void decodesString() {
String str = "\u041f?\u0440#\u0438 \u0432\u0456\u0442";
String encoded = "%D0%9F%3F%D1%80%23%D0%B8%20%D0%B2%D1%96%D1%82";
assertEquals(str, decode(encoded, HOST));
}
@Test
public void parsesQueryString() {
String queryString = "q1=to%20be%20or%20not%20to%20be&q2=foo&q2=%D0%9F%D1%80%D0%B8%D0%B2%D1%96%D1%82";
MultivaluedMapImpl expected = new MultivaluedMapImpl();
expected.add("q1", "to%20be%20or%20not%20to%20be");
expected.add("q2", "foo");
expected.add("q2", "%D0%9F%D1%80%D0%B8%D0%B2%D1%96%D1%82");
MultivaluedMap<String, String> result = parseQueryString(queryString, false);
assertEquals(expected, result);
}
@Test
public void parsesAndDecodeQueryString() {
String queryString = "q1=to%20be%20or%20not%20to%20be&q2=foo&q2=%D0%9F%D1%80%D0%B8%D0%B2%D1%96%D1%82";
MultivaluedMapImpl expected = new MultivaluedMapImpl();
expected.add("q1", "to be or not to be");
expected.addAll("q2", "foo", "\u041f\u0440\u0438\u0432\u0456\u0442");
MultivaluedMap<String, String> result = parseQueryString(queryString, true);
assertEquals(expected, result);
}
@Test
public void parsesPathSegments() {
String path = "/to/be/or%20not/to/be;a=foo;b=b%20a%23r";
List<PathSegment> expected = newArrayList(PathSegmentImpl.fromString("to", false),
PathSegmentImpl.fromString("be", false),
PathSegmentImpl.fromString("or not", false),
PathSegmentImpl.fromString("to", false),
PathSegmentImpl.fromString("be;a=foo;b=b a#r", false)
);
List<PathSegment> result = parsePathSegments(path, true);
assertEquals(expected, result);
}
@Test
public void failsDecodeMalformedString() {
String wrongEncoded = "%D0%9g%3F%D1%80%23%D0%B8%20%D0%B2%D1%96%D1%82";
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage(String.format("Malformed string '%s' at index %d", wrongEncoded, 5));
decode(wrongEncoded, HOST);
}
@Test
public void failsDecodeUncompletedString() {
String wrongEncoded = "%D0%9F%3F%D1%80%23%D0%B8%20%D0%B2%D1%96%D1%8";
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage(String.format("Malformed string '%s' at index %d", wrongEncoded, 42));
decode(wrongEncoded, HOST);
}
@UseDataProvider("forNormalizesUri")
@Test
public void normalizesUri(String originUri, String normalizedUri) throws Exception {
assertEquals(normalizedUri, UriComponent.normalize(URI.create(originUri)).toString());
}
@DataProvider
public static Object[][] forNormalizesUri() {
return new Object[][]{
{"http://localhost:8080/servlet/../1//2/3/./../../4", "http://localhost:8080/1/4"},
{"http://localhost:8080/servlet/./1//2/3/./../../4", "http://localhost:8080/servlet/1/4"},
{"http://localhost:8080/servlet/1//2/3/./../../4", "http://localhost:8080/servlet/1/4"},
{"http://localhost:8080/servlet/1//2./3/./../4", "http://localhost:8080/servlet/1/2./4"},
{"http://localhost:8080/servlet/1//.2/3/./../4", "http://localhost:8080/servlet/1/.2/4"},
{"http://localhost:8080/servlet/1..//.2/3/./../4", "http://localhost:8080/servlet/1../.2/4"},
{"http://localhost:8080/servlet/./1//2/3/./../../4", "http://localhost:8080/servlet/1/4"},
{"http://localhost:8080/servlet/.", "http://localhost:8080/servlet/"},
{"http://localhost:8080/servlet/..", "http://localhost:8080/"},
{"http://localhost:8080/servlet/1", "http://localhost:8080/servlet/1"}
};
}
@Test
public void parsesQueryString_EVERREST_58() {
String str = "q1=bar&&q2=foo&q2=test";
MultivaluedMapImpl expected = new MultivaluedMapImpl();
expected.add("q1", "bar");
expected.addAll("q2", "foo", "test");
MultivaluedMap<String, String> result = parseQueryString(str, false);
assertEquals(expected, result);
result = parseQueryString(str, true);
assertEquals(expected, result);
}
@DataProvider
public static Object[][] forResolvesUri() {
return new Object[][] {
{URI.create("http://localhost:8080/1/2/3?4=5"), URI.create("?7=8"), URI.create("http://localhost:8080/1/2/3?7=8")},
{URI.create("http://localhost:8080/1/2/3?4=5"), URI.create(""), URI.create("http://localhost:8080/1/2/3?4=5")},
{URI.create("http://localhost:8080/1/2/3?4=5"), URI.create("x/y/z"), URI.create("http://localhost:8080/1/2/x/y/z")},
{URI.create("http://localhost:8080/1/2/3"), URI.create("?7=8"), URI.create("http://localhost:8080/1/2/3?7=8")},
{URI.create("http://localhost:8080/1/2/3"), URI.create("x/y/z"), URI.create("http://localhost:8080/1/2/x/y/z")}
};
}
@UseDataProvider("forResolvesUri")
@Test
public void resolvesUri(URI baseUri, URI resolvingUri, URI expectedResult) {
assertEquals(expectedResult, UriComponent.resolve(baseUri, resolvingUri));
}
}