Clean up following #6016

Motivation:

* DefaultHeaders from netty-codec has some duplicated logic for header date parsing
* Several classes keep on using deprecated HttpHeaderDateFormat

Modifications:

* Move HttpHeaderDateFormatter to netty-codec and rename it into HeaderDateFormatter
* Make DefaultHeaders use HeaderDateFormatter
* Replace HttpHeaderDateFormat usage with HeaderDateFormatter

Result:

Faster and more consistent code
This commit is contained in:
Stephane Landelle 2016-11-21 21:29:44 +01:00 committed by Scott Mitchell
parent 930633350d
commit f755e58463
15 changed files with 170 additions and 265 deletions

View File

@ -18,13 +18,15 @@ package io.netty.handler.codec.http;
import static io.netty.handler.codec.http.CookieUtil.firstInvalidCookieNameOctet;
import static io.netty.handler.codec.http.CookieUtil.firstInvalidCookieValueOctet;
import static io.netty.handler.codec.http.CookieUtil.unwrapValue;
import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.http.cookie.CookieHeaderNames;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
@ -152,14 +154,10 @@ public final class CookieDecoder {
} else if (CookieHeaderNames.PATH.equalsIgnoreCase(name)) {
path = value;
} else if (CookieHeaderNames.EXPIRES.equalsIgnoreCase(name)) {
try {
long maxAgeMillis =
HttpHeaderDateFormat.get().parse(value).getTime() -
System.currentTimeMillis();
Date date = DateFormatter.parseHttpDate(value);
if (date != null) {
long maxAgeMillis = date.getTime() - System.currentTimeMillis();
maxAge = maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0? 1 : 0);
} catch (ParseException e) {
// Ignore.
}
} else if (CookieHeaderNames.MAX_AGE.equalsIgnoreCase(name)) {
maxAge = Integer.parseInt(value);

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.handler.codec.CharSequenceValueConverter;
import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.DefaultHeaders;
import io.netty.handler.codec.DefaultHeaders.NameValidator;
import io.netty.handler.codec.DefaultHeadersImpl;
@ -391,10 +392,10 @@ public class DefaultHttpHeaders extends HttpHeaders {
return (CharSequence) value;
}
if (value instanceof Date) {
return HttpHeaderDateFormat.get().format((Date) value);
return DateFormatter.format((Date) value);
}
if (value instanceof Calendar) {
return HttpHeaderDateFormat.get().format(((Calendar) value).getTime());
return DateFormatter.format(((Calendar) value).getTime());
}
return value.toString();
}

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.handler.codec.DateFormatter;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
@ -32,7 +33,7 @@ import java.util.TimeZone;
* <li>Sunday, 06-Nov-94 08:49:37 GMT: obsolete specification</li>
* <li>Sun Nov 6 08:49:37 1994: obsolete specification</li>
* </ul>
* @deprecated Use {@link HttpHeaderDateFormatter} instead
* @deprecated Use {@link DateFormatter} instead
*/
@Deprecated
public final class HttpHeaderDateFormat extends SimpleDateFormat {

View File

@ -17,6 +17,7 @@ package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.Headers;
import io.netty.util.AsciiString;
@ -839,7 +840,11 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
if (value == null) {
throw new ParseException("header not found: " + name, 0);
}
return HttpHeaderDateFormat.get().parse(value);
Date date = DateFormatter.parseHttpDate(value);
if (date == null) {
throw new ParseException("header can't be parsed into a Date: " + value, 0);
}
return date;
}
/**
@ -865,15 +870,8 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
@Deprecated
public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) {
final String value = getHeader(message, name);
if (value == null) {
return defaultValue;
}
try {
return HttpHeaderDateFormat.get().parse(value);
} catch (ParseException ignored) {
return defaultValue;
}
Date date = DateFormatter.parseHttpDate(value);
return date != null ? date : defaultValue;
}
/**
@ -897,7 +895,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
@Deprecated
public static void setDateHeader(HttpMessage message, CharSequence name, Date value) {
if (value != null) {
message.headers().set(name, HttpHeaderDateFormat.get().format(value));
message.headers().set(name, DateFormatter.format(value));
} else {
message.headers().set(name, null);
}

View File

@ -15,7 +15,7 @@
*/
package io.netty.handler.codec.http.cookie;
import io.netty.handler.codec.http.HttpHeaderDateFormatter;
import io.netty.handler.codec.DateFormatter;
import java.util.Date;
@ -168,7 +168,7 @@ public final class ClientCookieDecoder extends CookieDecoder {
if (maxAge != Long.MIN_VALUE) {
return maxAge;
} else if (isValueDefined(expiresStart, expiresEnd)) {
Date expiresDate = HttpHeaderDateFormatter.parse(header, expiresStart, expiresEnd);
Date expiresDate = DateFormatter.parseHttpDate(header, expiresStart, expiresEnd);
if (expiresDate != null) {
long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis();
return maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0);

View File

@ -21,7 +21,7 @@ import static io.netty.handler.codec.http.cookie.CookieUtil.stringBuilder;
import static io.netty.handler.codec.http.cookie.CookieUtil.stripTrailingSeparator;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import io.netty.handler.codec.http.HttpHeaderDateFormatter;
import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.http.HttpConstants;
import io.netty.handler.codec.http.HttpRequest;
@ -106,7 +106,7 @@ public final class ServerCookieEncoder extends CookieEncoder {
Date expires = new Date(cookie.maxAge() * 1000 + System.currentTimeMillis());
buf.append(CookieHeaderNames.EXPIRES);
buf.append((char) HttpConstants.EQUALS);
HttpHeaderDateFormatter.append(expires, buf);
DateFormatter.append(expires, buf);
buf.append((char) HttpConstants.SEMICOLON);
buf.append((char) HttpConstants.SP);
}

View File

@ -1,114 +0,0 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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 io.netty.handler.codec.http;
import org.junit.Test;
import java.util.Date;
import static org.junit.Assert.*;
import static io.netty.handler.codec.http.HttpHeaderDateFormatter.*;
public class HttpHeaderDateFormatterTest {
/**
* This date is set at "06 Nov 1994 08:49:37 GMT", from
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html">examples in RFC documentation</a>
*/
private static final long TIMESTAMP = 784111777000L;
private static final Date DATE = new Date(TIMESTAMP);
@Test
public void testParseWithSingleDigitDay() {
assertEquals(DATE, parse("Sun, 6 Nov 1994 08:49:37 GMT"));
}
@Test
public void testParseWithDoubleDigitDay() {
assertEquals(DATE, parse("Sun, 06 Nov 1994 08:49:37 GMT"));
}
@Test
public void testParseWithDashSeparatorSingleDigitDay() {
assertEquals(DATE, parse("Sunday, 06-Nov-94 08:49:37 GMT"));
}
@Test
public void testParseWithSingleDoubleDigitDay() {
assertEquals(DATE, parse("Sunday, 6-Nov-94 08:49:37 GMT"));
}
@Test
public void testParseWithoutGMT() {
assertEquals(DATE, parse("Sun Nov 6 08:49:37 1994"));
}
@Test
public void testParseWithFunkyTimezone() {
assertEquals(DATE, parse("Sun Nov 6 08:49:37 1994 -0000"));
}
@Test
public void testParseWithSingleDigitHourMinutesAndSecond() {
assertEquals(DATE, parse("Sunday, 6-Nov-94 8:49:37 GMT"));
}
@Test
public void testParseWithSingleDigitTime() {
assertEquals(DATE, parse("Sunday, 6 Nov 1994 8:49:37 GMT"));
Date _08_09_37 = new Date(TIMESTAMP - 40 * 60 * 1000);
assertEquals(_08_09_37, parse("Sunday, 6 Nov 1994 8:9:37 GMT"));
assertEquals(_08_09_37, parse("Sunday, 6 Nov 1994 8:09:37 GMT"));
Date _08_09_07 = new Date(TIMESTAMP - (40 * 60 + 30) * 1000);
assertEquals(_08_09_07, parse("Sunday, 6 Nov 1994 8:9:7 GMT"));
assertEquals(_08_09_07, parse("Sunday, 6 Nov 1994 8:9:07 GMT"));
}
@Test
public void testParseMidnight() {
assertEquals(new Date(784080000000L), parse("Sunday, 6 Nov 1994 00:00:00 GMT"));
}
@Test
public void testParseInvalidInput() {
// missing field
assertNull(parse("Sun, Nov 1994 08:49:37 GMT"));
assertNull(parse("Sun, 6 1994 08:49:37 GMT"));
assertNull(parse("Sun, 6 Nov 08:49:37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 :49:37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 49:37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 08::37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 08:37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 08:49: GMT"));
assertNull(parse("Sun, 6 Nov 1994 08:49 GMT"));
//invalid value
assertNull(parse("Sun, 6 FOO 1994 08:49:37 GMT"));
assertNull(parse("Sun, 36 Nov 1994 08:49:37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 28:49:37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 08:69:37 GMT"));
assertNull(parse("Sun, 6 Nov 1994 08:49:67 GMT"));
//wrong number of digits in timestamp
assertNull(parse("Sunday, 6 Nov 1994 0:0:000 GMT"));
assertNull(parse("Sunday, 6 Nov 1994 0:000:0 GMT"));
assertNull(parse("Sunday, 6 Nov 1994 000:0:0 GMT"));
}
@Test
public void testFormat() {
assertEquals("Sun, 6 Nov 1994 08:49:37 GMT", format(DATE));
}
}

View File

@ -15,7 +15,7 @@
*/
package io.netty.handler.codec.http.cookie;
import io.netty.handler.codec.http.HttpHeaderDateFormatter;
import io.netty.handler.codec.DateFormatter;
import org.junit.Test;
import java.util.ArrayList;
@ -30,26 +30,18 @@ import static org.junit.Assert.*;
public class ClientCookieDecoderTest {
@Test
public void testDecodingSingleCookieV0() {
String cookieString = "myCookie=myValue;expires=XXX;path=/apathsomewhere;domain=.adomainsomewhere;secure;";
cookieString = cookieString.replace("XXX",
HttpHeaderDateFormatter.format(new Date(System.currentTimeMillis() + 50000)));
String cookieString = "myCookie=myValue;expires="
+ DateFormatter.format(new Date(System.currentTimeMillis() + 50000))
+ ";path=/apathsomewhere;domain=.adomainsomewhere;secure;";
Cookie cookie = ClientCookieDecoder.STRICT.decode(cookieString);
assertNotNull(cookie);
assertEquals("myValue", cookie.value());
assertEquals(".adomainsomewhere", cookie.domain());
boolean fail = true;
for (int i = 40; i <= 60; i++) {
if (cookie.maxAge() == i) {
fail = false;
break;
}
}
if (fail) {
fail("expected: 50, actual: " + cookie.maxAge());
}
assertNotEquals("maxAge should be defined when parsing cookie " + cookieString,
Long.MIN_VALUE, cookie.maxAge());
assertTrue("maxAge should be about 50ms when parsing cookie " + cookieString,
cookie.maxAge() >= 40 && cookie.maxAge() <= 60);
assertEquals("/apathsomewhere", cookie.path());
assertTrue(cookie.isSecure());
}

View File

@ -17,9 +17,6 @@ package io.netty.handler.codec.http.cookie;
import org.junit.Test;
import io.netty.handler.codec.http.HttpHeaderDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
@ -29,9 +26,6 @@ public class ServerCookieDecoderTest {
@Test
public void testDecodingSingleCookie() {
String cookieString = "myCookie=myValue";
cookieString = cookieString.replace("XXX",
HttpHeaderDateFormat.get().format(new Date(System.currentTimeMillis() + 50000)));
Set<Cookie> cookies = ServerCookieDecoder.STRICT.decode(cookieString);
assertEquals(1, cookies.size());
Cookie cookie = cookies.iterator().next();

View File

@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import io.netty.handler.codec.http.HttpHeaderDateFormat;
import io.netty.handler.codec.DateFormatter;
import java.text.ParseException;
import java.util.ArrayList;
@ -51,7 +51,7 @@ public class ServerCookieEncoderTest {
Matcher matcher = Pattern.compile(result).matcher(encodedCookie);
assertTrue(matcher.find());
Date expiresDate = HttpHeaderDateFormat.get().parse(matcher.group(1));
Date expiresDate = DateFormatter.parseHttpDate(matcher.group(1));
long diff = (expiresDate.getTime() - System.currentTimeMillis()) / 1000;
// 2 secs should be fine
assertTrue(Math.abs(diff - maxAge) <= 2);

View File

@ -14,11 +14,11 @@
*/
package io.netty.handler.codec;
import io.netty.handler.codec.DefaultHeaders.HeaderDateFormat;
import io.netty.util.AsciiString;
import io.netty.util.internal.PlatformDependent;
import java.text.ParseException;
import java.util.Date;
/**
* Converts to/from native types, general {@link Object}, and {@link CharSequence}s.
@ -126,12 +126,12 @@ public class CharSequenceValueConverter implements ValueConverter<CharSequence>
@Override
public long convertToTimeMillis(CharSequence value) {
try {
return HeaderDateFormat.get().parse(value.toString());
} catch (ParseException e) {
PlatformDependent.throwException(e);
Date date = DateFormatter.parseHttpDate(value);
if (date == null) {
PlatformDependent.throwException(new ParseException("header can't be parsed into a Date: " + value, 0));
return 0;
}
return date.getTime();
}
@Override

View File

@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.handler.codec.http;
package io.netty.handler.codec;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
@ -43,7 +43,7 @@ import java.util.TimeZone;
* @see <a href="https://tools.ietf.org/html/rfc6265#section-5.1.1">RFC6265</a> for the parsing side
* @see <a href="https://tools.ietf.org/html/rfc1123#page-55">RFC1123</a> for the encoding side.
*/
public final class HttpHeaderDateFormatter {
public final class DateFormatter {
private static final BitSet DELIMITERS = new BitSet();
static {
@ -68,11 +68,11 @@ public final class HttpHeaderDateFormatter {
private static final String[] CALENDAR_MONTH_TO_SHORT_NAME =
new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
private static final FastThreadLocal<HttpHeaderDateFormatter> INSTANCES =
new FastThreadLocal<HttpHeaderDateFormatter>() {
private static final FastThreadLocal<DateFormatter> INSTANCES =
new FastThreadLocal<DateFormatter>() {
@Override
protected HttpHeaderDateFormatter initialValue() {
return new HttpHeaderDateFormatter();
protected DateFormatter initialValue() {
return new DateFormatter();
}
};
@ -81,8 +81,8 @@ public final class HttpHeaderDateFormatter {
* @param txt text to parse
* @return a {@link Date}, or null if text couldn't be parsed
*/
public static Date parse(CharSequence txt) {
return parse(txt, 0, txt.length());
public static Date parseHttpDate(CharSequence txt) {
return parseHttpDate(txt, 0, txt.length());
}
/**
@ -92,7 +92,7 @@ public final class HttpHeaderDateFormatter {
* @param end the end index inside <code>txt</code>
* @return a {@link Date}, or null if text couldn't be parsed
*/
public static Date parse(CharSequence txt, int start, int end) {
public static Date parseHttpDate(CharSequence txt, int start, int end) {
int length = end - start;
if (length == 0) {
return null;
@ -124,8 +124,8 @@ public final class HttpHeaderDateFormatter {
return formatter().append0(checkNotNull(date, "date"), checkNotNull(sb, "sb"));
}
private static HttpHeaderDateFormatter formatter() {
HttpHeaderDateFormatter formatter = INSTANCES.get();
private static DateFormatter formatter() {
DateFormatter formatter = INSTANCES.get();
formatter.reset();
return formatter;
}
@ -156,7 +156,7 @@ public final class HttpHeaderDateFormatter {
private boolean yearFound;
private int year;
private HttpHeaderDateFormatter() {
private DateFormatter() {
reset();
}
@ -171,7 +171,7 @@ public final class HttpHeaderDateFormatter {
month = -1;
yearFound = false;
year = -1;
cal.set(Calendar.MILLISECOND, 0);
cal.clear();
sb.setLength(0);
}

View File

@ -15,24 +15,17 @@
package io.netty.handler.codec;
import io.netty.util.HashingStrategy;
import io.netty.util.concurrent.FastThreadLocal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TimeZone;
import static io.netty.util.HashingStrategy.JAVA_HASHER;
import static io.netty.util.internal.MathUtil.findNextPositivePowerOfTwo;
@ -960,77 +953,6 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
return (T) this;
}
/**
* This {@link DateFormat} decodes 3 formats of {@link Date}.
*
* <ul>
* <li>Sun, 06 Nov 1994 08:49:37 GMT: standard specification, the only one with valid generation</li>
* <li>Sun, 06 Nov 1994 08:49:37 GMT: obsolete specification</li>
* <li>Sun Nov 6 08:49:37 1994: obsolete specification</li>
* </ul>
*/
public static final class HeaderDateFormat {
private static final FastThreadLocal<HeaderDateFormat> dateFormatThreadLocal =
new FastThreadLocal<HeaderDateFormat>() {
@Override
protected HeaderDateFormat initialValue() {
return new HeaderDateFormat();
}
};
static HeaderDateFormat get() {
return dateFormatThreadLocal.get();
}
/**
* Standard date format:
*
* <pre>
* Sun, 06 Nov 1994 08:49:37 GMT -> E, d MMM yyyy HH:mm:ss z
* </pre>
*/
private final DateFormat dateFormat1 = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
/**
* First obsolete format:
*
* <pre>
* Sunday, 06-Nov-94 08:49:37 GMT -> E, d-MMM-y HH:mm:ss z
* </pre>
*/
private final DateFormat dateFormat2 = new SimpleDateFormat("E, dd-MMM-yy HH:mm:ss z", Locale.ENGLISH);
/**
* Second obsolete format
*
* <pre>
* Sun Nov 6 08:49:37 1994 -> EEE, MMM d HH:mm:ss yyyy
* </pre>
*/
private final DateFormat dateFormat3 = new SimpleDateFormat("E MMM d HH:mm:ss yyyy", Locale.ENGLISH);
private HeaderDateFormat() {
TimeZone tz = TimeZone.getTimeZone("GMT");
dateFormat1.setTimeZone(tz);
dateFormat2.setTimeZone(tz);
dateFormat3.setTimeZone(tz);
}
long parse(String text) throws ParseException {
Date date = dateFormat1.parse(text);
if (date == null) {
date = dateFormat2.parse(text);
}
if (date == null) {
date = dateFormat3.parse(text);
}
if (date == null) {
throw new ParseException(text, 0);
}
return date.getTime();
}
}
private final class HeaderIterator implements Iterator<Map.Entry<K, V>> {
private HeaderEntry<K, V> current = head;

View File

@ -0,0 +1,114 @@
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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 io.netty.handler.codec;
import org.junit.Test;
import java.util.Date;
import static org.junit.Assert.*;
import static io.netty.handler.codec.DateFormatter.*;
public class DateFormatterTest {
/**
* This date is set at "06 Nov 1994 08:49:37 GMT", from
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html">examples in RFC documentation</a>
*/
private static final long TIMESTAMP = 784111777000L;
private static final Date DATE = new Date(TIMESTAMP);
@Test
public void testParseWithSingleDigitDay() {
assertEquals(DATE, parseHttpDate("Sun, 6 Nov 1994 08:49:37 GMT"));
}
@Test
public void testParseWithDoubleDigitDay() {
assertEquals(DATE, parseHttpDate("Sun, 06 Nov 1994 08:49:37 GMT"));
}
@Test
public void testParseWithDashSeparatorSingleDigitDay() {
assertEquals(DATE, parseHttpDate("Sunday, 06-Nov-94 08:49:37 GMT"));
}
@Test
public void testParseWithSingleDoubleDigitDay() {
assertEquals(DATE, parseHttpDate("Sunday, 6-Nov-94 08:49:37 GMT"));
}
@Test
public void testParseWithoutGMT() {
assertEquals(DATE, parseHttpDate("Sun Nov 6 08:49:37 1994"));
}
@Test
public void testParseWithFunkyTimezone() {
assertEquals(DATE, parseHttpDate("Sun Nov 6 08:49:37 1994 -0000"));
}
@Test
public void testParseWithSingleDigitHourMinutesAndSecond() {
assertEquals(DATE, parseHttpDate("Sunday, 6-Nov-94 8:49:37 GMT"));
}
@Test
public void testParseWithSingleDigitTime() {
assertEquals(DATE, parseHttpDate("Sunday, 6 Nov 1994 8:49:37 GMT"));
Date _08_09_37 = new Date(TIMESTAMP - 40 * 60 * 1000);
assertEquals(_08_09_37, parseHttpDate("Sunday, 6 Nov 1994 8:9:37 GMT"));
assertEquals(_08_09_37, parseHttpDate("Sunday, 6 Nov 1994 8:09:37 GMT"));
Date _08_09_07 = new Date(TIMESTAMP - (40 * 60 + 30) * 1000);
assertEquals(_08_09_07, parseHttpDate("Sunday, 6 Nov 1994 8:9:7 GMT"));
assertEquals(_08_09_07, parseHttpDate("Sunday, 6 Nov 1994 8:9:07 GMT"));
}
@Test
public void testParseMidnight() {
assertEquals(new Date(784080000000L), parseHttpDate("Sunday, 6 Nov 1994 00:00:00 GMT"));
}
@Test
public void testParseInvalidInput() {
// missing field
assertNull(parseHttpDate("Sun, Nov 1994 08:49:37 GMT"));
assertNull(parseHttpDate("Sun, 6 1994 08:49:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 08:49:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 :49:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 49:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 08::37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49: GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49 GMT"));
//invalid value
assertNull(parseHttpDate("Sun, 6 FOO 1994 08:49:37 GMT"));
assertNull(parseHttpDate("Sun, 36 Nov 1994 08:49:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 28:49:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:69:37 GMT"));
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49:67 GMT"));
//wrong number of digits in timestamp
assertNull(parseHttpDate("Sunday, 6 Nov 1994 0:0:000 GMT"));
assertNull(parseHttpDate("Sunday, 6 Nov 1994 0:000:0 GMT"));
assertNull(parseHttpDate("Sunday, 6 Nov 1994 000:0:0 GMT"));
}
@Test
public void testFormat() {
assertEquals("Sun, 6 Nov 1994 08:49:37 GMT", format(DATE));
}
}

View File

@ -13,10 +13,9 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.microbench.http;
package io.netty.handler.codec;
import io.netty.handler.codec.http.HttpHeaderDateFormat;
import io.netty.handler.codec.http.HttpHeaderDateFormatter;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;
@ -24,14 +23,14 @@ import java.util.Date;
import java.util.concurrent.TimeUnit;
@OutputTimeUnit(TimeUnit.SECONDS)
public class HttpHeaderDateFormatterBenchmark {
public class DateFormatterBenchmark {
private static final String DATE_STRING = "Sun, 27 Nov 2016 19:18:46 GMT";
private static final Date DATE = new Date(784111777000L);
@Benchmark
public Date parseHttpHeaderDateFormatter() {
return HttpHeaderDateFormatter.parse(DATE_STRING);
return DateFormatter.parseHttpDate(DATE_STRING);
}
@Benchmark
@ -41,7 +40,7 @@ public class HttpHeaderDateFormatterBenchmark {
@Benchmark
public String formatHttpHeaderDateFormatter() {
return HttpHeaderDateFormatter.format(DATE);
return DateFormatter.format(DATE);
}
@Benchmark