1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.libraries.mobiledatadownload.file.common; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static org.junit.Assert.assertThrows; 20 21 import android.net.Uri; 22 import com.google.thirdparty.robolectric.GoogleRobolectricTestRunner; 23 import org.junit.Test; 24 import org.junit.runner.RunWith; 25 26 @RunWith(GoogleRobolectricTestRunner.class) 27 public final class FragmentTest { 28 29 @Test builder_empty()30 public void builder_empty() throws Exception { 31 Fragment.Builder fragment = Fragment.builder(); 32 assertThat(fragment.build().toString()).isEmpty(); 33 } 34 35 @Test parse_empty()36 public void parse_empty() throws Exception { 37 Fragment fragment = Fragment.parse(""); 38 assertThat(fragment.toString()).isEmpty(); 39 } 40 41 @Test parse_simpleParam()42 public void parse_simpleParam() throws Exception { 43 Fragment fragment = Fragment.parse("simple=true"); 44 assertThat(fragment.toString()).isEqualTo("simple=true"); 45 assertThat(fragment.params().get(0).key()).isEqualTo("simple"); 46 } 47 48 @Test builder()49 public void builder() throws Exception { 50 Fragment fragment = 51 Fragment.builder() 52 .addParam( 53 Fragment.Param.builder("paramKey") 54 .addValue( 55 Fragment.ParamValue.builder("paramValue") 56 .addSubParam("subparamKey", "subparamValue"))) 57 .build(); 58 59 assertThat(fragment.toString()).isEqualTo("paramKey=paramValue(subparamKey=subparamValue)"); 60 } 61 62 @Test parse()63 public void parse() throws Exception { 64 Fragment fragment = Fragment.parse("paramKey=paramValue(subparamKey=subparamValue)"); 65 66 assertThat(fragment.toString()).isEqualTo("paramKey=paramValue(subparamKey=subparamValue)"); 67 68 Fragment.Param param = fragment.params().get(0); 69 assertThat(param.key()).isEqualTo("paramKey"); 70 Fragment.ParamValue value = param.values().get(0); 71 assertThat(value.name()).isEqualTo("paramValue"); 72 Fragment.SubParam subparam = value.subParams().get(0); 73 assertThat(subparam.key()).isEqualTo("subparamKey"); 74 assertThat(subparam.value()).isEqualTo("subparamValue"); 75 } 76 77 @Test parse_multipleParamsAndsubParams()78 public void parse_multipleParamsAndsubParams() throws Exception { 79 Fragment fragment = Fragment.parse("k1=v1&k2=v2(sk1=sv1)&k3=v3(sk1=sv1,sk2=sv2,sk3)"); 80 81 assertThat(fragment.toString()).isEqualTo("k1=v1&k2=v2(sk1=sv1)&k3=v3(sk1=sv1,sk2=sv2,sk3)"); 82 83 Fragment.Param p1 = fragment.params().get(0); 84 assertThat(p1.key()).isEqualTo("k1"); 85 Fragment.ParamValue v1 = p1.values().get(0); 86 assertThat(v1.name()).isEqualTo("v1"); 87 assertThat(v1.subParams().size()).isEqualTo(0); 88 89 Fragment.Param p2 = fragment.params().get(1); 90 assertThat(p2.key()).isEqualTo("k2"); 91 Fragment.ParamValue v2 = p2.values().get(0); 92 assertThat(v2.name()).isEqualTo("v2"); 93 assertThat(v2.subParams().size()).isEqualTo(1); 94 Fragment.SubParam p2s = v2.subParams().get(0); 95 assertThat(p2s.key()).isEqualTo("sk1"); 96 assertThat(p2s.value()).isEqualTo("sv1"); 97 98 Fragment.Param p3 = fragment.params().get(2); 99 assertThat(p3.key()).isEqualTo("k3"); 100 Fragment.ParamValue v3 = p3.values().get(0); 101 assertThat(v3.name()).isEqualTo("v3"); 102 assertThat(v3.subParams().size()).isEqualTo(3); 103 Fragment.SubParam p3s1 = v3.subParams().get(0); 104 assertThat(p3s1.key()).isEqualTo("sk1"); 105 assertThat(p3s1.hasValue()).isTrue(); 106 assertThat(p3s1.value()).isEqualTo("sv1"); 107 Fragment.SubParam p3s2 = v3.subParams().get(1); 108 assertThat(p3s2.key()).isEqualTo("sk2"); 109 assertThat(p3s2.hasValue()).isTrue(); 110 assertThat(p3s2.value()).isEqualTo("sv2"); 111 Fragment.SubParam p3s3 = v3.subParams().get(2); 112 assertThat(p3s3.key()).isEqualTo("sk3"); 113 assertThat(p3s3.hasValue()).isFalse(); 114 assertThat(p3s3.value()).isNull(); 115 } 116 117 @Test builder_multipleValues()118 public void builder_multipleValues() throws Exception { 119 Fragment fragment = 120 Fragment.builder() 121 .addParam("unset") 122 .addParam(Fragment.Param.builder("k1").addValue("v1")) 123 .addParam( 124 Fragment.Param.builder("k2") 125 .addValue("v2") 126 .addValue("v2a") 127 .addValue(Fragment.ParamValue.builder("v2b").addSubParam("sk1", "sv1"))) 128 .build(); 129 130 assertThat(fragment.toString()).isEqualTo("k1=v1&k2=v2+v2a+v2b(sk1=sv1)"); 131 } 132 133 @Test builder_nestedMutation()134 public void builder_nestedMutation() throws Exception { 135 Fragment.Builder fragment = Fragment.parse("k0=v0a&k1=v1&k2=v2+v2a+v2b(sk1=sv1)").toBuilder(); 136 137 fragment.findParam("k0").addValue("v0b"); 138 fragment.findParam("k1").findValue("v1").addSubParam("sk1", "sv1"); 139 fragment.findParam("k2").findValue("v2b").addSubParam("sk2", "sv2"); 140 141 assertThat(fragment.build().toString()) 142 .isEqualTo("k0=v0a+v0b&k1=v1(sk1=sv1)&k2=v2+v2a+v2b(sk1=sv1,sk2=sv2)"); 143 } 144 145 @Test parse_multipleValues()146 public void parse_multipleValues() throws Exception { 147 Fragment fragment = Fragment.parse("k0=v0&k1=v1&k2=v2+v2a+v2b(sk1=sv1)"); 148 149 Fragment.Param p0 = fragment.params().get(0); 150 assertThat(p0.key()).isEqualTo("k0"); 151 Fragment.ParamValue v0 = p0.values().get(0); 152 assertThat(v0.name()).isEqualTo("v0"); 153 assertThat(v0.subParams().isEmpty()).isTrue(); 154 155 Fragment.Param p1 = fragment.params().get(1); 156 assertThat(p1.key()).isEqualTo("k1"); 157 Fragment.ParamValue v1 = p1.values().get(0); 158 assertThat(v1.name()).isEqualTo("v1"); 159 assertThat(v1.subParams().isEmpty()).isTrue(); 160 161 Fragment.Param p2 = fragment.params().get(2); 162 assertThat(p2.key()).isEqualTo("k2"); 163 Fragment.ParamValue v2 = p2.values().get(0); 164 assertThat(v2.name()).isEqualTo("v2"); 165 assertThat(v2.subParams().isEmpty()).isTrue(); 166 167 Fragment.ParamValue v2a = p2.values().get(1); 168 assertThat(v2a.name()).isEqualTo("v2a"); 169 assertThat(v2a.subParams().isEmpty()).isTrue(); 170 171 Fragment.ParamValue v2b = p2.values().get(2); 172 assertThat(v2b.name()).isEqualTo("v2b"); 173 assertThat(v2b.subParams().size()).isEqualTo(1); 174 Fragment.SubParam v2bs1 = v2b.subParams().get(0); 175 assertThat(v2bs1.key()).isEqualTo("sk1"); 176 assertThat(v2bs1.value()).isEqualTo("sv1"); 177 } 178 179 @Test parse_duplicateParams()180 public void parse_duplicateParams() throws Exception { 181 Fragment fragment = Fragment.parse("k=1&k=2"); 182 assertThat(fragment.params().get(0).values().get(0).name()).isEqualTo("2"); 183 } 184 185 @Test parse_duplicateParamValues()186 public void parse_duplicateParamValues() throws Exception { 187 Fragment fragment = Fragment.parse("k=1+1(x=y)"); 188 assertThat(fragment.params().get(0).values().get(0).findSubParamValue("x")).isEqualTo("y"); 189 } 190 191 @Test parse_duplicatesubParams()192 public void parse_duplicatesubParams() throws Exception { 193 Fragment fragment = Fragment.parse("k=1(x=y,x=z)"); 194 assertThat(fragment.params().get(0).values().get(0).findSubParamValue("x")).isEqualTo("z"); 195 } 196 197 @Test parse_duplicateUnsetSubParams()198 public void parse_duplicateUnsetSubParams() throws Exception { 199 Fragment fragment = Fragment.parse("k=1(x=y,x)"); 200 assertThat(fragment.params().get(0).values().get(0).findSubParam("x")).isNotNull(); 201 assertThat(fragment.params().get(0).values().get(0).findSubParam("x").hasValue()).isFalse(); 202 assertThat(fragment.params().get(0).values().get(0).findSubParamValue("x")).isNull(); 203 } 204 205 @Test parse_unsetSubParam()206 public void parse_unsetSubParam() throws Exception { 207 Fragment fragment = Fragment.parse("p=v(sp1)"); 208 assertThat(fragment.findParam("p").findValue("v").findSubParam("sp1")).isNotNull(); 209 assertThat(fragment.findParam("p").findValue("v").findSubParam("sp1").hasValue()).isFalse(); 210 assertThat(fragment.findParam("p").findValue("v").findSubParamValue("sp1")).isNull(); 211 } 212 213 @Test roundTrip()214 public void roundTrip() throws Exception { 215 Fragment fragment = Fragment.parse("a=b&c=d(e=f,g=h,i=j)+e+f"); 216 217 assertThat(fragment.toString()).isEqualTo("a=b&c=d(e=f,g=h,i=j)+e+f"); 218 } 219 220 @Test parse_illegal()221 public void parse_illegal() throws Exception { 222 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x")); 223 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=")); 224 225 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("=")); 226 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("==")); 227 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("=x")); 228 229 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y(")); 230 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y)")); 231 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y()")); 232 233 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y(=)")); 234 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y(==)")); 235 assertThrows(IllegalArgumentException.class, () -> Fragment.parse("x=y(=z)")); 236 } 237 238 @Test parse_weirdButNotIllegal()239 public void parse_weirdButNotIllegal() throws Exception { 240 // Unencoded chars gets encoded 241 assertThat(Fragment.parse(" =y").toString()).isEqualTo("+=y"); 242 assertThat(Fragment.parse(" x=y ").toString()).isEqualTo("+x=y+"); 243 assertThat(Fragment.parse("()=y").toString()).isEqualTo("%28%29=y"); 244 assertThat(Fragment.parse("x==y").toString()).isEqualTo("x=%3Dy"); 245 assertThat(Fragment.parse("x=y(z==)").toString()).isEqualTo("x=y(z=%3D)"); 246 247 assertThat(Fragment.parse("x=y(z=)").toString()).isEqualTo("x=y(z)"); 248 assertThat(Fragment.parse("+=y").toString()).isEqualTo("+=y"); 249 assertThat(Fragment.parse("").toString()).isEmpty(); 250 assertThat(Fragment.parse((String) null).toString()).isEmpty(); 251 } 252 253 @Test build_escapingInvalidCharacters()254 public void build_escapingInvalidCharacters() throws Exception { 255 Fragment fragment = 256 Fragment.builder() 257 .addParam( 258 Fragment.Param.builder("m&m") 259 .addValue(Fragment.ParamValue.builder("2+2").addSubParam("k=", "(v)"))) 260 .build(); 261 assertThat(fragment.toString()).isEqualTo("m%26m=2%2B2(k%3D=%28v%29)"); 262 263 Fragment roundtrip = Fragment.parse(fragment.toString()); 264 Fragment.Param mnm = roundtrip.params().get(0); 265 assertThat(mnm.key()).isEqualTo("m&m"); 266 Fragment.ParamValue twoptwo = mnm.values().get(0); 267 assertThat(twoptwo.name()).isEqualTo("2+2"); 268 Fragment.SubParam pqp = twoptwo.subParams().get(0); 269 assertThat(pqp.key()).isEqualTo("k="); 270 assertThat(pqp.value()).isEqualTo("(v)"); 271 } 272 273 @Test toBuilder_shouldMakeDefensiveCopy()274 public void toBuilder_shouldMakeDefensiveCopy() throws Exception { 275 Fragment fragment = Fragment.parse("a=b(c=d)"); 276 Fragment.Builder fragmentBuilder = fragment.toBuilder(); 277 assertThat(fragment.toString()).isEqualTo("a=b(c=d)"); 278 assertThat(fragmentBuilder.build().toString()).isEqualTo("a=b(c=d)"); 279 280 fragmentBuilder.addParam(Fragment.Param.builder("X").addValue("XX")); 281 fragmentBuilder.findParam("a").addValue("Y"); 282 fragmentBuilder.findParam("a").findValue("b").addSubParam("Z", "ZZ"); 283 284 assertThat(fragment.toString()).isEqualTo("a=b(c=d)"); 285 assertThat(fragmentBuilder.build().toString()).isEqualTo("a=b(c=d,Z=ZZ)+Y&X=XX"); 286 } 287 288 @Test uri_withValidCharacters()289 public void uri_withValidCharacters() throws Exception { 290 String encodedFragmentString = "a=b+c(d=e)"; 291 Uri uri = Uri.parse("a://b/c").buildUpon().encodedFragment(encodedFragmentString).build(); 292 assertThat(uri.toString()).isEqualTo("a://b/c#a=b+c(d=e)"); 293 assertThat(uri.getEncodedFragment()).isEqualTo(encodedFragmentString); 294 Fragment roundtrip = Fragment.parse(uri); 295 Fragment.Param a = roundtrip.params().get(0); 296 assertThat(a.key()).isEqualTo("a"); 297 Fragment.ParamValue b = a.values().get(0); 298 assertThat(b.name()).isEqualTo("b"); 299 Fragment.ParamValue c = a.values().get(1); 300 assertThat(c.name()).isEqualTo("c"); 301 Fragment.SubParam de = c.subParams().get(0); 302 assertThat(de.key()).isEqualTo("d"); 303 assertThat(de.value()).isEqualTo("e"); 304 } 305 306 @Test uri_withInvalidCharacters()307 public void uri_withInvalidCharacters() throws Exception { 308 String encodedFragmentString = "m%26m=2%2B2(k%3D=%28v%29)"; 309 Uri uri = Uri.parse("a://b/c").buildUpon().encodedFragment(encodedFragmentString).build(); 310 assertThat(uri.toString()).isEqualTo("a://b/c#m%26m=2%2B2(k%3D=%28v%29)"); 311 assertThat(uri.getEncodedFragment()).isEqualTo(encodedFragmentString); 312 Fragment roundtrip = Fragment.parse(uri); 313 Fragment.Param mnm = roundtrip.params().get(0); 314 assertThat(mnm.key()).isEqualTo("m&m"); 315 Fragment.ParamValue twoptwo = mnm.values().get(0); 316 assertThat(twoptwo.name()).isEqualTo("2+2"); 317 Fragment.SubParam pqp = twoptwo.subParams().get(0); 318 assertThat(pqp.key()).isEqualTo("k="); 319 assertThat(pqp.value()).isEqualTo("(v)"); 320 } 321 } 322