/** Copyright 2014 Pieter Rautenbach Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.whatsthatlight.teamcity.hipchat.test; import static org.junit.Assert.*; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Scanner; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Appender; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.WriterAppender; import org.codehaus.jackson.map.ObjectMapper; import org.eclipse.jetty.server.Request; import org.testng.annotations.Test; import org.testng.annotations.BeforeClass; import com.whatsthatlight.teamcity.hipchat.HipChatApiProcessor; import com.whatsthatlight.teamcity.hipchat.HipChatApiResultLinks; import com.whatsthatlight.teamcity.hipchat.HipChatConfiguration; import com.whatsthatlight.teamcity.hipchat.HipChatEmoticon; import com.whatsthatlight.teamcity.hipchat.HipChatEmoticons; import com.whatsthatlight.teamcity.hipchat.HipChatMessageColour; import com.whatsthatlight.teamcity.hipchat.HipChatMessageFormat; import com.whatsthatlight.teamcity.hipchat.HipChatRoom; import com.whatsthatlight.teamcity.hipchat.HipChatApiResponseLinks; import com.whatsthatlight.teamcity.hipchat.HipChatRoomNotification; import com.whatsthatlight.teamcity.hipchat.HipChatRooms; import org.eclipse.jetty.server.handler.AbstractHandler; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.*; public class HipChatApiProcessorTest { private static Logger logger = Logger.getLogger("com.whatsthatlight.teamcity.hipchat"); @BeforeClass public static void ClassSetup() { // Set up a basic logger for debugging purposes BasicConfigurator.configure(); } @Test(enabled = false) public void testGetEmoticons() throws URISyntaxException { String apiUrl = "https://api.hipchat.com/v2/"; String apiToken = "token"; HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(apiUrl); configuration.setApiToken(apiToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); HipChatEmoticons emoticons = processor.getEmoticons(0); for (HipChatEmoticon emoticon : emoticons.items) { System.out.println(String.format("%s: %s - %s", emoticon.id, emoticon.shortcut, emoticon.url)); } } @Test public void testGetEmoticonsSuccess() throws Exception { // Test parameters int expectedNumberOfEmoticons = 1; String expectedEmoticonId = "0"; String expectedEmoticonShortcut = "emo"; String expectedEmoticonUrl = "http://example.com/"; int expectedStatusCode = HttpServletResponse.SC_OK; int port = 8080; URI uri = new URI(String.format("http://localhost:%s/", port)); String token = "token"; // JSON HipChatApiResponseLinks emoticonLinks = new HipChatApiResponseLinks("self", "webhooks", "members"); HipChatEmoticon emoticon = new HipChatEmoticon(expectedEmoticonId, emoticonLinks, expectedEmoticonShortcut, expectedEmoticonUrl); HipChatApiResultLinks resultLinks = new HipChatApiResultLinks("self", "prev", "next"); List<HipChatEmoticon> emoticonsList = new ArrayList<HipChatEmoticon>(); emoticonsList.add(emoticon); HipChatEmoticons emoticons = new HipChatEmoticons(emoticonsList, 0, expectedNumberOfEmoticons, resultLinks); ObjectMapper mapper = new ObjectMapper(); String expectedJson = mapper.writeValueAsString(emoticons); System.out.println(expectedJson); // Configuration HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri.toString()); configuration.setApiToken(token); // Handler class Handler extends AbstractHandler { private int statusCode; private String response; public Handler(int statusCode, String response) { this.statusCode = statusCode; this.response = response; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html;charset=utf-8"); response.setStatus(this.statusCode); response.getWriter().write(this.response); baseRequest.setHandled(true); } } // Setup SimpleServer server = new SimpleServer(port, new Handler(expectedStatusCode, expectedJson)); server.start(); // Execute HipChatApiProcessor processor = new HipChatApiProcessor(configuration); HipChatEmoticons actualEmoticons = processor.getEmoticons(0); // Clean up server.stop(); // Test assertEquals(expectedNumberOfEmoticons, actualEmoticons.maxResults); assertEquals(expectedNumberOfEmoticons, actualEmoticons.items.size()); HipChatEmoticon actualRoom = actualEmoticons.items.get(0); assertEquals(expectedEmoticonId, actualRoom.id); assertEquals(expectedEmoticonShortcut, actualRoom.shortcut); assertEquals(expectedEmoticonUrl, actualRoom.url); } @Test public void testGetEmoticonsException() throws Exception { // Test parameters String expectedExceptionText = "UnsupportedSchemeException"; int port = 8080; String uri = String.format("nohttp://localhost:%s/", port); String token = "token"; // Setup ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Appender appender = new WriterAppender(new PatternLayout("%m%n"), outputStream); logger.addAppender(appender); HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); // Execute HipChatEmoticons actualEmoticons = processor.getEmoticons(0); logger.removeAppender(appender); // Test boolean exceptionFound = false; String logOutput = new String(outputStream.toByteArray()); for (String line : logOutput.split("\n")) { if (line.contains(expectedExceptionText)) { exceptionFound = true; break; } } assertTrue(exceptionFound); assertNull(actualEmoticons); } @Test public void testGetEmoticonsReturnsEmptyInCaseOfFailure() throws URISyntaxException { String apiUrl = "https://api.hipchat.com/v2/"; String apiToken = "invalid_token"; HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(apiUrl); configuration.setApiToken(apiToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); HipChatEmoticons emoticons = processor.getEmoticons(0); assertNull(emoticons); } @Test public void testGetRoomsReturnsEmptyInCaseOfFailure() throws URISyntaxException { String apiUrl = "https://api.hipchat.com/v2/"; String apiToken = "invalid_token"; HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(apiUrl); configuration.setApiToken(apiToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); HipChatRooms rooms = processor.getRooms(0); assertNotNull(rooms); assertNotNull(rooms.items); assertEquals(0, rooms.items.size()); } @Test(enabled = false) public void testGetRooms() throws URISyntaxException { String apiUrl = "https://api.hipchat.com/v2/"; String apiToken = "token"; HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(apiUrl); configuration.setApiToken(apiToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); HipChatRooms rooms = processor.getRooms(0); for (HipChatRoom room : rooms.items) { System.out.println(String.format("%s - %s", room.id, room.name)); } } @Test public void testGetRoomsSuccess() throws Exception { // Test parameters int expectedNumberOfRooms = 1; String expectedRoomId = "0"; String expectedRoomName = "testRoom"; int expectedStatusCode = HttpServletResponse.SC_OK; int port = 8080; URI uri = new URI(String.format("http://localhost:%s/", port)); String token = "token"; // JSON HipChatApiResponseLinks roomLinks = new HipChatApiResponseLinks("self", "webhooks", "members"); HipChatRoom room = new HipChatRoom(expectedRoomId, roomLinks, expectedRoomName); HipChatApiResultLinks resultLinks = new HipChatApiResultLinks("self", "prev", "next"); List<HipChatRoom> roomsList = new ArrayList<HipChatRoom>(); roomsList.add(room); HipChatRooms rooms = new HipChatRooms(roomsList, 0, expectedNumberOfRooms, resultLinks); ObjectMapper mapper = new ObjectMapper(); String expectedJson = mapper.writeValueAsString(rooms); System.out.println(expectedJson); // Configuration HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri.toString()); configuration.setApiToken(token); // Handler class Handler extends AbstractHandler { private int statusCode; private String response; public Handler(int statusCode, String response) { this.statusCode = statusCode; this.response = response; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html;charset=utf-8"); response.setStatus(this.statusCode); response.getWriter().write(this.response); baseRequest.setHandled(true); } } // Setup SimpleServer server = new SimpleServer(port, new Handler(expectedStatusCode, expectedJson)); server.start(); // Execute HipChatApiProcessor processor = new HipChatApiProcessor(configuration); HipChatRooms actualRooms = processor.getRooms(0); // Clean up server.stop(); // Test assertEquals(expectedNumberOfRooms, actualRooms.maxResults); assertEquals(expectedNumberOfRooms, actualRooms.items.size()); HipChatRoom actualRoom = actualRooms.items.get(0); assertEquals(expectedRoomId, actualRoom.id); assertEquals(expectedRoomName, actualRoom.name); } @Test public void testGetRoomsException() throws Exception { // Test parameters int expectedNumberOfRooms = 0; String expectedExceptionText = "UnsupportedSchemeException"; int port = 8080; String uri = String.format("nohttp://localhost:%s/", port); String token = "token"; // Setup ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Appender appender = new WriterAppender(new PatternLayout("%m%n"), outputStream); logger.addAppender(appender); HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); // Execute HipChatRooms actualRooms = processor.getRooms(0); logger.removeAppender(appender); // Test boolean exceptionFound = false; String logOutput = new String(outputStream.toByteArray()); for (String line : logOutput.split("\n")) { if (line.contains(expectedExceptionText)) { exceptionFound = true; break; } } assertTrue(exceptionFound); assertEquals(expectedNumberOfRooms, actualRooms.startIndex); assertEquals(expectedNumberOfRooms, actualRooms.maxResults); assertEquals(expectedNumberOfRooms, actualRooms.items.size()); assertNull(actualRooms.links); } @Test public void testSendNotificationSuccess() throws Exception { // Test parameters int expectedStatusCode = HttpServletResponse.SC_NO_CONTENT; String expectedRoomId = "1"; String expectedToken = "token"; int port = 8080; URI uri = new URI(String.format("http://localhost:%s/", port)); ArrayList<String> responses = new ArrayList<String>(); HipChatRoomNotification notification = new HipChatRoomNotification("foo", HipChatMessageFormat.TEXT, HipChatMessageColour.INFO, true); ObjectMapper mapper = new ObjectMapper(); String expectedJson = mapper.writeValueAsString(notification); // Handler class Handler extends AbstractHandler { private String roomId; private int statusCode; private String authToken; private ArrayList<String> responses; public Handler(String roomId, int statusCode, String authToken, ArrayList<String> responses) { this.roomId = roomId; this.statusCode = statusCode; this.authToken = authToken; this.responses = responses; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { assertEquals(this.authToken, request.getHeader("Authorization").split(" ")[1]); assertEquals(this.roomId, target.split("/")[2]); response.setContentType("text/html;charset=utf-8"); response.setStatus(this.statusCode); baseRequest.setHandled(true); ServletInputStream inputStream = request.getInputStream(); String body = new Scanner(inputStream, "UTF-8").useDelimiter("\\A").next(); this.responses.add(body); } } // Setup HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri.toString()); configuration.setApiToken(expectedToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); SimpleServer server = new SimpleServer(port, new Handler(expectedRoomId, expectedStatusCode, expectedToken, responses)); server.start(); // Execute processor.sendNotification(notification, expectedRoomId); // Clean up server.stop(); // Test assertEquals(1, responses.size()); assertEquals(expectedJson, responses.get(0)); } @Test public void testSendNotificationException() throws Exception { // Test parameters String expectedExceptionText = "UnsupportedSchemeException"; int port = 8080; String uri = String.format("nohttp://localhost:%s/", port); String token = "token"; // Setup ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Appender appender = new WriterAppender(new PatternLayout("%m%n"), outputStream); logger.addAppender(appender); HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); // Execute processor.sendNotification(new HipChatRoomNotification(null, null, null, false), "1"); logger.removeAppender(appender); // Test boolean exceptionFound = false; String logOutput = new String(outputStream.toByteArray()); for (String line : logOutput.split("\n")) { if (line.contains(expectedExceptionText)) { exceptionFound = true; break; } } assertTrue(exceptionFound); } @Test public void testSendNotificationUndeliverable() throws Exception { // Test parameters String expectedExceptionText = "Message could not be delivered: 400 Bad Request"; int expectedStatusCode = HttpServletResponse.SC_BAD_REQUEST; String expectedRoomId = "1"; String expectedToken = "token"; int port = 8080; URI uri = new URI(String.format("http://localhost:%s/", port)); HipChatRoomNotification notification = new HipChatRoomNotification("foo", "text", "black", true); // Setup ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Appender appender = new WriterAppender(new PatternLayout("%m%n"), outputStream); logger.addAppender(appender); // Handler class Handler extends AbstractHandler { private int statusCode; public Handler(int statusCode) { this.statusCode = statusCode; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setStatus(this.statusCode); baseRequest.setHandled(true); } } // Setup HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri.toString()); configuration.setApiToken(expectedToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); SimpleServer server = new SimpleServer(port, new Handler(expectedStatusCode)); server.start(); // Execute processor.sendNotification(notification, expectedRoomId); // Clean up logger.removeAppender(appender); server.stop(); // Test boolean exceptionFound = false; String logOutput = new String(outputStream.toByteArray()); for (String line : logOutput.split("\n")) { if (line.contains(expectedExceptionText)) { exceptionFound = true; break; } } assertTrue(exceptionFound); } @Test public void testProxySupport() throws Exception { // Test parameters int expectedStatusCode = HttpServletResponse.SC_ACCEPTED; String host = "localhost"; int port = 8080; URI uri = new URI(String.format("http://%s:%s/", host, port)); String token = "token"; // Handler class Handler extends AbstractHandler { private int statusCode; private String authToken; public Handler(int statusCode, String authToken) { this.statusCode = statusCode; this.authToken = authToken; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { assertEquals(this.authToken, request.getParameter("auth_token")); assertEquals("true", request.getParameter("auth_test")); response.setContentType("text/html;charset=utf-8"); response.setStatus(this.statusCode); baseRequest.setHandled(true); } } // Setup // TODO: A more correct test would be to actually start up a proxy server here on another port. Properties systemProperties = new Properties(); systemProperties.setProperty("http.proxyHost", host); systemProperties.setProperty("http.proxyPort", Integer.toString(port)); HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri.toString()); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration, systemProperties); SimpleServer server = new SimpleServer(port, new Handler(expectedStatusCode, token)); server.start(); // Execute boolean actualAuthResult = processor.testAuthentication(); // Clean up server.stop(); // Test assertTrue(actualAuthResult); } @Test public void testTestAuthenticationSuccess() throws Exception { // Test parameters int expectedStatusCode = HttpServletResponse.SC_ACCEPTED; int port = 8080; URI uri = new URI(String.format("http://localhost:%s/", port)); String token = "token"; // Handler class Handler extends AbstractHandler { private int statusCode; private String authToken; public Handler(int statusCode, String authToken) { this.statusCode = statusCode; this.authToken = authToken; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { assertEquals(this.authToken, request.getParameter("auth_token")); assertEquals("true", request.getParameter("auth_test")); response.setContentType("text/html;charset=utf-8"); response.setStatus(this.statusCode); baseRequest.setHandled(true); } } // Setup HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri.toString()); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); SimpleServer server = new SimpleServer(port, new Handler(expectedStatusCode, token)); server.start(); // Execute boolean actualAuthResult = processor.testAuthentication(); // Clean up server.stop(); // Test assertTrue(actualAuthResult); } @Test public void testTestAuthenticationBypassSslCertCheckSuccess() throws Exception { // Test parameters boolean bypassSsl = true; int expectedStatusCode = HttpServletResponse.SC_ACCEPTED; String host = "localhost"; int httpsPort = 8443; URI uri = new URI(String.format("https://%s:%s/v2/", host, httpsPort)); String token = "token"; // Setup HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setBypassSslCheck(bypassSsl); configuration.setApiUrl(uri.toString()); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); // Mocks WireMockConfiguration config = wireMockConfig().httpsPort(httpsPort); WireMockServer wireMockServer = new WireMockServer(config); wireMockServer.start(); WireMock.configure(); stubFor(get(urlMatching("/v2/.*")).willReturn(aResponse().withStatus(expectedStatusCode))); try { // Execute boolean actualAuthResult = processor.testAuthentication(); // Test assertTrue(actualAuthResult); } finally { // Clean up wireMockServer.stop(); } } @Test public void testTestAuthenticationFailure() throws Exception { // Test parameters int expectedStatusCode = HttpServletResponse.SC_BAD_REQUEST; int port = 8080; URI uri = new URI(String.format("http://localhost:%s/", port)); String token = "token"; // Handler class Handler extends AbstractHandler { private int statusCode; public Handler(int statusCode) { this.statusCode = statusCode; } @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { assertEquals("true", request.getParameter("auth_test")); response.setContentType("text/html;charset=utf-8"); response.setStatus(this.statusCode); baseRequest.setHandled(true); } } // Setup HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri.toString()); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); SimpleServer server = new SimpleServer(port, new Handler(expectedStatusCode)); server.start(); // Execute boolean actualAuthResult = processor.testAuthentication(); // Clean up server.stop(); // Test assertFalse(actualAuthResult); } @Test public void testTestAuthenticationFailureWhenException() throws Exception { // Test parameters int port = 8080; String uri = String.format("nohttp://localhost:%s/", port); String token = "token"; // Setup HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(uri); configuration.setApiToken(token); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); // Execute boolean actualAuthResult = processor.testAuthentication(); // Test assertFalse(actualAuthResult); } @Test(enabled = false) public void testTestAuthentication() throws URISyntaxException { String apiUrl = "https://api.hipchat.com/v2/"; String apiToken = "token"; HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(apiUrl); configuration.setApiToken(apiToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); assertTrue(processor.testAuthentication()); } @Test(enabled = false) public void testTestAuthenticationWithSelfSignedCertManual() throws URISyntaxException { String apiUrl = "https://localhost/v2/"; String apiToken = "token"; HipChatConfiguration configuration = new HipChatConfiguration(); configuration.setApiUrl(apiUrl); configuration.setApiToken(apiToken); HipChatApiProcessor processor = new HipChatApiProcessor(configuration); assertTrue(processor.testAuthentication()); } }