Return-Path: X-Original-To: apmail-aurora-commits-archive@minotaur.apache.org Delivered-To: apmail-aurora-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A4CD118248 for ; Tue, 25 Aug 2015 18:19:16 +0000 (UTC) Received: (qmail 72834 invoked by uid 500); 25 Aug 2015 18:19:16 -0000 Delivered-To: apmail-aurora-commits-archive@aurora.apache.org Received: (qmail 72723 invoked by uid 500); 25 Aug 2015 18:19:16 -0000 Mailing-List: contact commits-help@aurora.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aurora.apache.org Delivered-To: mailing list commits@aurora.apache.org Received: (qmail 72488 invoked by uid 99); 25 Aug 2015 18:19:16 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Aug 2015 18:19:16 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id BDE7AE3621; Tue, 25 Aug 2015 18:19:15 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: zmanji@apache.org To: commits@aurora.apache.org Date: Tue, 25 Aug 2015 18:19:21 -0000 Message-Id: In-Reply-To: <2d86d301903d4a1c81757199842a5e58@git.apache.org> References: <2d86d301903d4a1c81757199842a5e58@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [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 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, 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, 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 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 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 events = new LinkedList(); + + 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 resolver; + private Clock clock; + private BackoffStrategy backoffStrategy; + + @Before + public void setUp() throws Exception { + control = createControl(); + + @SuppressWarnings("unchecked") + ExceptionalFunction 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 urlToUA; + private Closure> requestHandler; + private UrlResolverUtil urlResolverUtil; + private HttpServlet servlet; + private String url; + + @Before + public void setUp() { + control = createControl(); + + @SuppressWarnings("unchecked") + Function urlToUA = control.createMock(Function.class); + this.urlToUA = urlToUA; + + @SuppressWarnings("unchecked") + Closure> 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> requestCapture = + new Capture>(); + requestHandler.execute(capture(requestCapture)); + expectLastCall().andAnswer(new IAnswer() { + @Override public Void answer() throws Throwable { + assertTrue(requestCapture.hasCaptured()); + Pair 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 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 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 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 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 REQUEST_TIME = Amount.of(1000L, Time.NANOSECONDS); + + private void injectContextVars() throws Exception { + extendedUriInfo = createMock(ExtendedUriInfo.class); + servletRequest = createMock(HttpServletRequest.class); + + List 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 inputSupplier; + + @Before + public void setUp() { + inputSupplier = createMock(new Clazz>() {}); + } + + 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 testLines, + String filter, + List expectedLines) { + + List filteredLines = Lists.newArrayList( + LogPrinter.filterLines(Joiner.on("\n").join(testLines), filter).split("\n")); + + assertThat(filteredLines, is(expectedLines)); + } + + private static final List 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 FILTERED_LINES0 = TEST_LINES; + + private static final String FILTER1 = "Matching.*"; + private static final List 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 FILTERED_LINES2 = Lists.newArrayList( + "Matching line 1 twittttter", + "Matching line 2 twitter" + ); + + private static final String FILTER3 = "^.*\\d.*$"; + private static final List FILTERED_LINES3 = TEST_LINES; +}