blob: b9fd29837ae42d8706b292836cddc449daed6e55 [file] [log] [blame]
/*
* Copyright 2022 Google LLC
*
* Licensed 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 com.google.android.libraries.mobiledatadownload.file.common;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import android.net.Uri;
import com.google.thirdparty.robolectric.GoogleRobolectricTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(GoogleRobolectricTestRunner.class)
public final class FragmentTest {
@Test
public void builder_empty() throws Exception {
Fragment.Builder fragment = Fragment.builder();
assertThat(fragment.build().toString()).isEmpty();
}
@Test
public void parse_empty() throws Exception {
Fragment fragment = Fragment.parse("");
assertThat(fragment.toString()).isEmpty();
}
@Test
public void parse_simpleParam() throws Exception {
Fragment fragment = Fragment.parse("simple=true");
assertThat(fragment.toString()).isEqualTo("simple=true");
assertThat(fragment.params().get(0).key()).isEqualTo("simple");
}
@Test
public void builder() throws Exception {
Fragment fragment =
Fragment.builder()
.addParam(
Fragment.Param.builder("paramKey")
.addValue(
Fragment.ParamValue.builder("paramValue")
.addSubParam("subparamKey", "subparamValue")))
.build();
assertThat(fragment.toString()).isEqualTo("paramKey=paramValue(subparamKey=subparamValue)");
}
@Test
public void parse() throws Exception {
Fragment fragment = Fragment.parse("paramKey=paramValue(subparamKey=subparamValue)");
assertThat(fragment.toString()).isEqualTo("paramKey=paramValue(subparamKey=subparamValue)");
Fragment.Param param = fragment.params().get(0);
assertThat(param.key()).isEqualTo("paramKey");
Fragment.ParamValue value = param.values().get(0);
assertThat(value.name()).isEqualTo("paramValue");
Fragment.SubParam subparam = value.subParams().get(0);
assertThat(subparam.key()).isEqualTo("subparamKey");
assertThat(subparam.value()).isEqualTo("subparamValue");
}
@Test
public void parse_multipleParamsAndsubParams() throws Exception {
Fragment fragment = Fragment.parse("k1=v1&k2=v2(sk1=sv1)&k3=v3(sk1=sv1,sk2=sv2,sk3)");
assertThat(fragment.toString()).isEqualTo("k1=v1&k2=v2(sk1=sv1)&k3=v3(sk1=sv1,sk2=sv2,sk3)");
Fragment.Param p1 = fragment.params().get(0);
assertThat(p1.key()).isEqualTo("k1");
Fragment.ParamValue v1 = p1.values().get(0);
assertThat(v1.name()).isEqualTo("v1");
assertThat(v1.subParams().size()).isEqualTo(0);
Fragment.Param p2 = fragment.params().get(1);
assertThat(p2.key()).isEqualTo("k2");
Fragment.ParamValue v2 = p2.values().get(0);
assertThat(v2.name()).isEqualTo("v2");
assertThat(v2.subParams().size()).isEqualTo(1);
Fragment.SubParam p2s = v2.subParams().get(0);
assertThat(p2s.key()).isEqualTo("sk1");
assertThat(p2s.value()).isEqualTo("sv1");
Fragment.Param p3 = fragment.params().get(2);
assertThat(p3.key()).isEqualTo("k3");
Fragment.ParamValue v3 = p3.values().get(0);
assertThat(v3.name()).isEqualTo("v3");
assertThat(v3.subParams().size()).isEqualTo(3);
Fragment.SubParam p3s1 = v3.subParams().get(0);
assertThat(p3s1.key()).isEqualTo("sk1");
assertThat(p3s1.hasValue()).isTrue();
assertThat(p3s1.value()).isEqualTo("sv1");
Fragment.SubParam p3s2 = v3.subParams().get(1);
assertThat(p3s2.key()).isEqualTo("sk2");
assertThat(p3s2.hasValue()).isTrue();
assertThat(p3s2.value()).isEqualTo("sv2");
Fragment.SubParam p3s3 = v3.subParams().get(2);
assertThat(p3s3.key()).isEqualTo("sk3");
assertThat(p3s3.hasValue()).isFalse();
assertThat(p3s3.value()).isNull();
}
@Test
public void builder_multipleValues() throws Exception {
Fragment fragment =
Fragment.builder()
.addParam("unset")
.addParam(Fragment.Param.builder("k1").addValue("v1"))
.addParam(
Fragment.Param.builder("k2")
.addValue("v2")
.addValue("v2a")
.addValue(Fragment.ParamValue.builder("v2b").addSubParam("sk1", "sv1")))
.build();
assertThat(fragment.toString()).isEqualTo("k1=v1&k2=v2+v2a+v2b(sk1=sv1)");
}
@Test
public void builder_nestedMutation() throws Exception {
Fragment.Builder fragment = Fragment.parse("k0=v0a&k1=v1&k2=v2+v2a+v2b(sk1=sv1)").toBuilder();
fragment.findParam("k0").addValue("v0b");
fragment.findParam("k1").findValue("v1").addSubParam("sk1", "sv1");
fragment.findParam("k2").findValue("v2b").addSubParam("sk2", "sv2");
assertThat(fragment.build().toString())
.isEqualTo("k0=v0a+v0b&k1=v1(sk1=sv1)&k2=v2+v2a+v2b(sk1=sv1,sk2=sv2)");
}
@Test
public void parse_multipleValues() throws Exception {
Fragment fragment = Fragment.parse("k0=v0&k1=v1&k2=v2+v2a+v2b(sk1=sv1)");
Fragment.Param p0 = fragment.params().get(0);
assertThat(p0.key()).isEqualTo("k0");
Fragment.ParamValue v0 = p0.values().get(0);
assertThat(v0.name()).isEqualTo("v0");
assertThat(v0.subParams().isEmpty()).isTrue();
Fragment.Param p1 = fragment.params().get(1);
assertThat(p1.key()).isEqualTo("k1");
Fragment.ParamValue v1 = p1.values().get(0);
assertThat(v1.name()).isEqualTo("v1");
assertThat(v1.subParams().isEmpty()).isTrue();
Fragment.Param p2 = fragment.params().get(2);
assertThat(p2.key()).isEqualTo("k2");
Fragment.ParamValue v2 = p2.values().get(0);
assertThat(v2.name()).isEqualTo("v2");
assertThat(v2.subParams().isEmpty()).isTrue();
Fragment.ParamValue v2a = p2.values().get(1);
assertThat(v2a.name()).isEqualTo("v2a");
assertThat(v2a.subParams().isEmpty()).isTrue();
Fragment.ParamValue v2b = p2.values().get(2);
assertThat(v2b.name()).isEqualTo("v2b");
assertThat(v2b.subParams().size()).isEqualTo(1);
Fragment.SubParam v2bs1 = v2b.subParams().get(0);
assertThat(v2bs1.key()).isEqualTo("sk1");
assertThat(v2bs1.value()).isEqualTo("sv1");
}
@Test
public void parse_duplicateParams() throws Exception {
Fragment fragment = Fragment.parse("k=1&k=2");
assertThat(fragment.params().get(0).values().get(0).name()).isEqualTo("2");
}
@Test
public void parse_duplicateParamValues() throws Exception {
Fragment fragment = Fragment.parse("k=1+1(x=y)");
assertThat(fragment.params().get(0).values().get(0).findSubParamValue("x")).isEqualTo("y");
}
@Test
public void parse_duplicatesubParams() throws Exception {
Fragment fragment = Fragment.parse("k=1(x=y,x=z)");
assertThat(fragment.params().get(0).values().get(0).findSubParamValue("x")).isEqualTo("z");
}
@Test
public void parse_duplicateUnsetSubParams() throws Exception {
Fragment fragment = Fragment.parse("k=1(x=y,x)");
assertThat(fragment.params().get(0).values().get(0).findSubParam("x")).isNotNull();
assertThat(fragment.params().get(0).values().get(0).findSubParam("x").hasValue()).isFalse();
assertThat(fragment.params().get(0).values().get(0).findSubParamValue("x")).isNull();
}
@Test
public void parse_unsetSubParam() throws Exception {
Fragment fragment = Fragment.parse("p=v(sp1)");
assertThat(fragment.findParam("p").findValue("v").findSubParam("sp1")).isNotNull();
assertThat(fragment.findParam("p").findValue("v").findSubParam("sp1").hasValue()).isFalse();
assertThat(fragment.findParam("p").findValue("v").findSubParamValue("sp1")).isNull();
}
@Test
public void roundTrip() throws Exception {
Fragment fragment = Fragment.parse("a=b&c=d(e=f,g=h,i=j)+e+f");
assertThat(fragment.toString()).isEqualTo("a=b&c=d(e=f,g=h,i=j)+e+f");
}
@Test
public void parse_illegal() throws Exception {
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x"));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x="));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("="));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("=="));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("=x"));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y("));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y)"));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y()"));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y(=)"));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y(==)"));
assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y(=z)"));
}
@Test
public void parse_weirdButNotIllegal() throws Exception {
// Unencoded chars gets encoded
assertThat(Fragment.parse(" =y").toString()).isEqualTo("+=y");
assertThat(Fragment.parse(" x=y ").toString()).isEqualTo("+x=y+");
assertThat(Fragment.parse("()=y").toString()).isEqualTo("%28%29=y");
assertThat(Fragment.parse("x==y").toString()).isEqualTo("x=%3Dy");
assertThat(Fragment.parse("x=y(z==)").toString()).isEqualTo("x=y(z=%3D)");
assertThat(Fragment.parse("x=y(z=)").toString()).isEqualTo("x=y(z)");
assertThat(Fragment.parse("+=y").toString()).isEqualTo("+=y");
assertThat(Fragment.parse("").toString()).isEmpty();
assertThat(Fragment.parse((String) null).toString()).isEmpty();
}
@Test
public void build_escapingInvalidCharacters() throws Exception {
Fragment fragment =
Fragment.builder()
.addParam(
Fragment.Param.builder("m&m")
.addValue(Fragment.ParamValue.builder("2+2").addSubParam("k=", "(v)")))
.build();
assertThat(fragment.toString()).isEqualTo("m%26m=2%2B2(k%3D=%28v%29)");
Fragment roundtrip = Fragment.parse(fragment.toString());
Fragment.Param mnm = roundtrip.params().get(0);
assertThat(mnm.key()).isEqualTo("m&m");
Fragment.ParamValue twoptwo = mnm.values().get(0);
assertThat(twoptwo.name()).isEqualTo("2+2");
Fragment.SubParam pqp = twoptwo.subParams().get(0);
assertThat(pqp.key()).isEqualTo("k=");
assertThat(pqp.value()).isEqualTo("(v)");
}
@Test
public void toBuilder_shouldMakeDefensiveCopy() throws Exception {
Fragment fragment = Fragment.parse("a=b(c=d)");
Fragment.Builder fragmentBuilder = fragment.toBuilder();
assertThat(fragment.toString()).isEqualTo("a=b(c=d)");
assertThat(fragmentBuilder.build().toString()).isEqualTo("a=b(c=d)");
fragmentBuilder.addParam(Fragment.Param.builder("X").addValue("XX"));
fragmentBuilder.findParam("a").addValue("Y");
fragmentBuilder.findParam("a").findValue("b").addSubParam("Z", "ZZ");
assertThat(fragment.toString()).isEqualTo("a=b(c=d)");
assertThat(fragmentBuilder.build().toString()).isEqualTo("a=b(c=d,Z=ZZ)+Y&X=XX");
}
@Test
public void uri_withValidCharacters() throws Exception {
String encodedFragmentString = "a=b+c(d=e)";
Uri uri = Uri.parse("a://b/c").buildUpon().encodedFragment(encodedFragmentString).build();
assertThat(uri.toString()).isEqualTo("a://b/c#a=b+c(d=e)");
assertThat(uri.getEncodedFragment()).isEqualTo(encodedFragmentString);
Fragment roundtrip = Fragment.parse(uri);
Fragment.Param a = roundtrip.params().get(0);
assertThat(a.key()).isEqualTo("a");
Fragment.ParamValue b = a.values().get(0);
assertThat(b.name()).isEqualTo("b");
Fragment.ParamValue c = a.values().get(1);
assertThat(c.name()).isEqualTo("c");
Fragment.SubParam de = c.subParams().get(0);
assertThat(de.key()).isEqualTo("d");
assertThat(de.value()).isEqualTo("e");
}
@Test
public void uri_withInvalidCharacters() throws Exception {
String encodedFragmentString = "m%26m=2%2B2(k%3D=%28v%29)";
Uri uri = Uri.parse("a://b/c").buildUpon().encodedFragment(encodedFragmentString).build();
assertThat(uri.toString()).isEqualTo("a://b/c#m%26m=2%2B2(k%3D=%28v%29)");
assertThat(uri.getEncodedFragment()).isEqualTo(encodedFragmentString);
Fragment roundtrip = Fragment.parse(uri);
Fragment.Param mnm = roundtrip.params().get(0);
assertThat(mnm.key()).isEqualTo("m&m");
Fragment.ParamValue twoptwo = mnm.values().get(0);
assertThat(twoptwo.name()).isEqualTo("2+2");
Fragment.SubParam pqp = twoptwo.subParams().get(0);
assertThat(pqp.key()).isEqualTo("k=");
assertThat(pqp.value()).isEqualTo("(v)");
}
}