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 com.google.common.base.Ascii; 20 import com.google.common.base.Joiner; 21 import com.google.common.base.Splitter; 22 import com.google.common.collect.ImmutableBiMap; 23 import com.google.common.collect.ImmutableSet; 24 import com.google.common.collect.Lists; 25 import java.lang.reflect.Field; 26 import java.util.List; 27 import junit.framework.TestCase; 28 29 /** 30 * Tests for the HttpHeaders class. 31 * 32 * @author Kurt Alfred Kluever 33 */ 34 public class HttpHeadersTest extends TestCase { 35 testConstantNameMatchesString()36 public void testConstantNameMatchesString() throws Exception { 37 // Special case some of the weird HTTP Header names... 38 ImmutableBiMap<String, String> specialCases = 39 ImmutableBiMap.<String, String>builder() 40 .put("CDN_LOOP", "CDN-Loop") 41 .put("ETAG", "ETag") 42 .put("SOURCE_MAP", "SourceMap") 43 .put("SEC_CH_UA_WOW64", "Sec-CH-UA-WoW64") 44 .put("SEC_WEBSOCKET_ACCEPT", "Sec-WebSocket-Accept") 45 .put("SEC_WEBSOCKET_EXTENSIONS", "Sec-WebSocket-Extensions") 46 .put("SEC_WEBSOCKET_KEY", "Sec-WebSocket-Key") 47 .put("SEC_WEBSOCKET_PROTOCOL", "Sec-WebSocket-Protocol") 48 .put("SEC_WEBSOCKET_VERSION", "Sec-WebSocket-Version") 49 .put("X_WEBKIT_CSP", "X-WebKit-CSP") 50 .put("X_WEBKIT_CSP_REPORT_ONLY", "X-WebKit-CSP-Report-Only") 51 .buildOrThrow(); 52 ImmutableSet<String> uppercaseAcronyms = 53 ImmutableSet.of( 54 "CH", "ID", "DNT", "DNS", "DPR", "ECT", "GPC", "HTTP2", "IP", "MD5", "P3P", "RTT", "TE", 55 "UA", "UID", "URL", "WWW", "XSS"); 56 assertConstantNameMatchesString(HttpHeaders.class, specialCases, uppercaseAcronyms); 57 } 58 59 // Visible for other tests to use assertConstantNameMatchesString( Class<?> clazz, ImmutableBiMap<String, String> specialCases, ImmutableSet<String> uppercaseAcronyms)60 static void assertConstantNameMatchesString( 61 Class<?> clazz, 62 ImmutableBiMap<String, String> specialCases, 63 ImmutableSet<String> uppercaseAcronyms) 64 throws IllegalAccessException { 65 for (Field field : relevantFields(clazz)) { 66 assertEquals( 67 upperToHttpHeaderName(field.getName(), specialCases, uppercaseAcronyms), field.get(null)); 68 } 69 } 70 71 // Visible for other tests to use relevantFields(Class<?> cls)72 static ImmutableSet<Field> relevantFields(Class<?> cls) { 73 ImmutableSet.Builder<Field> builder = ImmutableSet.builder(); 74 for (Field field : cls.getDeclaredFields()) { 75 /* 76 * Coverage mode generates synthetic fields. If we ever add private 77 * fields, they will cause similar problems, and we may want to switch 78 * this check to isAccessible(). 79 */ 80 if (!field.isSynthetic() && field.getType() == String.class) { 81 builder.add(field); 82 } 83 } 84 return builder.build(); 85 } 86 87 private static final Splitter SPLITTER = Splitter.on('_'); 88 private static final Joiner JOINER = Joiner.on('-'); 89 upperToHttpHeaderName( String constantName, ImmutableBiMap<String, String> specialCases, ImmutableSet<String> uppercaseAcronyms)90 private static String upperToHttpHeaderName( 91 String constantName, 92 ImmutableBiMap<String, String> specialCases, 93 ImmutableSet<String> uppercaseAcronyms) { 94 if (specialCases.containsKey(constantName)) { 95 return specialCases.get(constantName); 96 } 97 List<String> parts = Lists.newArrayList(); 98 for (String part : SPLITTER.split(constantName)) { 99 if (!uppercaseAcronyms.contains(part)) { 100 part = part.charAt(0) + Ascii.toLowerCase(part.substring(1)); 101 } 102 parts.add(part); 103 } 104 return JOINER.join(parts); 105 } 106 } 107