You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by zm...@apache.org on 2015/08/25 20:19:21 UTC
[07/37] aurora git commit: Import of Twitter Commons.
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/logging/RootLogConfigTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/logging/RootLogConfigTest.java b/commons/src/test/java/com/twitter/common/logging/RootLogConfigTest.java
new file mode 100644
index 0000000..b47a2cd
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/logging/RootLogConfigTest.java
@@ -0,0 +1,320 @@
+package com.twitter.common.logging;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Franco Callari
+ * @author Keith Tsui.
+ */
+public class RootLogConfigTest {
+ private static class FakeHandler extends Handler {
+ boolean hasPublished = false;
+ FakeHandler() { reset(); }
+ void reset() { hasPublished = false; }
+ public void publish(LogRecord record) { hasPublished = true; }
+ public void flush() {}
+ public void close() throws SecurityException {}
+ }
+
+ // Dummy classes used by the tests for --vmodule.
+ private static class ClassA {
+ static Logger logger = Logger.getLogger(ClassA.class.getName());
+ }
+
+ private static class ClassB {
+ static Logger logger = Logger.getLogger(ClassB.class.getName());
+ }
+
+ private ByteArrayOutputStream fakeErrorLog;
+ private PrintStream errPrintStream;
+ Logger fakeRootLogger, testLogger;
+ FakeHandler fakeFileLog;
+ ConsoleHandler consoleHandler;
+
+ private void assertHasLoggedToStderr() {
+ errPrintStream.flush();
+ assertTrue(fakeErrorLog.size() > 0);
+ }
+
+ private void assertHasNotLoggedToStderr() {
+ errPrintStream.flush();
+ assertEquals(fakeErrorLog.size(), 0);
+ }
+
+ private void assertHasLoggedToFile() {
+ assertTrue(fakeFileLog.hasPublished);
+ }
+
+ private void assertHasNotLoggedToFile() {
+ assertFalse(fakeFileLog.hasPublished);
+ }
+
+ // Passes if logger log at least at the given level, directing to stderr.
+ private void assertErrorLogAtLevel(Logger logger, Level level) {
+ List<Level> levels = Arrays.asList(
+ Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG,
+ Level.FINE, Level.FINER, Level.FINEST);
+ for (Level l : levels) {
+ logger.log(l, "Message");
+ if (level.intValue() <= l.intValue()) {
+ assertHasLoggedToStderr();
+ } else {
+ assertHasNotLoggedToStderr();
+ }
+ resetLogs();
+ }
+ }
+
+ // Passes if logger does not allow verbose logging.
+ private void assertNoVerboseLogging(Logger logger) {
+ logger.config("Config");
+ logger.fine("Fine");
+ logger.finer("Finer");
+ logger.finest("Finest");
+ assertHasNotLoggedToStderr();
+ assertHasNotLoggedToFile();
+ }
+
+ private void resetLogs() {
+ errPrintStream.flush();
+ fakeErrorLog.reset();
+ fakeFileLog.reset();
+ }
+
+ // The following two methods are used to inject our fake root logger, so to avoid test flakyness
+ // due to background threads.
+ private RootLogConfig.Builder getConfig() {
+ return RootLogConfig.builder().rootLoggerName(fakeRootLogger.getName());
+ }
+
+ private void setFakeRootForLogger(Logger logger) {
+ Preconditions.checkArgument(logger != fakeRootLogger);
+ logger.setUseParentHandlers(true);
+ logger.setParent(fakeRootLogger);
+ }
+
+ @Before
+ public void setUp() {
+ // Intercept stderr (this must be done first).
+ fakeErrorLog = new ByteArrayOutputStream();
+ errPrintStream = new PrintStream(fakeErrorLog);
+ System.setErr(errPrintStream);
+
+ // Create other members
+ consoleHandler = new ConsoleHandler();
+ fakeFileLog = new FakeHandler();
+
+ // Emulate default setup (just a console handler), but avoiding the use
+ // of the global root logger so not to get a flaky test due to background threads.
+ fakeRootLogger = Logger.getLogger("FakeRoot-" + UUID.randomUUID().toString());
+ fakeRootLogger.setUseParentHandlers(false);
+ for (Handler h : fakeRootLogger.getHandlers()) {
+ fakeRootLogger.removeHandler(h);
+ }
+ fakeRootLogger.addHandler(consoleHandler);
+
+ testLogger = Logger.getLogger(RootLogConfigTest.class.getName());
+ testLogger.setUseParentHandlers(true);
+ testLogger.setParent(fakeRootLogger);
+
+ setFakeRootForLogger(ClassA.logger);
+ setFakeRootForLogger(ClassB.logger);
+
+ resetLogs();
+ }
+
+ @Test
+ public void testDefaultConfig() {
+ // Verify that default info, warning, severe logging goes to stderr, no logging below info.
+ assertErrorLogAtLevel(testLogger, Level.INFO);
+ resetLogs();
+ assertNoVerboseLogging(testLogger);
+ }
+
+ @Test
+ public void testLogToStderr() {
+ // Add a fake handler, verify that it works along with the console.
+ fakeRootLogger.addHandler(fakeFileLog);
+ testLogger.info("Info");
+ assertHasLoggedToStderr();
+ assertHasLoggedToFile();
+
+ // Configure logtostderr
+ getConfig().logToStderr(true).build().apply();
+ resetLogs();
+
+ // Verify that severe, warning, info logs go to stderr only.
+ testLogger.severe("Severe");
+ assertHasLoggedToStderr();
+ assertHasNotLoggedToFile();
+ resetLogs();
+ testLogger.warning("Warning");
+ assertHasLoggedToStderr();
+ assertHasNotLoggedToFile();
+ resetLogs();
+ testLogger.info("Info");
+ assertHasLoggedToStderr();
+ assertHasNotLoggedToFile();
+ resetLogs();
+
+ assertNoVerboseLogging(testLogger);
+ }
+
+ @Test
+ public void testAlsoLogToStderr() {
+ // Add a fake handler, remove console handler, verify that it works.
+ fakeRootLogger.removeHandler(consoleHandler);
+ fakeRootLogger.addHandler(fakeFileLog);
+ testLogger.info("Info");
+ assertHasNotLoggedToStderr();
+ assertHasLoggedToFile();
+ resetLogs();
+
+ // Configure alsologtostderr
+ getConfig().alsoLogToStderr(true).build().apply();
+ resetLogs();
+
+ // Verify that severe, warning, info logs go to both.
+ testLogger.severe("Severe");
+ assertHasLoggedToStderr();
+ assertHasLoggedToFile();
+ resetLogs();
+ testLogger.warning("Warning");
+ assertHasLoggedToStderr();
+ assertHasLoggedToFile();
+ resetLogs();
+ testLogger.info("Info");
+ assertHasLoggedToStderr();
+ assertHasLoggedToFile();
+ resetLogs();
+
+ assertNoVerboseLogging(testLogger);
+ }
+
+ @Test
+ public void testLogToStderrOverridesAlsoLogToStderr() {
+ // Add a fake handler, remove console handler, verify that it works.
+ fakeRootLogger.removeHandler(consoleHandler);
+ fakeRootLogger.addHandler(fakeFileLog);
+ testLogger.info("Info");
+ assertHasNotLoggedToStderr();
+ assertHasLoggedToFile();
+
+ // Configure with logtostderr AND alsologtostderr
+ getConfig().logToStderr(true).alsoLogToStderr(true).build().apply();
+ resetLogs();
+
+ // Verify that severe, warning, info logs go to stderr only.
+ testLogger.severe("Severe");
+ assertHasLoggedToStderr();
+ assertHasNotLoggedToFile();
+ resetLogs();
+ testLogger.warning("Warning");
+ assertHasLoggedToStderr();
+ assertHasNotLoggedToFile();
+ resetLogs();
+ testLogger.info("Info");
+ assertHasLoggedToStderr();
+ assertHasNotLoggedToFile();
+ resetLogs();
+
+ assertNoVerboseLogging(testLogger);
+ }
+
+ @Test
+ public void testUseGLogFormatter() {
+ // Configure glogformatter. We test in "logtostderr" mode so to verify correct formatting
+ // for both handlers.
+ getConfig().logToStderr(true).useGLogFormatter(true).build().apply();
+ resetLogs();
+
+ testLogger.severe("Severe Log Message");
+ assertHasLoggedToStderr();
+ String output = fakeErrorLog.toString();
+ // Verify that it is all in one line and chope the \n.
+ assertTrue(output.split("\n").length == 1);
+ assertTrue(output.endsWith("\n"));
+ output = output.replaceAll("\n", "");
+
+ // Verify that it is on glog format.
+ assertTrue("Unexpected output: " + output,
+ output.matches("E\\d+ " // Level, month, day.
+ + "\\d\\d:\\d\\d:\\d\\d\\.\\d+ " // Timestamp.
+ + "THREAD\\d+ " // Thread id.
+ + RootLogConfigTest.class.getName() + "\\.testUseGLogFormatter: " // Class name.
+ + "Severe Log Message" // Message.
+ ));
+ }
+
+ @Test
+ public void testVlog() {
+ // Configure with logtoStderr and vlog==FINE;
+ getConfig().logToStderr(true).vlog(RootLogConfig.LogLevel.FINE).build().apply();
+ resetLogs();
+
+ // Verify logging at levels fine and above.
+ assertErrorLogAtLevel(testLogger, Level.FINE);
+ }
+
+ @Test
+ public void testVModule() {
+ // Configure with ClassA using FINE and ClassB using WARNING;
+ Map<Class<?>, RootLogConfig.LogLevel> vmoduleMap =
+ ImmutableMap.of(ClassA.class, RootLogConfig.LogLevel.FINE,
+ ClassB.class, RootLogConfig.LogLevel.WARNING);
+ getConfig().logToStderr(true).vmodule(vmoduleMap).build().apply();
+ resetLogs();
+
+ // No verbose logging other than in ClassA and ClassB.
+ assertNoVerboseLogging(testLogger);
+
+ // ClassA logs at FINE and above
+ assertErrorLogAtLevel(ClassA.logger, Level.FINE);
+ resetLogs();
+
+ // ClassB logs at WARNING and above
+ assertErrorLogAtLevel(ClassB.logger, Level.WARNING);
+ }
+
+ @Test
+ public void testVModuleOverridesVlog() {
+ // Configure with ClassA using FINE and ClassB using FINER;
+ Map<Class<?>, RootLogConfig.LogLevel> vmoduleMap =
+ ImmutableMap.of(ClassA.class, RootLogConfig.LogLevel.FINEST,
+ ClassB.class, RootLogConfig.LogLevel.INFO);
+ // Configure setting default vlog=FINER
+ getConfig()
+ .logToStderr(true).vlog(RootLogConfig.LogLevel.FINER).vmodule(vmoduleMap).build().apply();
+ resetLogs();
+
+ // Default logging is at finer level.
+ assertErrorLogAtLevel(testLogger, Level.FINER);
+
+ // ClassA logs at FINEST and above
+ assertErrorLogAtLevel(ClassA.logger, Level.FINEST);
+ resetLogs();
+
+ // ClassB logs at INFO and above
+ assertErrorLogAtLevel(ClassB.logger, Level.INFO);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeHandlerTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeHandlerTest.java b/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeHandlerTest.java
new file mode 100644
index 0000000..621a333
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeHandlerTest.java
@@ -0,0 +1,100 @@
+// =================================================================================================
+// Copyright 2013 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.logging.julbridge;
+
+import java.util.ListResourceBundle;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+import org.junit.Test;
+
+import com.twitter.common.logging.julbridge.JULBridgeLevelConverter;
+import com.twitter.common.logging.julbridge.JULBridgeHandler;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.sameInstance;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class JULBridgeHandlerTest {
+
+ @Test
+ public void checkMessageWithParametersIsFormatted() {
+ LogRecord record = new LogRecord(Level.FINEST, "test is {0}");
+ record.setParameters(new Object[] {"successful"});
+
+ assertThat(JULBridgeHandler.formatMessage(record), is("test is successful"));
+ }
+
+ @Test
+ public void checkMessageWithResourceBundleIsFormatted() {
+ ResourceBundle bundle = new ListResourceBundle() {
+ @Override protected Object[][] getContents() {
+ return new Object[][] {
+ {"test is successful", "le test fonctionne"}
+ };
+ }
+ };
+
+ LogRecord record = new LogRecord(Level.FINEST, "test is successful");
+ record.setResourceBundle(bundle);
+
+ assertThat(JULBridgeHandler.formatMessage(record), is("le test fonctionne"));
+ }
+
+ @Test
+ public void checkGetLoggerReturnsLoggerWithSameName() {
+ LogRecord record = new LogRecord(Level.FINEST, "test message");
+ record.setLoggerName("test.checkGetLogger");
+
+ assertThat(new JULBridgeHandler().getLogger(record).getName(), is("test.checkGetLogger"));
+ }
+
+ @Test
+ public void checkToLoggingEvent() {
+ LogRecord record = new LogRecord(Level.FINEST, "test is {0}");
+ record.setParameters(new Object[] {"successful"});
+
+ record.setThreadID(42);
+ Throwable t = new Throwable();
+ record.setThrown(t);
+
+ // source class and method names are usually inferred, but because there's no JUL in the stack
+ // frame, it won't work as expected.
+ record.setSourceClassName(getClass().getName());
+ record.setSourceMethodName("checkToLoggingEvent");
+
+ Logger log4jLogger = new JULBridgeHandler().getLogger(record);
+ org.apache.log4j.Level log4jLevel = JULBridgeLevelConverter.toLog4jLevel(Level.FINEST);
+ LoggingEvent event = JULBridgeHandler.toLoggingEvent(record, log4jLogger, log4jLevel, false);
+
+ assertThat(event.getLogger(), is((Category) log4jLogger));
+ assertThat(event.getLevel(), is(log4jLevel));
+ assertThat(event.getMessage(), is((Object) "test is successful"));
+ assertThat(event.getThreadName(), is("42"));
+ assertThat(event.getTimeStamp(), is(record.getMillis()));
+ assertThat(event.getThrowableInformation().getThrowable(), is(sameInstance(t)));
+
+ LocationInfo info = event.getLocationInformation();
+ assertThat(info.getClassName(), is(getClass().getName()));
+ assertThat(info.getMethodName(), is("checkToLoggingEvent"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverterTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverterTest.java b/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverterTest.java
new file mode 100644
index 0000000..17428d8
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverterTest.java
@@ -0,0 +1,83 @@
+package com.twitter.common.logging.julbridge;
+
+import java.util.Arrays;
+import java.util.logging.Level;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.twitter.common.logging.julbridge.JULBridgeLevelConverter;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class JULBridgeLevelConverterTest {
+
+ @RunWith(Parameterized.class)
+ public static class JULMappingToLog4JTest {
+ @SuppressWarnings("serial")
+ @Parameters
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][] {
+ { Level.FINEST, org.apache.log4j.Level.TRACE },
+ { Level.FINER, org.apache.log4j.Level.DEBUG },
+ { Level.FINE, org.apache.log4j.Level.DEBUG },
+ { Level.INFO, org.apache.log4j.Level.INFO },
+ { Level.WARNING, org.apache.log4j.Level.WARN },
+ { Level.SEVERE, org.apache.log4j.Level.ERROR },
+ { Level.ALL, org.apache.log4j.Level.ALL },
+ { Level.OFF, org.apache.log4j.Level.OFF },
+ // Unknown level should map to DEBUG
+ { new Level("test", 42) {}, org.apache.log4j.Level.DEBUG }
+ });
+ }
+
+ private final Level level;
+ private final org.apache.log4j.Level expected;
+
+ public JULMappingToLog4JTest(Level level, org.apache.log4j.Level expected) {
+ this.level = level;
+ this.expected = expected;
+ }
+
+ @Test
+ public void checkJULMapsToLog4J() {
+ assertThat(JULBridgeLevelConverter.toLog4jLevel(level), is(expected));
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class Log4JMappingToJULTest {
+ @SuppressWarnings("serial")
+ @Parameters
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][] {
+ { org.apache.log4j.Level.TRACE, Level.FINEST },
+ { org.apache.log4j.Level.DEBUG, Level.FINE },
+ { org.apache.log4j.Level.INFO, Level.INFO },
+ { org.apache.log4j.Level.WARN, Level.WARNING },
+ { org.apache.log4j.Level.ERROR, Level.SEVERE },
+ { org.apache.log4j.Level.FATAL, Level.SEVERE },
+ { org.apache.log4j.Level.ALL, Level.ALL },
+ { org.apache.log4j.Level.OFF, Level.OFF },
+ // Unknown level should map to FINE
+ { new org.apache.log4j.Level(42, "test", 42) {}, Level.FINE }
+ });
+ }
+
+ private final org.apache.log4j.Level level;
+ private final Level expected;
+
+ public Log4JMappingToJULTest(org.apache.log4j.Level level, Level expected) {
+ this.level = level;
+ this.expected = expected;
+ }
+
+ @Test
+ public void checkJULMapsToLog4J() {
+ assertThat(JULBridgeLevelConverter.fromLog4jLevel(level), is(expected));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLogManagerTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLogManagerTest.java b/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLogManagerTest.java
new file mode 100644
index 0000000..c518d89
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/logging/julbridge/JULBridgeLogManagerTest.java
@@ -0,0 +1,78 @@
+// =================================================================================================
+// Copyright 2013 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.logging.julbridge;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.Hierarchy;
+import org.apache.log4j.spi.LoggerRepository;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.spi.RootLogger;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class JULBridgeLogManagerTest {
+
+ @After
+ public void restoreLogConfiguration() throws SecurityException, IOException {
+ LogManager.getLogManager().readConfiguration();
+ }
+
+ @Test
+ public void checkAssimilateTakesOver() {
+ // Create a test log4j environment
+ final List<LoggingEvent> events = new LinkedList<LoggingEvent>();
+
+ org.apache.log4j.Logger log4jRoot = new RootLogger(org.apache.log4j.Level.ALL);
+ LoggerRepository loggerRepository = new Hierarchy(log4jRoot);
+ loggerRepository.setThreshold(org.apache.log4j.Level.INFO);
+
+ log4jRoot.addAppender(new AppenderSkeleton() {
+ @Override public boolean requiresLayout() {
+ return false;
+ }
+
+ @Override public void close() {}
+
+ @Override protected void append(LoggingEvent event) {
+ events.add(event);
+ }
+ });
+
+
+ JULBridgeLogManager.assimilate(loggerRepository);
+
+ Logger.getLogger("test.1").log(Level.INFO, "test message 1");
+ Logger.getLogger("test.2").log(Level.FINE, "test message 2");
+ Logger.getLogger("test.3").log(Level.WARNING, "test message 3");
+
+ assertThat(events.size(), is(2));
+ assertThat(events.get(0).getLoggerName(), is("test.1"));
+ assertThat(events.get(0).getMessage(), is((Object) "test message 1"));
+ assertThat(events.get(1).getLoggerName(), is("test.3"));
+ assertThat(events.get(1).getMessage(), is((Object) "test message 3"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/InetSocketAddressHelperTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/InetSocketAddressHelperTest.java b/commons/src/test/java/com/twitter/common/net/InetSocketAddressHelperTest.java
new file mode 100644
index 0000000..b90c8ca
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/InetSocketAddressHelperTest.java
@@ -0,0 +1,114 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.net;
+
+import org.junit.Test;
+
+import java.net.InetSocketAddress;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author John Sirois
+ */
+public class InetSocketAddressHelperTest {
+
+ @Test
+ public void testParseValueInvalid() {
+ try {
+ InetSocketAddressHelper.parse(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ InetSocketAddressHelper.parse("");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ InetSocketAddressHelper.parse(":");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ InetSocketAddressHelper.parse("*:");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ InetSocketAddressHelper.parse(":jake");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ InetSocketAddressHelper.parse(":70000");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ InetSocketAddressHelper.parse("localhost:");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testParseArgValuePort() {
+ assertEquals(new InetSocketAddress(6666), InetSocketAddressHelper.parse(":6666"));
+ assertEquals(new InetSocketAddress(0), InetSocketAddressHelper.parse(":*"));
+ }
+
+ @Test
+ public void testParseArgValueHostPort() {
+ assertEquals(InetSocketAddress.createUnresolved("localhost", 5555),
+ InetSocketAddressHelper.parse("localhost:5555"));
+
+ assertEquals(InetSocketAddress.createUnresolved("127.0.0.1", 4444),
+ InetSocketAddressHelper.parse("127.0.0.1:4444"));
+ }
+
+ @Test
+ public void testInetSocketAddressToServerString() {
+ assertEquals("localhost:8000",
+ InetSocketAddressHelper.toString(InetSocketAddress.createUnresolved("localhost", 8000)));
+
+ assertEquals("foo.bar.baz:8000",
+ InetSocketAddressHelper.toString(InetSocketAddress.createUnresolved("foo.bar.baz", 8000)));
+
+ assertEquals("127.0.0.1:8000",
+ InetSocketAddressHelper.toString(InetSocketAddress.createUnresolved("127.0.0.1", 8000)));
+
+ assertEquals("10.0.0.1:8000",
+ InetSocketAddressHelper.toString(InetSocketAddress.createUnresolved("10.0.0.1", 8000)));
+
+ assertEquals("0.0.0.0:80", InetSocketAddressHelper.toString(new InetSocketAddress(80)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/UrlHelperTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/UrlHelperTest.java b/commons/src/test/java/com/twitter/common/net/UrlHelperTest.java
new file mode 100644
index 0000000..0bc02e8
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/UrlHelperTest.java
@@ -0,0 +1,123 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.net;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+
+import java.net.URISyntaxException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author John Sirois
+ */
+public class UrlHelperTest {
+ @Test
+ public void testGetDomain() {
+ assertEquals("www.twitter.com", UrlHelper.getDomain("www.twitter.com"));
+ assertEquals("www.twitter.com", UrlHelper.getDomain("www.twitter.com/a/b/c?foo=bar&bar=baz"));
+
+ assertEquals("www.bign.com",
+ UrlHelper.getDomain("www.bign.com/davidvandiverhttp://cli.gs/da0e0"));
+ assertEquals("www.thesun.co.uk",
+ UrlHelper.getDomain("www.thesun.co.uk/sol/homepa-http://dragtotop.com/thesun.co.uk"));
+ assertEquals("www.formspring.me",
+ UrlHelper.getDomain("www.formspring.me/chuuworangerrhttp://bit.ly/7pydt3"));
+ assertEquals("www.bign.com",
+ UrlHelper.getDomain("www.bign.com/davidvandiverhttp://cli.gs/da0e0"));
+ assertEquals("www.roundplace.com",
+ UrlHelper.getDomain("www.roundplace.com/en/watch/108/3/"
+ + "baltimore-rave-http://dragtotop.com/patriots_vs_ravens"));
+ assertEquals("www.bign.com",
+ UrlHelper.getDomain("www.bign.com/davidvandiverhttp://cli.gs/da0e0"));
+ assertEquals(null, UrlHelper.getDomain("http://?idonthaveadomain=true"));
+ assertEquals(null, UrlHelper.getDomain(":::<<<<<::IAMNOTAVALIDURIā"));
+ }
+
+ @Test
+ public void testGetDomainChecked() throws Exception {
+ assertEquals("www.twitter.com", UrlHelper.getDomainChecked("http://www.twitter.com"));
+ assertEquals("www.twitter.com", UrlHelper.getDomainChecked("https://www.twitter.com/?a=b"));
+ assertEquals(null, UrlHelper.getDomainChecked("http://?idonthaveadomain=true"));
+ try {
+ UrlHelper.getDomainChecked(":::<<<<<::IAMNOTAVALIDURIā");
+ fail();
+ } catch (URISyntaxException e) {
+ // Expected
+ }
+ }
+
+ @Test
+ public void testGetPath() {
+ assertEquals("", UrlHelper.getPath("www.twitter.com"));
+ assertEquals("/", UrlHelper.getPath("www.twitter.com/"));
+ assertEquals("/foo", UrlHelper.getPath("http://www.twitter.com/foo"));
+ assertEquals("/bar", UrlHelper.getPath("https://www.twitter.com/bar"));
+ assertEquals("/a/b/c", UrlHelper.getPath("www.twitter.com/a/b/c"));
+
+ assertEquals("/davidvandiverhttp://cli.gs/da0e0",
+ UrlHelper.getPath("www.bign.com/davidvandiverhttp://cli.gs/da0e0"));
+ assertEquals("/sol/homepa-http://dragtotop.com/thesun.co.uk",
+ UrlHelper.getPath("www.thesun.co.uk/sol/homepa-http://dragtotop.com/thesun.co.uk"));
+ assertEquals("/chuuworangerrhttp://bit.ly/7pydt3",
+ UrlHelper.getPath("www.formspring.me/chuuworangerrhttp://bit.ly/7pydt3"));
+ assertEquals("/davidvandiverhttp://cli.gs/da0e0",
+ UrlHelper.getPath("www.bign.com/davidvandiverhttp://cli.gs/da0e0"));
+ assertEquals("/en/watch/10855/3/baltimore-rave-http://dragtotop.com/patriots_vs_ravens",
+ UrlHelper.getPath("www.roundplace.com/en/watch/10855/3/"
+ + "baltimore-rave-http://dragtotop.com/patriots_vs_ravens"));
+ assertEquals("/davidvandiverhttp://cli.gs/da0e0",
+ UrlHelper.getPath("www.bign.com/davidvandiverhttp://cli.gs/da0e0"));
+ }
+
+ @Test
+ public void testAddProtocol() {
+ assertEquals("http://www.twitter.com", UrlHelper.addProtocol("www.twitter.com"));
+ assertEquals("http://www.twitter.com", UrlHelper.addProtocol("http://www.twitter.com"));
+ assertEquals("https://www.twitter.com", UrlHelper.addProtocol("https://www.twitter.com"));
+
+ assertEquals("http://www.twitter.com/this/is/a/http://stange/but/valid/path",
+ UrlHelper.addProtocol("http://www.twitter.com/this/is/a/http://stange/but/valid/path"));
+ assertEquals("http://www.twitter.com/this/is/a/http://stange/but/valid/path",
+ UrlHelper.addProtocol("www.twitter.com/this/is/a/http://stange/but/valid/path"));
+ }
+
+ @Test
+ public void testStripUrlParameters() {
+ assertEquals("www.twitter.com", UrlHelper.stripUrlParameters("www.twitter.com"));
+ assertEquals("www.twitter.com", UrlHelper.stripUrlParameters("www.twitter.com?foo-bar"));
+ assertEquals("www.twitter.com/a/b/",
+ UrlHelper.stripUrlParameters("www.twitter.com/a/b/?foo-bar"));
+
+ assertEquals("http://www.twitter.com", UrlHelper.stripUrlParameters("http://www.twitter.com"));
+ assertEquals("http://www.twitter.com",
+ UrlHelper.stripUrlParameters("http://www.twitter.com?foo=bar"));
+ assertEquals("http://www.twitter.com/a",
+ UrlHelper.stripUrlParameters("http://www.twitter.com/a?foo=bar"));
+ }
+
+ @Test
+ public void testGetDomainLevels() {
+ assertEquals(ImmutableList.of("www.fred", "fred"), UrlHelper.getDomainLevels("fred"));
+ assertEquals(ImmutableList.of("www.twitter.com", "twitter.com", "com"),
+ UrlHelper.getDomainLevels("www.twitter.com"));
+ assertEquals(ImmutableList.of("www.twitter.co.uk", "twitter.co.uk", "co.uk", "uk"),
+ UrlHelper.getDomainLevels("twitter.co.uk"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/UrlResolverTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/UrlResolverTest.java b/commons/src/test/java/com/twitter/common/net/UrlResolverTest.java
new file mode 100644
index 0000000..2eedc17
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/UrlResolverTest.java
@@ -0,0 +1,174 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.net;
+
+import com.twitter.common.base.ExceptionalFunction;
+import com.twitter.common.net.UrlResolver.ResolvedUrl;
+import com.twitter.common.net.UrlResolver.ResolvedUrl.EndState;
+import com.twitter.common.util.BackoffStrategy;
+import com.twitter.common.util.Clock;
+import org.easymock.IMocksControl;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static com.google.common.testing.junit4.JUnitAsserts.assertContentsInOrder;
+import static org.easymock.EasyMock.createControl;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author John Sirois
+ */
+public class UrlResolverTest {
+ private IMocksControl control;
+ private ExceptionalFunction<String, String, IOException> resolver;
+ private Clock clock;
+ private BackoffStrategy backoffStrategy;
+
+ @Before
+ public void setUp() throws Exception {
+ control = createControl();
+
+ @SuppressWarnings("unchecked")
+ ExceptionalFunction<String, String, IOException> resolver =
+ control.createMock(ExceptionalFunction.class);
+ this.resolver = resolver;
+ this.clock = control.createMock(Clock.class);
+ this.backoffStrategy = control.createMock(BackoffStrategy.class);
+ }
+
+ @Test
+ public void testResolveUrlResolved() throws Exception {
+ expect(resolver.apply("jake")).andReturn("jake");
+ control.replay();
+
+ ResolvedUrl resolvedUrl = createResolver(3).resolveUrl("jake");
+ assertEquals("jake", resolvedUrl.getStartUrl());
+ assertContentsInOrder("Expected no intermediate urls", resolvedUrl.getIntermediateUrls());
+ assertNull(resolvedUrl.getEndUrl());
+ assertEquals(EndState.REACHED_LANDING, resolvedUrl.getEndState());
+
+ control.verify();
+ }
+
+ @Test
+ public void testResolveUrlSingleRedirect() throws Exception {
+ expect(resolver.apply("jake")).andReturn("joe");
+ expect(resolver.apply("joe")).andReturn("joe");
+ control.replay();
+
+ ResolvedUrl resolvedUrl = createResolver(3).resolveUrl("jake");
+ assertEquals("jake", resolvedUrl.getStartUrl());
+ assertContentsInOrder("Expected no intermediate urls", resolvedUrl.getIntermediateUrls());
+ assertEquals("joe", resolvedUrl.getEndUrl());
+ assertEquals(EndState.REACHED_LANDING, resolvedUrl.getEndState());
+
+ control.verify();
+ }
+
+ @Test
+ public void testResolveUrlMultipleRedirects() throws Exception {
+ expect(resolver.apply("jake")).andReturn("joe");
+ expect(resolver.apply("joe")).andReturn("bill");
+ expect(resolver.apply("bill")).andReturn("bob");
+ expect(resolver.apply("bob")).andReturn("fred");
+ expect(resolver.apply("fred")).andReturn("fred");
+ control.replay();
+
+ ResolvedUrl resolvedUrl = createResolver(5).resolveUrl("jake");
+ assertEquals("jake", resolvedUrl.getStartUrl());
+ assertContentsInOrder(resolvedUrl.getIntermediateUrls(), "joe", "bill", "bob");
+ assertEquals("fred", resolvedUrl.getEndUrl());
+ assertEquals(EndState.REACHED_LANDING, resolvedUrl.getEndState());
+
+ control.verify();
+ }
+
+ @Test
+ public void testResolveUrlRedirectLimit() throws Exception {
+ expect(resolver.apply("jake")).andReturn("joe");
+ expect(resolver.apply("joe")).andReturn("bill");
+ control.replay();
+
+ ResolvedUrl resolvedUrl = createResolver(2).resolveUrl("jake");
+ assertEquals("jake", resolvedUrl.getStartUrl());
+ assertContentsInOrder(resolvedUrl.getIntermediateUrls(), "joe");
+ assertEquals("bill", resolvedUrl.getEndUrl());
+ assertEquals(EndState.REDIRECT_LIMIT, resolvedUrl.getEndState());
+
+ control.verify();
+ }
+
+ @Test
+ public void testResolveUrlResolveError() throws Exception {
+ expect(resolver.apply("jake")).andThrow(new IOException());
+ control.replay();
+
+ ResolvedUrl resolvedUrl = createResolver(3).resolveUrl("jake");
+ assertEquals("jake", resolvedUrl.getStartUrl());
+ assertContentsInOrder("Expected no intermediate urls", resolvedUrl.getIntermediateUrls());
+ assertNull(resolvedUrl.getEndUrl());
+ assertEquals(EndState.ERROR, resolvedUrl.getEndState());
+
+ control.verify();
+ }
+
+ @Test
+ public void testResolveUrlResolveErrorCode() throws Exception {
+ expect(resolver.apply("jake")).andReturn(null);
+ expect(backoffStrategy.calculateBackoffMs(0L)).andReturn(1L);
+ clock.waitFor(1L);
+
+ expect(resolver.apply("jake")).andReturn(null);
+ expect(backoffStrategy.calculateBackoffMs(1L)).andReturn(2L);
+ clock.waitFor(2L);
+
+ expect(resolver.apply("jake")).andReturn(null);
+ // we shouldn't back off after the last attempt
+ control.replay();
+
+ ResolvedUrl resolvedUrl = createResolver(3).resolveUrl("jake");
+ assertEquals("jake", resolvedUrl.getStartUrl());
+ assertContentsInOrder("Expected no intermediate urls", resolvedUrl.getIntermediateUrls());
+ assertNull(resolvedUrl.getEndUrl());
+ assertEquals(EndState.ERROR, resolvedUrl.getEndState());
+
+ control.verify();
+ }
+
+ @Test
+ public void testResolveStepsToPermanentError() throws Exception {
+ expect(resolver.apply("jake")).andReturn("joe");
+ expect(resolver.apply("joe")).andReturn("fred");
+ expect(resolver.apply("fred")).andReturn(null);
+ // we shouldn't back off after the last attempt
+ control.replay();
+
+ ResolvedUrl resolvedUrl = createResolver(3).resolveUrl("jake");
+ assertEquals("jake", resolvedUrl.getStartUrl());
+ assertContentsInOrder(resolvedUrl.getIntermediateUrls(), "joe");
+ assertEquals("fred", resolvedUrl.getEndUrl());
+ assertEquals(EndState.ERROR, resolvedUrl.getEndState());
+ }
+
+ private UrlResolver createResolver(int maxRedirects) {
+ return new UrlResolver(clock, backoffStrategy, resolver, maxRedirects);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/UrlResolverUtilTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/UrlResolverUtilTest.java b/commons/src/test/java/com/twitter/common/net/UrlResolverUtilTest.java
new file mode 100644
index 0000000..635ae13
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/UrlResolverUtilTest.java
@@ -0,0 +1,165 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.net;
+
+import com.google.common.base.Function;
+import com.google.common.testing.TearDown;
+import com.google.common.testing.junit4.TearDownTestCase;
+import com.twitter.common.base.Closure;
+import com.twitter.common.collections.Pair;
+import org.easymock.Capture;
+import org.easymock.IAnswer;
+import org.easymock.IMocksControl;
+import org.junit.Before;
+import org.junit.Test;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.bio.SocketConnector;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URL;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * TODO(John Sirois): add test for error conditions
+ *
+ * @author John Sirois
+ */
+public class UrlResolverUtilTest extends TearDownTestCase {
+ private static final String REDIRECT_LOCATION = "http://bar";
+
+ private IMocksControl control;
+ private Function<URL, String> urlToUA;
+ private Closure<Pair<HttpServletRequest, HttpServletResponse>> requestHandler;
+ private UrlResolverUtil urlResolverUtil;
+ private HttpServlet servlet;
+ private String url;
+
+ @Before
+ public void setUp() {
+ control = createControl();
+
+ @SuppressWarnings("unchecked")
+ Function<URL, String> urlToUA = control.createMock(Function.class);
+ this.urlToUA = urlToUA;
+
+ @SuppressWarnings("unchecked")
+ Closure<Pair<HttpServletRequest, HttpServletResponse>> handler =
+ control.createMock(Closure.class);
+ requestHandler = handler;
+
+ urlResolverUtil = new UrlResolverUtil(urlToUA);
+
+ servlet = new HttpServlet() {
+ @Override protected void service(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ requestHandler.execute(Pair.of(req, resp));
+ }
+ };
+ }
+
+ @Test
+ public void testUASelection() throws Exception {
+ url = startServer();
+ String redirectLocation = "http://bar.com";
+
+ expect(urlToUA.apply(new URL(url))).andReturn("foo-agent");
+ expectRequestAndRedirect(redirectLocation);
+ control.replay();
+
+ String effectiveUrl = urlResolverUtil.getEffectiveUrl(url, null /* no proxy */);
+ assertEquals(redirectLocation, effectiveUrl);
+
+ control.verify();
+ }
+
+ @Test
+ public void testRelativeRedirect() throws Exception {
+ url = startServer();
+ String relativeRedirect = "relatively/speaking";
+
+ expect(urlToUA.apply(new URL(url))).andReturn("foo-agent");
+ expectRequestAndRedirect(relativeRedirect);
+ control.replay();
+
+ String effectiveUrl = urlResolverUtil.getEffectiveUrl(url, null /* no proxy */);
+ assertEquals(url + relativeRedirect, effectiveUrl);
+
+ control.verify();
+ }
+
+ @Test
+ public void testInvalidRedirect() throws Exception {
+ url = startServer();
+ String badRedirect = ":::<<<<<::IAMNOTAVALIDURI";
+
+ expect(urlToUA.apply(new URL(url))).andReturn("foo-agent");
+ expectRequestAndRedirect(badRedirect);
+ control.replay();
+
+ String effectiveUrl = urlResolverUtil.getEffectiveUrl(url, null /* no proxy */);
+ assertEquals(badRedirect, effectiveUrl);
+
+ control.verify();
+ }
+
+ private void expectRequestAndRedirect(final String location) throws Exception {
+ final Capture<Pair<HttpServletRequest, HttpServletResponse>> requestCapture =
+ new Capture<Pair<HttpServletRequest, HttpServletResponse>>();
+ requestHandler.execute(capture(requestCapture));
+ expectLastCall().andAnswer(new IAnswer<Void>() {
+ @Override public Void answer() throws Throwable {
+ assertTrue(requestCapture.hasCaptured());
+ Pair<HttpServletRequest, HttpServletResponse> pair = requestCapture.getValue();
+
+ HttpServletRequest request = pair.getFirst();
+ assertEquals("HEAD", request.getMethod());
+ assertEquals("foo-agent", request.getHeader("User-Agent"));
+
+ pair.getSecond().sendRedirect(location);
+ return null;
+ }
+ });
+ }
+
+ private String startServer() throws Exception {
+ final Server server = new Server();
+ final SocketConnector connector = new SocketConnector();
+ connector.setHost("127.0.0.1");
+ connector.setPort(0);
+ server.addConnector(connector);
+
+ Context context = new Context(server, "/", Context.NO_SECURITY);
+ context.addServlet(new ServletHolder(servlet), "/*");
+ server.start();
+ addTearDown(new TearDown() {
+ @Override public void tearDown() throws Exception {
+ server.stop();
+ }
+ });
+
+ return "http://" + connector.getHost() + ":" + connector.getLocalPort() + "/";
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/UrlTokenizerUtilTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/UrlTokenizerUtilTest.java b/commons/src/test/java/com/twitter/common/net/UrlTokenizerUtilTest.java
new file mode 100644
index 0000000..193394e
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/UrlTokenizerUtilTest.java
@@ -0,0 +1,97 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.net;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Adam Samet
+ */
+public class UrlTokenizerUtilTest {
+
+ @Test
+ public void testGetReversedDomainParts() {
+ List<String> list1 = Lists.newArrayList();
+ String url1 = "www.twitter.com";
+ list1.add("com");
+ assertEquals(list1, UrlTokenizerUtil.getReversedDomainParts(url1, 1));
+ list1.add("twitter");
+ assertEquals(list1, UrlTokenizerUtil.getReversedDomainParts(url1, 2));
+ list1.add("www");
+ assertEquals(list1, UrlTokenizerUtil.getReversedDomainParts(url1, 3));
+ list1.add("");
+ assertEquals(list1, UrlTokenizerUtil.getReversedDomainParts(url1, 4));
+ list1.add("");
+ assertEquals(list1, UrlTokenizerUtil.getReversedDomainParts(url1, 5));
+
+ List<String> list2 = Lists.newArrayList();
+ String url2 = "www.twitter.co.uk";
+ list2.add("co.uk");
+ assertEquals(list2, UrlTokenizerUtil.getReversedDomainParts(url2, 1));
+ list2.add("twitter");
+ assertEquals(list2, UrlTokenizerUtil.getReversedDomainParts(url2, 2));
+ list2.add("www");
+ assertEquals(list2, UrlTokenizerUtil.getReversedDomainParts(url2, 3));
+ list2.add("");
+ assertEquals(list2, UrlTokenizerUtil.getReversedDomainParts(url2, 4));
+ list2.add("");
+ assertEquals(list2, UrlTokenizerUtil.getReversedDomainParts(url2, 5));
+
+ List<String> list3 = Lists.newArrayList();
+ String url3= "www.twitter.co.ukNOT";
+ list3.add("ukNOT");
+ assertEquals(list3, UrlTokenizerUtil.getReversedDomainParts(url3, 1));
+ list3.add("co");
+ assertEquals(list3, UrlTokenizerUtil.getReversedDomainParts(url3, 2));
+ list3.add("twitter");
+ assertEquals(list3, UrlTokenizerUtil.getReversedDomainParts(url3, 3));
+ list3.add("www");
+ assertEquals(list3, UrlTokenizerUtil.getReversedDomainParts(url3, 4));
+ list3.add("");
+ assertEquals(list3, UrlTokenizerUtil.getReversedDomainParts(url3, 5));
+
+ assertEquals(Arrays.asList("co.jp", "google"),
+ UrlTokenizerUtil.getReversedDomainParts("news.google.co.jp", 2));
+ assertEquals(Arrays.asList("co.jp", "google"),
+ UrlTokenizerUtil.getReversedDomainParts("news.google.co.jp", 2));
+ assertEquals(Arrays.asList("com", "google"),
+ UrlTokenizerUtil.getReversedDomainParts("news.google.com", 2));
+ assertEquals(Arrays.asList("com", "google", "news"),
+ UrlTokenizerUtil.getReversedDomainParts("news.google.com", 3));
+ }
+
+ @Test
+ public void testIsTLD() throws Exception {
+ assertTrue(UrlTokenizerUtil.isTLD("com.cn", false));
+ assertTrue(UrlTokenizerUtil.isTLD("com", false));
+ assertTrue(UrlTokenizerUtil.isTLD("co.jp", false));
+ assertTrue(UrlTokenizerUtil.isTLD("co.uk", false));
+ assertTrue(UrlTokenizerUtil.isTLD("uk.co", true));
+ assertTrue(UrlTokenizerUtil.isTLD("cn.com", true));
+ assertFalse(UrlTokenizerUtil.isTLD("google.co.uk", false));
+ assertFalse(UrlTokenizerUtil.isTLD("google.jp", false));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/http/RequestLoggerTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/http/RequestLoggerTest.java b/commons/src/test/java/com/twitter/common/net/http/RequestLoggerTest.java
new file mode 100644
index 0000000..49c072e
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/http/RequestLoggerTest.java
@@ -0,0 +1,90 @@
+package com.twitter.common.net.http;
+
+import java.util.logging.Level;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mortbay.jetty.HttpHeaders;
+import org.mortbay.jetty.HttpURI;
+import org.mortbay.jetty.Request;
+import org.mortbay.jetty.RequestLog;
+import org.mortbay.jetty.Response;
+
+import com.twitter.common.net.http.RequestLogger.LogSink;
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Time;
+import com.twitter.common.testing.easymock.EasyMockTest;
+import com.twitter.common.util.testing.FakeClock;
+
+import static org.easymock.EasyMock.expect;
+
+public class RequestLoggerTest extends EasyMockTest {
+
+ private FakeClock clock;
+ private LogSink sink;
+ private Request request;
+ private Response response;
+
+ private RequestLog log;
+
+ @Before
+ public void setUp() throws Exception {
+ clock = new FakeClock();
+ sink = createMock(LogSink.class);
+ request = createMock(Request.class);
+ response = createMock(Response.class);
+ log = new RequestLogger(clock, sink);
+ }
+
+ @Test
+ public void testFormat200() throws Exception {
+ clock.advance(Amount.of(40L * 365, Time.DAYS));
+
+ expect(response.getStatus()).andReturn(200).atLeastOnce();
+ expect(request.getServerName()).andReturn("snoopy");
+ expect(request.getHeader(HttpHeaders.X_FORWARDED_FOR)).andReturn(null);
+ expect(request.getMethod()).andReturn("GET");
+ expect(request.getUri()).andReturn(new HttpURI("/"));
+ expect(request.getProtocol()).andReturn("http");
+ expect(response.getContentCount()).andReturn(256L);
+ expect(request.getRemoteAddr()).andReturn("easymock-test");
+ expect(request.getHeader(HttpHeaders.REFERER)).andReturn(null);
+ expect(request.getHeader(HttpHeaders.USER_AGENT)).andReturn("junit");
+ expect(request.getTimeStamp()).andReturn(clock.nowMillis()).atLeastOnce();
+
+ expect(sink.isLoggable(Level.FINE)).andReturn(true);
+ sink.log(Level.FINE, "snoopy easymock-test [22/Dec/2009:00:00:00 +0000]"
+ + " \"GET / http\" 200 256 \"-\" \"junit\" 110");
+
+ control.replay();
+
+ clock.advance(Amount.of(110L, Time.MILLISECONDS));
+ log.log(request, response);
+ }
+
+ @Test
+ public void testFormat500() throws Exception {
+ clock.advance(Amount.of(40L * 365, Time.DAYS));
+
+ expect(response.getStatus()).andReturn(500).atLeastOnce();
+ expect(request.getServerName()).andReturn("woodstock");
+ expect(request.getHeader(HttpHeaders.X_FORWARDED_FOR)).andReturn(null);
+ expect(request.getMethod()).andReturn("POST");
+ expect(request.getUri()).andReturn(new HttpURI("/data"));
+ expect(request.getProtocol()).andReturn("http");
+ expect(response.getContentCount()).andReturn(128L);
+ expect(request.getRemoteAddr()).andReturn("easymock-test");
+ expect(request.getHeader(HttpHeaders.REFERER)).andReturn(null);
+ expect(request.getHeader(HttpHeaders.USER_AGENT)).andReturn("junit");
+ expect(request.getTimeStamp()).andReturn(clock.nowMillis()).atLeastOnce();
+
+ expect(sink.isLoggable(Level.INFO)).andReturn(true);
+ sink.log(Level.INFO, "woodstock easymock-test [22/Dec/2009:00:00:00 +0000]"
+ + " \"POST /data http\" 500 128 \"-\" \"junit\" 500");
+
+ control.replay();
+
+ clock.advance(Amount.of(500L, Time.MILLISECONDS));
+ log.log(request, response);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterIntegrationTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterIntegrationTest.java b/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterIntegrationTest.java
new file mode 100644
index 0000000..8ff6811
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterIntegrationTest.java
@@ -0,0 +1,153 @@
+package com.twitter.common.net.http.filters;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.google.inject.servlet.GuiceFilter;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.guice.JerseyServletModule;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.twitter.common.net.http.HttpServerDispatch;
+import com.twitter.common.net.http.JettyHttpServerDispatch;
+import com.twitter.common.stats.Stat;
+import com.twitter.common.stats.Stats;
+import com.twitter.common.util.Clock;
+import com.twitter.common.util.testing.FakeClock;
+
+import static com.sun.jersey.api.core.ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class HttpStatsFilterIntegrationTest {
+ private Client client;
+ private FakeClock clock;
+ private JettyHttpServerDispatch server;
+
+ @Before
+ public void setUp() {
+ Stats.flush();
+
+ server = new JettyHttpServerDispatch();
+ server.listen(0);
+ server.registerFilter(GuiceFilter.class, "/*");
+
+ clock = new FakeClock();
+
+ final Injector injector = Guice.createInjector(
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(TestServlet.class).in(Singleton.class);
+
+ bind(Clock.class).toInstance(clock);
+ bind(HttpStatsFilter.class).in(Singleton.class);
+ }
+ },
+ new JerseyServletModule() {
+ @Override
+ protected void configureServlets() {
+ filter("/*").through(HttpStatsFilter.class);
+ serve("/*").with(GuiceContainer.class, ImmutableMap.of(
+ PROPERTY_CONTAINER_RESPONSE_FILTERS, HttpStatsFilter.class.getName()));
+ }
+ }
+ );
+ server.getRootContext().addEventListener(new GuiceServletContextListener() {
+ @Override protected Injector getInjector() {
+ return injector;
+ }
+ });
+
+ ClientConfig config = new DefaultClientConfig();
+ client = Client.create(config);
+ }
+
+ @Path("/")
+ public static class TestServlet {
+ @GET
+ @Path("/hello")
+ @Produces(MediaType.TEXT_PLAIN)
+ @HttpStatsFilter.TrackRequestStats("hello")
+ public Response hello() {
+ return Response.ok("hello world").build();
+ }
+
+ @GET
+ @Path("/hola")
+ @Produces(MediaType.TEXT_PLAIN)
+ @HttpStatsFilter.TrackRequestStats("hola")
+ public Response hola() {
+ return Response.ok("hola mundo").build();
+ }
+
+ @GET
+ @Path("/goodbye")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response goodbye() {
+ return Response.ok("goodbye cruel world").build();
+ }
+ }
+
+ private String getResource(String path) {
+ return client
+ .resource(String.format("http://localhost:%s%s", server.getPort(), path))
+ .accept(MediaType.TEXT_PLAIN)
+ .get(String.class);
+ }
+
+ private void assertStatValue(String statName, long expectedValue) {
+ Stat<Long> stat = Stats.getVariable(statName);
+ assertEquals(expectedValue, stat.read().longValue());
+ }
+
+ @Test
+ public void testStatsTracking() throws Exception {
+ getResource("/hello");
+
+ assertStatValue("http_hello_200_responses_events", 1);
+ }
+
+ @Test
+ public void testRepeatedContextInjection() throws Exception {
+ getResource("/hello");
+ getResource("/hola");
+ getResource("/hello");
+
+ assertStatValue("http_hello_200_responses_events", 2);
+ assertStatValue("http_hola_200_responses_events", 1);
+ }
+
+ @Test
+ public void testNoStatsTracking() throws Exception {
+ getResource("/goodbye");
+
+ assertNull(Stats.getVariable("http_goodbye_200_responses_events"));
+ }
+
+ @Test
+ public void testNoMatchedMethod() throws Exception {
+ try {
+ getResource("/what");
+ fail("Should have thrown a 404.");
+ } catch (UniformInterfaceException e) {
+ assertStatValue("http_404_responses_events", 1);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterTest.java b/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterTest.java
new file mode 100644
index 0000000..ba9783c
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/http/filters/HttpStatsFilterTest.java
@@ -0,0 +1,214 @@
+package com.twitter.common.net.http.filters;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.List;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Context;
+
+import com.google.common.collect.Lists;
+import com.sun.jersey.api.core.ExtendedUriInfo;
+import com.sun.jersey.api.model.AbstractResourceMethod;
+import com.sun.jersey.spi.container.ContainerRequest;
+import com.sun.jersey.spi.container.ContainerResponse;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.twitter.common.collections.Pair;
+import com.twitter.common.net.http.filters.HttpStatsFilter.TrackRequestStats;
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Time;
+import com.twitter.common.stats.SlidingStats;
+import com.twitter.common.testing.easymock.EasyMockTest;
+import com.twitter.common.util.testing.FakeClock;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class HttpStatsFilterTest extends EasyMockTest {
+ private FakeClock clock;
+ private HttpServletRequest request;
+ private HttpServletResponse response;
+ private FilterChain filterChain;
+ private HttpStatsFilter filter;
+ private ContainerRequest containerRequest;
+ private ContainerResponse containerResponse;
+ private ExtendedUriInfo extendedUriInfo;
+ private HttpServletRequest servletRequest;
+
+ private static final Amount<Long, Time> REQUEST_TIME = Amount.of(1000L, Time.NANOSECONDS);
+
+ private void injectContextVars() throws Exception {
+ extendedUriInfo = createMock(ExtendedUriInfo.class);
+ servletRequest = createMock(HttpServletRequest.class);
+
+ List<Object> injectables = Lists.newArrayList(extendedUriInfo, servletRequest);
+
+ for (Field f : filter.getClass().getDeclaredFields()) {
+ if (f.isAnnotationPresent(Context.class)) {
+ for (Object injectable : injectables) {
+ if (f.getType().isInstance(injectable)) {
+ f.setAccessible(true);
+ f.set(filter, injectable);
+ }
+ }
+ }
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ clock = new FakeClock();
+ request = createMock(HttpServletRequest.class);
+ response = createMock(HttpServletResponse.class);
+ filterChain = createMock(FilterChain.class);
+ filter = new HttpStatsFilter(clock);
+
+ containerRequest = createMock(ContainerRequest.class);
+ containerResponse = createMock(ContainerResponse.class);
+
+ injectContextVars();
+ }
+
+ @Test
+ public void testStartTimeIsSetAsRequestAttribute() throws Exception {
+ request.setAttribute(HttpStatsFilter.REQUEST_START_TIME, REQUEST_TIME.getValue());
+ filterChain.doFilter(request, response);
+
+ control.replay();
+
+ clock.advance(REQUEST_TIME);
+ filter.doFilter(request, response, filterChain);
+ }
+
+ @Test
+ public void testExceptionStatsCounting() throws Exception {
+ request.setAttribute(HttpStatsFilter.REQUEST_START_TIME, REQUEST_TIME.getValue());
+ expectLastCall().times(2);
+ clock.advance(REQUEST_TIME);
+
+ filterChain.doFilter(anyObject(HttpServletRequest.class), anyObject(HttpServletResponse.class));
+ expectLastCall().andThrow(new IOException());
+
+ filterChain.doFilter(anyObject(HttpServletRequest.class), anyObject(HttpServletResponse.class));
+ expectLastCall().andThrow(new ServletException());
+
+ control.replay();
+
+ try {
+ filter.doFilter(request, response, filterChain);
+ fail("Filter should have re-thrown the exception.");
+ } catch (IOException e) {
+ // Exception is expected, but we still want to assert on the stat tracking, so we can't
+ // just use @Test(expected...)
+ assertEquals(1, filter.exceptionCount.get());
+ }
+
+ try {
+ filter.doFilter(request, response, filterChain);
+ fail("Filter should have re-thrown the exception.");
+ } catch (ServletException e) {
+ // See above.
+ assertEquals(2, filter.exceptionCount.get());
+ }
+ }
+
+ private void expectAnnotationValue(String value, int times) {
+ AbstractResourceMethod matchedMethod = createMock(AbstractResourceMethod.class);
+ expect(extendedUriInfo.getMatchedMethod()).andReturn(matchedMethod).times(times);
+
+ TrackRequestStats annotation = createMock(TrackRequestStats.class);
+ expect(matchedMethod.getAnnotation(TrackRequestStats.class)).andReturn(annotation).times(times);
+
+ expect(annotation.value()).andReturn(value).times(times);
+ }
+
+ private void expectAnnotationValue(String value) {
+ expectAnnotationValue(value, 1);
+ }
+
+ @Test
+ public void testBasicStatsCounting() throws Exception {
+ expect(containerResponse.getStatus()).andReturn(HttpServletResponse.SC_OK);
+
+ expect(servletRequest.getAttribute(HttpStatsFilter.REQUEST_START_TIME))
+ .andReturn(clock.nowNanos());
+
+ String value = "some_value";
+ expectAnnotationValue(value);
+
+ control.replay();
+
+ clock.advance(REQUEST_TIME);
+ assertEquals(containerResponse, filter.filter(containerRequest, containerResponse));
+
+ SlidingStats stat = filter.requestCounters.get(Pair.of(value, HttpServletResponse.SC_OK));
+ assertEquals(1, stat.getEventCounter().get());
+ assertEquals(REQUEST_TIME.getValue().longValue(), stat.getTotalCounter().get());
+ assertEquals(1, filter.statusCounters.get(HttpServletResponse.SC_OK).getEventCounter().get());
+ }
+
+ @Test
+ public void testMultipleRequests() throws Exception {
+ int numCalls = 2;
+
+ expect(containerResponse.getStatus()).andReturn(HttpServletResponse.SC_OK).times(numCalls);
+
+ expect(servletRequest.getAttribute(HttpStatsFilter.REQUEST_START_TIME))
+ .andReturn(clock.nowNanos()).times(numCalls);
+
+ String value = "some_value";
+ expectAnnotationValue(value, numCalls);
+
+ control.replay();
+
+ clock.advance(REQUEST_TIME);
+ for (int i = 0; i < numCalls; i++) {
+ filter.filter(containerRequest, containerResponse);
+ }
+
+ SlidingStats stat = filter.requestCounters.get(Pair.of(value, HttpServletResponse.SC_OK));
+ assertEquals(numCalls, stat.getEventCounter().get());
+ assertEquals(REQUEST_TIME.getValue() * numCalls, stat.getTotalCounter().get());
+ assertEquals(numCalls,
+ filter.statusCounters.get(HttpServletResponse.SC_OK).getEventCounter().get());
+ }
+
+ @Test
+ public void testNoStartTime() throws Exception {
+ expect(servletRequest.getAttribute(HttpStatsFilter.REQUEST_START_TIME))
+ .andReturn(null);
+
+ expect(containerResponse.getStatus()).andReturn(HttpServletResponse.SC_OK);
+
+ control.replay();
+
+ assertEquals(containerResponse, filter.filter(containerRequest, containerResponse));
+
+ assertEquals(0, filter.statusCounters.asMap().keySet().size());
+ }
+
+ @Test
+ public void testNoMatchedMethod() throws Exception {
+ expect(containerResponse.getStatus()).andReturn(HttpServletResponse.SC_NOT_FOUND);
+
+ expect(servletRequest.getAttribute(HttpStatsFilter.REQUEST_START_TIME))
+ .andReturn(clock.nowNanos());
+
+ expect(extendedUriInfo.getMatchedMethod()).andReturn(null);
+
+ control.replay();
+
+ clock.advance(REQUEST_TIME);
+ assertEquals(containerResponse, filter.filter(containerRequest, containerResponse));
+ assertEquals(1,
+ filter.statusCounters.get(HttpServletResponse.SC_NOT_FOUND).getEventCounter().get());
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/http/handlers/AssetHandlerTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/http/handlers/AssetHandlerTest.java b/commons/src/test/java/com/twitter/common/net/http/handlers/AssetHandlerTest.java
new file mode 100644
index 0000000..94adf60
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/http/handlers/AssetHandlerTest.java
@@ -0,0 +1,383 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.net.http.handlers;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.GZIPInputStream;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.io.InputSupplier;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.twitter.common.net.http.handlers.AssetHandler.StaticAsset;
+import com.twitter.common.testing.easymock.EasyMockTest;
+
+import static com.twitter.common.net.http.handlers.AssetHandler.CACHE_CONTROL_MAX_AGE_SECS;
+import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static org.easymock.EasyMock.expect;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author William Farner
+ */
+public class AssetHandlerTest extends EasyMockTest {
+
+ private static final String TEST_DATA = "here is my great test data";
+ // Checksum of the gzipped TEST_DATA.
+ private static final String TEST_DATA_CHECKSUM = "ePvVhtAeVRu85KSOLKL0oQ==";
+ private static final String CONTENT_TYPE = "text/plain";
+
+ private InputSupplier<InputStream> inputSupplier;
+
+ @Before
+ public void setUp() {
+ inputSupplier = createMock(new Clazz<InputSupplier<InputStream>>() {});
+ }
+
+ private static class Request {
+ private final HttpServletRequest req;
+ private final HttpServletResponse resp;
+ private final ByteArrayOutputStream responseBody;
+
+ Request(HttpServletRequest req, HttpServletResponse resp, ByteArrayOutputStream responseBody) {
+ this.req = req;
+ this.resp = resp;
+ this.responseBody = responseBody;
+ }
+ }
+
+ private Request doGet(String suppliedChecksum, String supportedEncodings,
+ int expectedResponseCode, boolean expectRead) throws Exception {
+ HttpServletRequest req = createMock(HttpServletRequest.class);
+ HttpServletResponse resp = createMock(HttpServletResponse.class);
+
+ if (expectRead) {
+ expect(inputSupplier.getInput()).andReturn(new ByteArrayInputStream(TEST_DATA.getBytes()));
+ }
+
+ expect(req.getHeader("If-None-Match")).andReturn(suppliedChecksum);
+
+ resp.setStatus(expectedResponseCode);
+ if (expectedResponseCode == SC_OK) {
+ expect(req.getHeader("Accept-Encoding")).andReturn(supportedEncodings);
+ resp.setHeader("Cache-Control", "public,max-age=" + CACHE_CONTROL_MAX_AGE_SECS);
+ resp.setHeader("ETag", TEST_DATA_CHECKSUM);
+ resp.setContentType(CONTENT_TYPE);
+
+ if (supportedEncodings != null && supportedEncodings.contains("gzip")) {
+ resp.setHeader("Content-Encoding", "gzip");
+ }
+ }
+ return new Request(req, resp, expectPayload(resp));
+ }
+
+ @Test
+ public void testCached() throws Exception {
+
+ // First request - no cached value
+ Request test1 = doGet(
+ null, // No local checksum.
+ null, // No encodings supported.
+ SC_OK,
+ true // Triggers a data read.
+ );
+
+ // Second request - client performs conditional GET with wrong checksum.
+ Request test2 = doGet(
+ "foo", // Wrong checksum.
+ null, // No encodings supported.
+ SC_OK,
+ false // No read.
+ );
+
+ // Third request - client performs conditional GET with correct checksum.
+ Request test3 = doGet(
+ TEST_DATA_CHECKSUM, // Correct checksum.
+ null, // No encodings supported.
+ SC_NOT_MODIFIED,
+ false // No read.
+ );
+
+ control.replay();
+
+ AssetHandler handler = new AssetHandler(new StaticAsset(inputSupplier, CONTENT_TYPE, true));
+
+ handler.doGet(test1.req, test1.resp);
+ assertThat(new String(test1.responseBody.toByteArray()), is(TEST_DATA));
+
+ handler.doGet(test2.req, test2.resp);
+ assertThat(new String(test2.responseBody.toByteArray()), is(TEST_DATA));
+
+ handler.doGet(test3.req, test3.resp);
+ assertThat(new String(test3.responseBody.toByteArray()), is(""));
+ }
+
+ @Test
+ public void testCachedGzipped() throws Exception {
+
+ // First request - no cached value
+ Request test1 = doGet(
+ null, // No local checksum.
+ "gzip", // Supported encodings.
+ SC_OK,
+ true // Triggers a data read.
+ );
+
+ // Second request - client performs conditional GET with wrong checksum.
+ Request test2 = doGet(
+ "foo", // Wrong checksum.
+ "gzip,fakeencoding", // Supported encodings.
+ SC_OK,
+ false // No read.
+ );
+
+ // Third request - client performs conditional GET with correct checksum.
+ Request test3 = doGet(
+ TEST_DATA_CHECKSUM, // Correct checksum.
+ "gzip,deflate", // Supported encodings.
+ SC_NOT_MODIFIED,
+ false // No read.
+ );
+
+ control.replay();
+
+ AssetHandler handler = new AssetHandler(new StaticAsset(inputSupplier, CONTENT_TYPE, true));
+
+ handler.doGet(test1.req, test1.resp);
+ assertThat(unzip(test1.responseBody), is(TEST_DATA));
+
+ handler.doGet(test2.req, test2.resp);
+ assertThat(unzip(test2.responseBody), is(TEST_DATA));
+
+ handler.doGet(test3.req, test3.resp);
+ assertThat(new String(test3.responseBody.toByteArray()), is(""));
+ }
+
+ @Test
+ public void testUncached() throws Exception {
+
+ // First request - no cached value
+ Request test1 = doGet(
+ null, // No local checksum.
+ null, // No encodings supported.
+ SC_OK,
+ true // Triggers a data read.
+ );
+
+ // Second request - client performs conditional GET with wrong checksum.
+ Request test2 = doGet(
+ "foo", // Wrong checksum.
+ null, // No encodings supported.
+ SC_OK,
+ true // Triggers a data read.
+ );
+
+ // Third request - client performs conditional GET with correct checksum.
+ Request test3 = doGet(
+ TEST_DATA_CHECKSUM, // Correct checksum.
+ null, // No encodings supported.
+ SC_NOT_MODIFIED,
+ true // Triggers a data read.
+ );
+
+ control.replay();
+
+ AssetHandler handler = new AssetHandler(new StaticAsset(inputSupplier, CONTENT_TYPE, false));
+
+ handler.doGet(test1.req, test1.resp);
+ assertThat(new String(test1.responseBody.toByteArray()), is(TEST_DATA));
+
+ handler.doGet(test2.req, test2.resp);
+ assertThat(new String(test2.responseBody.toByteArray()), is(TEST_DATA));
+
+ handler.doGet(test3.req, test3.resp);
+ assertThat(new String(test3.responseBody.toByteArray()), is(""));
+ }
+
+ @Test
+ public void testUncachedGzipped() throws Exception {
+
+ // First request - no cached value
+ Request test1 = doGet(
+ null, // No local checksum.
+ "gzip", // Supported encodings.
+ SC_OK,
+ true // Triggers a data read.
+ );
+
+ // Second request - client performs conditional GET with wrong checksum.
+ Request test2 = doGet(
+ "foo", // Wrong checksum.
+ "gzip,fakeencoding", // Supported encodings.
+ SC_OK,
+ true // Triggers a data read.
+ );
+
+ // Third request - client performs conditional GET with correct checksum.
+ Request test3 = doGet(
+ TEST_DATA_CHECKSUM, // Correct checksum.
+ "gzip,deflate", // Supported encodings.
+ SC_NOT_MODIFIED,
+ true // Triggers a data read.
+ );
+
+ control.replay();
+
+ AssetHandler handler = new AssetHandler(new StaticAsset(inputSupplier, CONTENT_TYPE, false));
+
+ handler.doGet(test1.req, test1.resp);
+ assertThat(unzip(test1.responseBody), is(TEST_DATA));
+
+ handler.doGet(test2.req, test2.resp);
+ assertThat(unzip(test2.responseBody), is(TEST_DATA));
+
+ handler.doGet(test3.req, test3.resp);
+ assertThat(new String(test3.responseBody.toByteArray()), is(""));
+ }
+
+ private static ByteArrayOutputStream expectPayload(HttpServletResponse resp) throws Exception {
+ ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
+ expect(resp.getOutputStream()).andReturn(new FakeServletOutputStream(responseBody));
+ return responseBody;
+ }
+
+ private static String unzip(ByteArrayOutputStream streamData) throws IOException {
+ ByteArrayInputStream in = new ByteArrayInputStream(streamData.toByteArray());
+ GZIPInputStream unzip = new GZIPInputStream(in);
+ return new String(ByteStreams.toByteArray(unzip));
+ }
+
+ private static class FakeServletOutputStream extends ServletOutputStream {
+ private final OutputStream realStream;
+
+ FakeServletOutputStream(OutputStream realStream) {
+ this.realStream = realStream;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ realStream.write(b);
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ realStream.write(b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ realStream.write(b, off, len);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ realStream.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ realStream.close();
+ }
+
+ @Override
+ public void print(String s) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void print(boolean b) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void print(char c) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void print(int i) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void print(long l) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void print(float f) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void print(double d) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println() throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println(String s) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println(boolean b) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println(char c) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println(int i) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println(long l) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println(float f) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Override
+ public void println(double d) throws IOException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/http/handlers/HttpServletRequestParamsTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/http/handlers/HttpServletRequestParamsTest.java b/commons/src/test/java/com/twitter/common/net/http/handlers/HttpServletRequestParamsTest.java
new file mode 100644
index 0000000..5891cb1
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/http/handlers/HttpServletRequestParamsTest.java
@@ -0,0 +1,69 @@
+package com.twitter.common.net.http.handlers;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.twitter.common.testing.easymock.EasyMockTest;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+
+public class HttpServletRequestParamsTest extends EasyMockTest {
+ private static final String INT_PARAM = "int_param";
+ private static final String LONG_PARAM = "long_param";
+ private static final String STRING_PARAM = "string_param";
+ private static final String UNSET_PARAM = "unset_param";
+ private static final String BOOL_PARAM = "bool_param";
+
+ private HttpServletRequest request;
+
+ @Before
+ public void setUp() throws Exception {
+ request = createMock(HttpServletRequest.class);
+ expect(request.getParameter(INT_PARAM)).andReturn("123").anyTimes();
+ expect(request.getParameter(LONG_PARAM)).andReturn("260833376896966656").anyTimes();
+ expect(request.getParameter(STRING_PARAM)).andReturn("asdf").anyTimes();
+ expect(request.getParameter(UNSET_PARAM)).andReturn(null).anyTimes();
+ expect(request.getParameter(BOOL_PARAM)).andReturn("TRUE").anyTimes();
+ }
+
+ @Test
+ public void testGetIntParam() {
+ EasyMock.replay(request);
+ assertEquals(123, HttpServletRequestParams.getInt(request, INT_PARAM, 456));
+ assertEquals(456, HttpServletRequestParams.getInt(request, STRING_PARAM, 456));
+ assertEquals(456, HttpServletRequestParams.getInt(request, UNSET_PARAM, 456));
+ assertEquals(456, HttpServletRequestParams.getInt(request, LONG_PARAM, 456));
+ }
+
+ @Test
+ public void testGetLongParam() {
+ EasyMock.replay(request);
+ assertEquals(123, HttpServletRequestParams.getLong(request, INT_PARAM, 456));
+ assertEquals(260833376896966656L, HttpServletRequestParams.getLong(request, LONG_PARAM, 456));
+ assertEquals(123456789012345678L,
+ HttpServletRequestParams.getLong(request, STRING_PARAM, 123456789012345678L));
+ assertEquals(456, HttpServletRequestParams.getLong(request, UNSET_PARAM, 456));
+ }
+
+ @Test
+ public void testGetStringParam() {
+ EasyMock.replay(request);
+ assertEquals("123", HttpServletRequestParams.getString(request, INT_PARAM, "default"));
+ assertEquals("260833376896966656",
+ HttpServletRequestParams.getString(request, LONG_PARAM, "default"));
+ assertEquals("asdf", HttpServletRequestParams.getString(request, STRING_PARAM, "default"));
+ assertEquals("default", HttpServletRequestParams.getString(request, UNSET_PARAM, "default"));
+ }
+
+ @Test
+ public void testGetBoolParam() {
+ EasyMock.replay(request);
+ assertEquals(false, HttpServletRequestParams.getBool(request, INT_PARAM, true));
+ assertEquals(false, HttpServletRequestParams.getBool(request, LONG_PARAM, false));
+ assertEquals(true, HttpServletRequestParams.getBool(request, BOOL_PARAM, false));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/net/http/handlers/LogPrinterTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/net/http/handlers/LogPrinterTest.java b/commons/src/test/java/com/twitter/common/net/http/handlers/LogPrinterTest.java
new file mode 100644
index 0000000..8f40913
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/net/http/handlers/LogPrinterTest.java
@@ -0,0 +1,74 @@
+package com.twitter.common.net.http.handlers;
+
+import java.io.File;
+import java.util.List;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for the LogPrinter.
+ *
+ * @author William Farner
+ */
+public class LogPrinterTest {
+
+ @Test
+ public void testRelativeFileHandling() {
+ LogPrinter printer = new LogPrinter(new File("/this/is/the/log/dir"), true);
+ LogPrinter.LogFile absFile = printer.new LogFile("/absolute/path.log");
+ assertEquals("/absolute/path.log", absFile.getPath());
+ LogPrinter.LogFile relFile = printer.new LogFile("relative/file.log");
+ assertEquals("/this/is/the/log/dir/relative/file.log", relFile.getPath());
+ }
+
+ @Test
+ public void testFilterLines() {
+ testFilterLinesHelper(TEST_LINES, FILTER0, FILTERED_LINES0);
+ testFilterLinesHelper(TEST_LINES, FILTER1, FILTERED_LINES1);
+ testFilterLinesHelper(TEST_LINES, FILTER2, FILTERED_LINES2);
+ testFilterLinesHelper(TEST_LINES, FILTER3, FILTERED_LINES3);
+ }
+
+ private void testFilterLinesHelper(List<String> testLines,
+ String filter,
+ List<String> expectedLines) {
+
+ List<String> filteredLines = Lists.newArrayList(
+ LogPrinter.filterLines(Joiner.on("\n").join(testLines), filter).split("\n"));
+
+ assertThat(filteredLines, is(expectedLines));
+ }
+
+ private static final List<String> TEST_LINES = Lists.newArrayList(
+ "Matching line 1 twittttter",
+ "Matching line 2 twitter",
+ "Not matching line 1 twiter",
+ "Matching line 3"
+ );
+
+ private static final String FILTER0 = "";
+ private static final List<String> FILTERED_LINES0 = TEST_LINES;
+
+ private static final String FILTER1 = "Matching.*";
+ private static final List<String> FILTERED_LINES1 = Lists.newArrayList(
+ "Matching line 1 twittttter",
+ "Matching line 2 twitter",
+ "Matching line 3"
+ );
+
+ private static final String FILTER2 = "^.*twitt+er$";
+ private static final List<String> FILTERED_LINES2 = Lists.newArrayList(
+ "Matching line 1 twittttter",
+ "Matching line 2 twitter"
+ );
+
+ private static final String FILTER3 = "^.*\\d.*$";
+ private static final List<String> FILTERED_LINES3 = TEST_LINES;
+}