package org.sonar.api.utils;
import com.google.common.base.Charsets;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.SystemUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
-import org.mortbay.jetty.testing.ServletTester;
+import org.junit.rules.TemporaryFolder;
+import org.simpleframework.http.Request;
+import org.simpleframework.http.Response;
+import org.simpleframework.http.core.Container;
+import org.simpleframework.transport.connect.SocketConnection;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
import java.io.File;
import java.io.IOException;
-import java.net.*;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Properties;
import static org.fest.assertions.Assertions.assertThat;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assume.assumeThat;
-import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class HttpDownloaderTest {
- private static ServletTester tester;
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ private static SocketConnection socketConnection;
private static String baseUrl;
@BeforeClass
- public static void startServer() throws Exception {
- assumeThat(SystemUtils.IS_OS_WINDOWS, is(false)); // Temporarily deactivated on Windows because of frequent freezes
-
- tester = new ServletTester();
- tester.setContextPath("/");
- tester.addServlet(RedirectServlet.class, "/redirect/");
- tester.addServlet(FakeServlet.class, "/");
- baseUrl = tester.createSocketConnector(true);
- tester.start();
+ public static void startServer() throws IOException {
+ socketConnection = new SocketConnection(new Container() {
+ public void handle(Request req, Response resp) {
+ try {
+ if (req.getPath().getPath().contains("/redirect/")) {
+ resp.setCode(303);
+ resp.add("Location", "/");
+ } else {
+ resp.getPrintStream().append("agent=" + req.getValues("User-Agent").get(0));
+ }
+ } catch (IOException e) {
+ } finally {
+ try {
+ resp.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ });
+ SocketAddress address = socketConnection.connect(new InetSocketAddress(0));
+
+ baseUrl = "http://localhost:" + ((InetSocketAddress) address).getPort();
}
@AfterClass
- public static void stopServer() throws Exception {
- /* workaround for a jetty deadlock :
- 1. stopping server logs a SLF4J/Logback message, but the message calls AbstractConnector.toString, which is synchronized on getLocalPort()
- 2. a jetty thread tries also to stop and is locked on the same synchronized block.
-
- "3862294@qtp-17303670-1":
- at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:66)
- - waiting to lock <0x8be33f88> (a ch.qos.logback.core.ConsoleAppender)
- at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:60)
- at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:270)
- at ch.qos.logback.classic.Logger.callAppenders(Logger.java:257)
- at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:439)
- at ch.qos.logback.classic.Logger.filterAndLog_2(Logger.java:430)
- at ch.qos.logback.classic.Logger.debug(Logger.java:508)
- at org.mortbay.log.Slf4jLog.debug(Slf4jLog.java:40)
- at org.mortbay.log.Log.debug(Log.java:112)
- at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:77)
- - locked <0x8b8cf980> (a java.lang.Object)
- at org.mortbay.jetty.nio.SelectChannelConnector.close(SelectChannelConnector.java:136)
- - locked <0x8b8c0150> (a org.mortbay.jetty.nio.SelectChannelConnector)
- at org.mortbay.jetty.AbstractConnector$Acceptor.run(AbstractConnector.java:735)
- at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
-"main":
- at org.mortbay.jetty.nio.SelectChannelConnector.getLocalPort(SelectChannelConnector.java:188)
- - waiting to lock <0x8b8c0150> (a org.mortbay.jetty.nio.SelectChannelConnector)
- at org.mortbay.jetty.AbstractConnector.toString(AbstractConnector.java:669)
- at java.lang.String.valueOf(String.java:2826)
- at java.lang.StringBuffer.append(StringBuffer.java:219)
- - locked <0x8b7e8618> (a java.lang.StringBuffer)
- at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:237)
- at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:196)
- at ch.qos.logback.classic.spi.LoggingEvent.getFormattedMessage(LoggingEvent.java:282)
- at ch.qos.logback.classic.pattern.MessageConverter.convert(MessageConverter.java:22)
- at ch.qos.logback.classic.pattern.MessageConverter.convert(MessageConverter.java:19)
- at ch.qos.logback.core.pattern.FormattingConverter.write(FormattingConverter.java:32)
- at ch.qos.logback.core.pattern.PatternLayoutBase.writeLoopOnConverters(PatternLayoutBase.java:110)
- at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:132)
- at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:51)
- at ch.qos.logback.core.WriterAppender.subAppend(WriterAppender.java:261)
- at ch.qos.logback.core.WriterAppender.append(WriterAppender.java:114)
- at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:87)
- - locked <0x8be33f88> (a ch.qos.logback.core.ConsoleAppender)
- at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:60)
- at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:270)
- at ch.qos.logback.classic.Logger.callAppenders(Logger.java:257)
- at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:439)
- at ch.qos.logback.classic.Logger.filterAndLog_2(Logger.java:430)
- at ch.qos.logback.classic.Logger.info(Logger.java:605)
- at org.mortbay.log.Slf4jLog.info(Slf4jLog.java:67)
- at org.mortbay.log.Log.info(Log.java:154)
- at org.mortbay.jetty.AbstractConnector.doStop(AbstractConnector.java:313)
- at org.mortbay.jetty.nio.SelectChannelConnector.doStop(SelectChannelConnector.java:326)
- at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
- - locked <0x8b8ce798> (a java.lang.Object)
- at org.mortbay.jetty.Server.doStop(Server.java:280)
- at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:76)
- - locked <0x8b8cf7b8> (a java.lang.Object)
- at org.mortbay.jetty.testing.ServletTester.stop(ServletTester.java:92)
- at org.sonar.api.utils.HttpDownloaderTest.stopServer(HttpDownloaderTest.java:62)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
- at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
- at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
- at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:37)
- at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
- at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
- at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
- at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
- at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
- at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
- at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
- at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
- at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
- at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:120)
- at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:103)
- at org.apache.maven.surefire.Surefire.run(Surefire.java:169)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
- at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)
-
-
-
- For this reason the ugly workaround is to wait the end of the thread before stopping...
-
- We'll have to check if Jetty 7 resolves this toString() issue.
- */
- if (tester != null) {
- Thread.sleep(1000);
- tester.stop();
+ public static void stopServer() throws IOException {
+ if (null != socketConnection) {
+ socketConnection.close();
}
}
@Test
- public void downloadBytes() throws Exception {
+ public void downloadBytes() throws URISyntaxException {
byte[] bytes = new HttpDownloader(new Settings()).readBytes(new URI(baseUrl));
assertThat(bytes.length).isGreaterThan(10);
}
@Test
- public void readString() throws Exception {
+ public void readString() throws URISyntaxException {
String text = new HttpDownloader(new Settings()).readString(new URI(baseUrl), Charsets.UTF_8);
assertThat(text.length()).isGreaterThan(10);
}
@Test(expected = SonarException.class)
- public void failIfServerDown() throws Exception {
+ public void failIfServerDown() throws URISyntaxException {
// I hope that the port 1 is not used !
new HttpDownloader(new Settings()).readBytes(new URI("http://localhost:1/unknown"));
}
@Test
public void downloadToFile() throws URISyntaxException, IOException {
- File toDir = new File("target/test-tmp/org/sonar/api/utils/DownloaderTest/");
- FileUtils.forceMkdir(toDir);
- FileUtils.cleanDirectory(toDir);
+ File toDir = temporaryFolder.newFolder();
File toFile = new File(toDir, "downloadToFile.txt");
new HttpDownloader(new Settings()).download(new URI(baseUrl), toFile);
@Test
public void shouldNotCreateFileIfFailToDownload() throws Exception {
- File toDir = new File("target/test-tmp/org/sonar/api/utils/DownloaderTest/");
- FileUtils.forceMkdir(toDir);
- FileUtils.cleanDirectory(toDir);
+ File toDir = temporaryFolder.newFolder();
File toFile = new File(toDir, "downloadToFile.txt");
try {
Server server = mock(Server.class);
when(server.getVersion()).thenReturn("2.2");
- byte[] bytes = new HttpDownloader(server, new Settings()).readBytes(new URI(baseUrl));
+ InputStream stream = new HttpDownloader(server, new Settings()).openStream(new URI(baseUrl));
Properties props = new Properties();
- props.load(IOUtils.toInputStream(new String(bytes)));
+ props.load(stream);
+ stream.close();
+
assertThat(props.getProperty("agent")).isEqualTo("Sonar 2.2");
}
@Test
public void followRedirect() throws URISyntaxException {
- byte[] bytes = new HttpDownloader(new Settings()).readBytes(new URI(baseUrl + "/redirect/"));
- assertThat(new String(bytes)).contains("count");
+ String content = new HttpDownloader(new Settings()).readString(new URI(baseUrl + "/redirect/"), Charsets.UTF_8);
+ assertThat(content).contains("agent");
}
@Test
public void shouldGetDirectProxySynthesis() throws URISyntaxException {
ProxySelector proxySelector = mock(ProxySelector.class);
- when(proxySelector.select((URI) anyObject())).thenReturn(Arrays.asList(Proxy.NO_PROXY));
+ when(proxySelector.select(any(URI.class))).thenReturn(Arrays.asList(Proxy.NO_PROXY));
assertThat(HttpDownloader.getProxySynthesis(new URI("http://an_url"), proxySelector)).isEqualTo("no proxy");
}
@Test
public void shouldGetProxySynthesis() throws URISyntaxException {
ProxySelector proxySelector = mock(ProxySelector.class);
- when(proxySelector.select((URI) anyObject())).thenReturn(Arrays.asList((Proxy) new FakeProxy()));
+ when(proxySelector.select(any(URI.class))).thenReturn(Arrays.<Proxy> asList(new FakeProxy()));
assertThat(HttpDownloader.getProxySynthesis(new URI("http://an_url"), proxySelector)).isEqualTo("proxy: http://proxy_url:4040");
}
}
@Test
- public void uri_description() throws Exception {
- HttpDownloader downloader = new HttpDownloader(new Settings());
- String description = downloader.description(new URI("http://sonarsource.org"));
+ public void uri_description() throws URISyntaxException {
+ String description = new HttpDownloader(new Settings()).description(new URI("http://sonarsource.org"));
assertThat(description).matches("http://sonarsource.org \\(.*\\)");
}
}