View Javadoc
1   /*
2    * Copyright (C) 2011 The Guava Authors
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  
17  package com.google.common.net;
18  
19  import static com.google.common.base.Charsets.UTF_16;
20  import static com.google.common.base.Charsets.UTF_8;
21  import static com.google.common.net.MediaType.ANY_APPLICATION_TYPE;
22  import static com.google.common.net.MediaType.ANY_AUDIO_TYPE;
23  import static com.google.common.net.MediaType.ANY_IMAGE_TYPE;
24  import static com.google.common.net.MediaType.ANY_TEXT_TYPE;
25  import static com.google.common.net.MediaType.ANY_TYPE;
26  import static com.google.common.net.MediaType.ANY_VIDEO_TYPE;
27  import static com.google.common.net.MediaType.HTML_UTF_8;
28  import static com.google.common.net.MediaType.JPEG;
29  import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
30  import static java.lang.reflect.Modifier.isFinal;
31  import static java.lang.reflect.Modifier.isPublic;
32  import static java.lang.reflect.Modifier.isStatic;
33  import static java.util.Arrays.asList;
34  
35  import com.google.common.annotations.Beta;
36  import com.google.common.annotations.GwtCompatible;
37  import com.google.common.annotations.GwtIncompatible;
38  import com.google.common.base.Function;
39  import com.google.common.base.Optional;
40  import com.google.common.base.Predicate;
41  import com.google.common.base.Throwables;
42  import com.google.common.collect.FluentIterable;
43  import com.google.common.collect.ImmutableListMultimap;
44  import com.google.common.collect.ImmutableMultimap;
45  import com.google.common.testing.EqualsTester;
46  import com.google.common.testing.NullPointerTester;
47  
48  import junit.framework.TestCase;
49  
50  import java.lang.reflect.Field;
51  import java.nio.charset.Charset;
52  import java.nio.charset.IllegalCharsetNameException;
53  import java.nio.charset.UnsupportedCharsetException;
54  
55  /**
56   * Tests for {@link MediaType}.
57   *
58   * @author Gregory Kick
59   */
60  @Beta
61  @GwtCompatible(emulated = true)
62  public class MediaTypeTest extends TestCase {
63    @GwtIncompatible("reflection") public void testParse_useConstants() throws Exception {
64      for (MediaType constant : getConstants()) {
65        assertSame(constant, MediaType.parse(constant.toString()));
66      }
67    }
68  
69    @GwtIncompatible("reflection") public void testCreate_useConstants() throws Exception {
70      for (MediaType constant : getConstants()) {
71        assertSame(constant, MediaType.create(constant.type(), constant.subtype())
72            .withParameters(constant.parameters()));
73      }
74    }
75  
76    @GwtIncompatible("reflection") public void testConstants_charset() throws Exception {
77      for (Field field : getConstantFields()) {
78        Optional<Charset> charset = ((MediaType) field.get(null)).charset();
79        if (field.getName().endsWith("_UTF_8")) {
80          assertEquals(Optional.of(UTF_8), charset);
81        } else {
82          assertEquals(Optional.absent(), charset);
83        }
84      }
85    }
86  
87    @GwtIncompatible("reflection") private static FluentIterable<Field> getConstantFields() {
88      return FluentIterable.from(asList(MediaType.class.getDeclaredFields()))
89          .filter(new Predicate<Field>() {
90            @Override public boolean apply(Field input) {
91              int modifiers = input.getModifiers();
92              return isPublic(modifiers) && isStatic(modifiers) && isFinal(modifiers)
93                  && MediaType.class.equals(input.getType());
94            }
95          });
96    }
97  
98    @GwtIncompatible("reflection") private static FluentIterable<MediaType> getConstants() {
99      return getConstantFields()
100         .transform(new Function<Field, MediaType>() {
101           @Override public MediaType apply(Field input) {
102             try {
103               return (MediaType) input.get(null);
104             } catch (Exception e) {
105               throw Throwables.propagate(e);
106             }
107           }
108         });
109   }
110 
111   public void testCreate_invalidType() {
112     try {
113       MediaType.create("te><t", "plaintext");
114       fail();
115     } catch (IllegalArgumentException expected) {}
116   }
117 
118   public void testCreate_invalidSubtype() {
119     try {
120       MediaType.create("text", "pl@intext");
121       fail();
122     } catch (IllegalArgumentException expected) {}
123   }
124 
125   public void testCreate_wildcardTypeDeclaredSubtype() {
126     try {
127       MediaType.create("*", "text");
128       fail();
129     } catch (IllegalArgumentException expected) {}
130   }
131 
132   public void testCreateApplicationType() {
133     MediaType newType = MediaType.createApplicationType("yams");
134     assertEquals("application", newType.type());
135     assertEquals("yams", newType.subtype());
136   }
137 
138   public void testCreateAudioType() {
139     MediaType newType = MediaType.createAudioType("yams");
140     assertEquals("audio", newType.type());
141     assertEquals("yams", newType.subtype());
142   }
143 
144   public void testCreateImageType() {
145     MediaType newType = MediaType.createImageType("yams");
146     assertEquals("image", newType.type());
147     assertEquals("yams", newType.subtype());
148   }
149 
150   public void testCreateTextType() {
151     MediaType newType = MediaType.createTextType("yams");
152     assertEquals("text", newType.type());
153     assertEquals("yams", newType.subtype());
154   }
155 
156   public void testCreateVideoType() {
157     MediaType newType = MediaType.createVideoType("yams");
158     assertEquals("video", newType.type());
159     assertEquals("yams", newType.subtype());
160   }
161 
162   public void testGetType() {
163     assertEquals("text", MediaType.parse("text/plain").type());
164     assertEquals("application",
165         MediaType.parse("application/atom+xml; charset=utf-8").type());
166   }
167 
168   public void testGetSubtype() {
169     assertEquals("plain", MediaType.parse("text/plain").subtype());
170     assertEquals("atom+xml",
171         MediaType.parse("application/atom+xml; charset=utf-8").subtype());
172   }
173 
174   private static final ImmutableListMultimap<String, String> PARAMETERS =
175       ImmutableListMultimap.of("a", "1", "a", "2", "b", "3");
176 
177   public void testGetParameters() {
178     assertEquals(ImmutableListMultimap.of(), MediaType.parse("text/plain").parameters());
179     assertEquals(ImmutableListMultimap.of("charset", "utf-8"),
180         MediaType.parse("application/atom+xml; charset=utf-8").parameters());
181     assertEquals(PARAMETERS,
182         MediaType.parse("application/atom+xml; a=1; a=2; b=3").parameters());
183   }
184 
185   public void testWithoutParameters() {
186     assertSame(MediaType.parse("image/gif"),
187         MediaType.parse("image/gif").withoutParameters());
188     assertEquals(MediaType.parse("image/gif"),
189         MediaType.parse("image/gif; foo=bar").withoutParameters());
190   }
191 
192   public void testWithParameters() {
193     assertEquals(MediaType.parse("text/plain; a=1; a=2; b=3"),
194         MediaType.parse("text/plain").withParameters(PARAMETERS));
195     assertEquals(MediaType.parse("text/plain; a=1; a=2; b=3"),
196         MediaType.parse("text/plain; a=1; a=2; b=3").withParameters(PARAMETERS));
197   }
198 
199   public void testWithParameters_invalidAttribute() {
200     MediaType mediaType = MediaType.parse("text/plain");
201     ImmutableListMultimap<String, String> parameters =
202         ImmutableListMultimap.of("a", "1", "@", "2", "b", "3");
203     try {
204       mediaType.withParameters(parameters);
205       fail();
206     } catch (IllegalArgumentException expected) {}
207   }
208 
209   public void testWithParameter() {
210     assertEquals(MediaType.parse("text/plain; a=1"),
211         MediaType.parse("text/plain").withParameter("a", "1"));
212     assertEquals(MediaType.parse("text/plain; a=1"),
213         MediaType.parse("text/plain; a=1; a=2").withParameter("a", "1"));
214     assertEquals(MediaType.parse("text/plain; a=3"),
215         MediaType.parse("text/plain; a=1; a=2").withParameter("a", "3"));
216     assertEquals(MediaType.parse("text/plain; a=1; a=2; b=3"),
217         MediaType.parse("text/plain; a=1; a=2").withParameter("b", "3"));
218   }
219 
220   public void testWithParameter_invalidAttribute() {
221     MediaType mediaType = MediaType.parse("text/plain");
222     try {
223       mediaType.withParameter("@", "2");
224       fail();
225     } catch (IllegalArgumentException expected) {}
226   }
227 
228   public void testWithCharset() {
229     assertEquals(MediaType.parse("text/plain; charset=utf-8"),
230         MediaType.parse("text/plain").withCharset(UTF_8));
231     assertEquals(MediaType.parse("text/plain; charset=utf-8"),
232         MediaType.parse("text/plain; charset=utf-16").withCharset(UTF_8));
233   }
234 
235   public void testHasWildcard() {
236     assertFalse(PLAIN_TEXT_UTF_8.hasWildcard());
237     assertFalse(JPEG.hasWildcard());
238     assertTrue(ANY_TYPE.hasWildcard());
239     assertTrue(ANY_APPLICATION_TYPE.hasWildcard());
240     assertTrue(ANY_AUDIO_TYPE.hasWildcard());
241     assertTrue(ANY_IMAGE_TYPE.hasWildcard());
242     assertTrue(ANY_TEXT_TYPE.hasWildcard());
243     assertTrue(ANY_VIDEO_TYPE.hasWildcard());
244   }
245 
246   public void testIs() {
247     assertTrue(PLAIN_TEXT_UTF_8.is(ANY_TYPE));
248     assertTrue(JPEG.is(ANY_TYPE));
249     assertTrue(ANY_TEXT_TYPE.is(ANY_TYPE));
250     assertTrue(PLAIN_TEXT_UTF_8.is(ANY_TEXT_TYPE));
251     assertTrue(PLAIN_TEXT_UTF_8.withoutParameters().is(ANY_TEXT_TYPE));
252     assertFalse(JPEG.is(ANY_TEXT_TYPE));
253     assertTrue(PLAIN_TEXT_UTF_8.is(PLAIN_TEXT_UTF_8));
254     assertTrue(PLAIN_TEXT_UTF_8.is(PLAIN_TEXT_UTF_8.withoutParameters()));
255     assertFalse(PLAIN_TEXT_UTF_8.withoutParameters().is(PLAIN_TEXT_UTF_8));
256     assertFalse(PLAIN_TEXT_UTF_8.is(HTML_UTF_8));
257     assertFalse(PLAIN_TEXT_UTF_8.withParameter("charset", "UTF-16").is(PLAIN_TEXT_UTF_8));
258     assertFalse(PLAIN_TEXT_UTF_8.is(PLAIN_TEXT_UTF_8.withParameter("charset", "UTF-16")));
259   }
260 
261   public void testParse_empty() {
262     try {
263       MediaType.parse("");
264       fail();
265     } catch (IllegalArgumentException expected) {}
266   }
267 
268   public void testParse_badInput() {
269     try {
270       MediaType.parse("/");
271       fail();
272     } catch (IllegalArgumentException expected) {}
273     try {
274       MediaType.parse("text");
275       fail();
276     } catch (IllegalArgumentException expected) {}
277     try {
278       MediaType.parse("text/");
279       fail();
280     } catch (IllegalArgumentException expected) {}
281     try {
282       MediaType.parse("te<t/plain");
283       fail();
284     } catch (IllegalArgumentException expected) {}
285     try {
286       MediaType.parse("text/pl@in");
287       fail();
288     } catch (IllegalArgumentException expected) {}
289     try {
290       MediaType.parse("text/plain;");
291       fail();
292     } catch (IllegalArgumentException expected) {}
293     try {
294       MediaType.parse("text/plain; ");
295       fail();
296     } catch (IllegalArgumentException expected) {}
297     try {
298       MediaType.parse("text/plain; a");
299       fail();
300     } catch (IllegalArgumentException expected) {}
301     try {
302       MediaType.parse("text/plain; a=");
303       fail();
304     } catch (IllegalArgumentException expected) {}
305     try {
306       MediaType.parse("text/plain; a=@");
307       fail();
308     } catch (IllegalArgumentException expected) {}
309     try {
310       MediaType.parse("text/plain; a=\"@");
311       fail();
312     } catch (IllegalArgumentException expected) {}
313     try {
314       MediaType.parse("text/plain; a=1;");
315       fail();
316     } catch (IllegalArgumentException expected) {}
317     try {
318       MediaType.parse("text/plain; a=1; ");
319       fail();
320     } catch (IllegalArgumentException expected) {}
321     try {
322       MediaType.parse("text/plain; a=1; b");
323       fail();
324     } catch (IllegalArgumentException expected) {}
325     try {
326       MediaType.parse("text/plain; a=1; b=");
327       fail();
328     } catch (IllegalArgumentException expected) {}
329     try {
330       MediaType.parse("text/plain; a=\u2025");
331       fail();
332     } catch (IllegalArgumentException expected) {}
333   }
334 
335   public void testGetCharset() {
336     assertEquals(Optional.absent(), MediaType.parse("text/plain").charset());
337     assertEquals(Optional.of(UTF_8),
338         MediaType.parse("text/plain; charset=utf-8").charset());
339   }
340 
341   @GwtIncompatible("Non-UTF-8 Charset") public void testGetCharset_utf16() {
342     assertEquals(Optional.of(UTF_16),
343         MediaType.parse("text/plain; charset=utf-16").charset());
344   }
345 
346   public void testGetCharset_tooMany() {
347     MediaType mediaType = MediaType.parse("text/plain; charset=utf-8; charset=utf-16");
348     try {
349       mediaType.charset();
350       fail();
351     } catch (IllegalStateException expected) {}
352   }
353 
354   public void testGetCharset_illegalCharset() {
355     MediaType mediaType = MediaType.parse(
356         "text/plain; charset=\"!@#$%^&*()\"");
357     try {
358       mediaType.charset();
359       fail();
360     } catch (IllegalCharsetNameException expected) {}
361   }
362 
363   public void testGetCharset_unsupportedCharset() {
364     MediaType mediaType = MediaType.parse(
365         "text/plain; charset=utf-wtf");
366     try {
367       mediaType.charset();
368       fail();
369     } catch (UnsupportedCharsetException expected) {}
370   }
371 
372   public void testEquals() {
373     new EqualsTester()
374         .addEqualityGroup(MediaType.create("text", "plain"),
375             MediaType.create("TEXT", "PLAIN"),
376             MediaType.parse("text/plain"),
377             MediaType.parse("TEXT/PLAIN"),
378             MediaType.create("text", "plain").withParameter("a", "1").withoutParameters())
379         .addEqualityGroup(
380             MediaType.create("text", "plain").withCharset(UTF_8),
381             MediaType.create("text", "plain").withParameter("CHARSET", "UTF-8"),
382             MediaType.create("text", "plain").withParameters(
383                 ImmutableMultimap.of("charset", "utf-8")),
384             MediaType.parse("text/plain;charset=utf-8"),
385             MediaType.parse("text/plain; charset=utf-8"),
386             MediaType.parse("text/plain;  charset=utf-8"),
387             MediaType.parse("text/plain; \tcharset=utf-8"),
388             MediaType.parse("text/plain; \r\n\tcharset=utf-8"),
389             MediaType.parse("text/plain; CHARSET=utf-8"),
390             MediaType.parse("text/plain; charset=\"utf-8\""),
391             MediaType.parse("text/plain; charset=\"\\u\\tf-\\8\""),
392             MediaType.parse("text/plain; charset=UTF-8"))
393         .addEqualityGroup(MediaType.parse("text/plain; charset=utf-8; charset=utf-8"))
394         .addEqualityGroup(MediaType.create("text", "plain").withParameter("a", "value"),
395             MediaType.create("text", "plain").withParameter("A", "value"))
396         .addEqualityGroup(MediaType.create("text", "plain").withParameter("a", "VALUE"),
397             MediaType.create("text", "plain").withParameter("A", "VALUE"))
398         .addEqualityGroup(
399             MediaType.create("text", "plain")
400                 .withParameters(ImmutableListMultimap.of("a", "1", "a", "2")),
401             MediaType.create("text", "plain")
402                 .withParameters(ImmutableListMultimap.of("a", "2", "a", "1")))
403         .addEqualityGroup(MediaType.create("text", "csv"))
404         .addEqualityGroup(MediaType.create("application", "atom+xml"))
405         .testEquals();
406   }
407 
408   @GwtIncompatible("Non-UTF-8 Charset") public void testEquals_nonUtf8Charsets() {
409     new EqualsTester()
410         .addEqualityGroup(MediaType.create("text", "plain"))
411         .addEqualityGroup(MediaType.create("text", "plain").withCharset(UTF_8))
412         .addEqualityGroup(MediaType.create("text", "plain").withCharset(UTF_16))
413         .testEquals();
414   }
415 
416   @GwtIncompatible("com.google.common.testing.NullPointerTester")
417   public void testNullPointer() {
418     NullPointerTester tester = new NullPointerTester();
419     tester.testAllPublicConstructors(MediaType.class);
420     tester.testAllPublicStaticMethods(MediaType.class);
421     tester.testAllPublicInstanceMethods(MediaType.parse("text/plain"));
422   }
423 
424   public void testToString() {
425     assertEquals("text/plain", MediaType.create("text", "plain").toString());
426     assertEquals("text/plain; something=\"cr@zy\"; something-else=\"crazy with spaces\"",
427         MediaType.create("text", "plain")
428             .withParameter("something", "cr@zy")
429             .withParameter("something-else", "crazy with spaces")
430             .toString());
431   }
432 }