package com.qcloud.weapp.test.tunnel; import org.junit.*; import static org.junit.Assert.*; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import static org.mockito.Mockito.*; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.qcloud.weapp.Configuration; import com.qcloud.weapp.ConfigurationException; import com.qcloud.weapp.ConfigurationManager; import com.qcloud.weapp.authorization.UserInfo; import com.qcloud.weapp.test.HttpMock; import com.qcloud.weapp.test.URLConnectionMock; import com.qcloud.weapp.tunnel.EmitError; import com.qcloud.weapp.tunnel.EmitResult; import com.qcloud.weapp.tunnel.Tunnel; import com.qcloud.weapp.tunnel.TunnelHandleOptions; import com.qcloud.weapp.tunnel.TunnelHandler; import com.qcloud.weapp.tunnel.TunnelMessage; import com.qcloud.weapp.tunnel.TunnelRoom; import com.qcloud.weapp.tunnel.TunnelService; public class TunnelServiceTest { private TunnelServiceTestHelper helper = new TunnelServiceTestHelper(); @Before public void setup() { Configuration config = new Configuration(); config.setServerHost("test.qcloud.la"); config.setAuthServerUrl("http://127.0.0.1:10086/auth"); config.setTunnelServerUrl("http://127.0.0.1:10086/tunnel"); config.setTunnelSignatureKey("test key"); config.setNetworkTimeout(1000); try { ConfigurationManager.setup(config); } catch (ConfigurationException e) { e.printStackTrace(); } } @Test public void testGetConnectionWithSession() { HttpMock httpMock = helper.createTunnelHttpMock("GET", "valid"); TunnelHandler handlerMock = mock(TunnelHandler.class); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandleOptions options = new TunnelHandleOptions(); options.setCheckLogin(true); try { service.handle(handlerMock, options); } catch (ConfigurationException e) { e.printStackTrace(); } try { JSONObject body = new JSONObject(httpMock.getResponseText()); assertNotNull(body.getString("url")); } catch (JSONException e) { fail(); } ArgumentCaptor<Tunnel> tunnel = ArgumentCaptor.forClass(Tunnel.class); ArgumentCaptor<UserInfo> userInfo = ArgumentCaptor.forClass(UserInfo.class); verify(handlerMock, only()).onTunnelRequest(tunnel.capture(), userInfo.capture()); assertNotNull(tunnel.getValue()); assertNotNull(userInfo.getValue()); } @Test public void testGetConnectionWithoutSession() { HttpMock httpMock = helper.createTunnelHttpMock("GET"); TunnelHandler handlerMock = mock(TunnelHandler.class); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandleOptions options = new TunnelHandleOptions(); options.setCheckLogin(false); try { service.handle(handlerMock, options); } catch (ConfigurationException e) { e.printStackTrace(); } try { JSONObject body = new JSONObject(httpMock.getResponseText()); assertNotNull(body.getString("url")); } catch (JSONException e) { fail(e.getMessage()); } ArgumentCaptor<Tunnel> tunnel = ArgumentCaptor.forClass(Tunnel.class); ArgumentCaptor<UserInfo> userInfo = ArgumentCaptor.forClass(UserInfo.class); verify(handlerMock, only()).onTunnelRequest(tunnel.capture(), userInfo.capture()); assertNotNull(tunnel.getValue()); assertNull(userInfo.getValue()); } @Test public void testGetConnectionWithInvalidSession() { HttpMock httpMock = helper.createTunnelHttpMock("GET", "invalid"); TunnelHandler handlerMock = mock(TunnelHandler.class); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandleOptions options = new TunnelHandleOptions(); options.setCheckLogin(true); try { service.handle(handlerMock, options); } catch (ConfigurationException e) { e.printStackTrace(); } try { JSONObject body = new JSONObject(httpMock.getResponseText()); assertTrue(helper.checkBodyHasMagicId(body)); assertNotNull(body.get("error")); } catch (JSONException e) { fail(); } verify(handlerMock, never()).onTunnelRequest(any(Tunnel.class), any(UserInfo.class)); } @Test public void testPostConnectPacket() throws JSONException, ConfigurationException { HttpMock httpMock = helper.createTunnelHttpMock("POST"); httpMock.setRequestBody(helper.buildPacket(new JSONObject() .put("type", "connect") .put("tunnelId", "tunnel1") .toString() )); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandler handlerMock = mock(TunnelHandler.class); service.handle(handlerMock, null); ArgumentCaptor<Tunnel> tunnel = ArgumentCaptor.forClass(Tunnel.class); verify(handlerMock, times(1)).onTunnelConnect(tunnel.capture()); verify(handlerMock, only()).onTunnelConnect(tunnel.capture()); assertEquals(tunnel.getValue().getTunnelId(), "tunnel1"); assertTrue(helper.checkPostResponseSuccess(httpMock.getResponseText())); } @Test public void testPostClosePacket() throws JSONException, ConfigurationException { HttpMock httpMock = helper.createTunnelHttpMock("POST"); httpMock.setRequestBody(helper.buildPacket(new JSONObject() .put("type", "close") .put("tunnelId", "tunnel1") .toString() )); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandler handlerMock = mock(TunnelHandler.class); service.handle(handlerMock, null); ArgumentCaptor<Tunnel> tunnel = ArgumentCaptor.forClass(Tunnel.class); verify(handlerMock, times(1)).onTunnelClose(tunnel.capture()); verify(handlerMock, only()).onTunnelClose(tunnel.capture()); assertEquals(tunnel.getValue().getTunnelId(), "tunnel1"); assertTrue(helper.checkPostResponseSuccess(httpMock.getResponseText())); } @Test public void testPostMessagePacket() throws JSONException, ConfigurationException { HttpMock httpMock = helper.createTunnelHttpMock("POST"); httpMock.setRequestBody(helper.buildPacket(new JSONObject() .put("type", "message") .put("tunnelId", "tunnel1") .put("content", new JSONObject() .put("type", "test-type") .put("content", "test-content") .toString() ) .toString() )); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandler handlerMock = mock(TunnelHandler.class); service.handle(handlerMock, null); ArgumentCaptor<Tunnel> tunnel = ArgumentCaptor.forClass(Tunnel.class); ArgumentCaptor<TunnelMessage> message = ArgumentCaptor.forClass(TunnelMessage.class); verify(handlerMock, times(1)).onTunnelMessage(tunnel.capture(), message.capture()); verify(handlerMock, only()).onTunnelMessage(tunnel.capture(), message.capture()); assertEquals("tunnel1", tunnel.getValue().getTunnelId()); assertEquals("test-type", message.getValue().getType()); assertEquals("test-content", message.getValue().getContent()); assertTrue(helper.checkPostResponseSuccess(httpMock.getResponseText())); } @Test public void testPostUnknownMessagePacket() throws JSONException, ConfigurationException { HttpMock httpMock = helper.createTunnelHttpMock("POST"); httpMock.setRequestBody(helper.buildPacket(new JSONObject() .put("type", "message") .put("tunnelId", "tunnel1") .put("content", "unknown-raw") .toString() )); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandler handlerMock = mock(TunnelHandler.class); service.handle(handlerMock, null); ArgumentCaptor<Tunnel> tunnel = ArgumentCaptor.forClass(Tunnel.class); ArgumentCaptor<TunnelMessage> message = ArgumentCaptor.forClass(TunnelMessage.class); verify(handlerMock, times(1)).onTunnelMessage(tunnel.capture(), message.capture()); assertEquals("tunnel1", tunnel.getValue().getTunnelId()); assertEquals("UnknownRaw", message.getValue().getType()); assertEquals("unknown-raw", message.getValue().getContent()); verifyNoMoreInteractions(handlerMock); assertTrue(helper.checkPostResponseSuccess(httpMock.getResponseText())); } @Test public void testPostUnknownPacket() throws JSONException, ConfigurationException { HttpMock httpMock = helper.createTunnelHttpMock("POST"); httpMock.setRequestBody(helper.buildPacket(new JSONObject() .put("type", "unknown") .put("tunnelId", "tunnel1") .toString() )); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandler handlerMock = mock(TunnelHandler.class); service.handle(handlerMock, null); Mockito.verifyZeroInteractions(handlerMock); assertTrue(helper.checkPostResponseSuccess(httpMock.getResponseText())); } @Test public void testPostPacketWithErrorSignature() throws JSONException, ConfigurationException { HttpMock httpMock = helper.createTunnelHttpMock("POST"); httpMock.setRequestBody(helper.buildPacket( new JSONObject() .put("type", "connect") .put("tunnelId", "tunnel1") .toString(), true )); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandler handlerMock = mock(TunnelHandler.class); service.handle(handlerMock, null); Mockito.verifyZeroInteractions(handlerMock); assertFalse(helper.checkPostResponseSuccess(httpMock.getResponseText())); } @Test public void testPostBadRequest() throws JSONException, ConfigurationException { HttpMock httpMock = helper.createTunnelHttpMock("POST"); httpMock.setRequestBody("illegal request"); TunnelService service = new TunnelService(httpMock.request, httpMock.response); TunnelHandler handlerMock = mock(TunnelHandler.class); service.handle(handlerMock, null); Mockito.verifyZeroInteractions(handlerMock); assertFalse(helper.checkPostResponseSuccess(httpMock.getResponseText())); } @Test public void testTunnelEmit() throws JSONException, EmitError { URLConnectionMock mock = helper.useURLConnectionMock(); try { mock.setResponseBody(new JSONObject().put("code", 0).toString()); Tunnel tunnel = Tunnel.getById("tunnel1"); tunnel.emit("test-type", "test-content"); JSONArray packets = helper.resolvePackets(mock.getRequestBody()); assertEquals(1, packets.length()); JSONObject firstPacket = packets.getJSONObject(0); assertEquals("tunnel1", firstPacket.getJSONArray("tunnelIds").getString(0)); assertEquals("message", firstPacket.getString("type")); JSONObject message = new JSONObject(firstPacket.getString("content")); assertEquals("test-type", message.getString("type")); assertEquals("test-content", message.getString("content")); } finally { helper.restoreURLConnectionMock(); } } @Test public void testEmitWithInvalidTunnels() throws JSONException, EmitError { URLConnectionMock mock = helper.useURLConnectionMock(); try { mock.setResponseBody(new JSONObject() .put("code", 0) .put("data", new JSONObject() .put("invalidTunnelIds", new JSONArray().put("tunnel1")) .toString() ) .toString() ); Tunnel tunnel = Tunnel.getById("tunnel1"); EmitResult result = tunnel.emit("test-type", new JSONObject().put("message", "test-content")); assertEquals(1, result.getTunnelInvalidInfos().size()); assertEquals("tunnel1", result.getTunnelInvalidInfos().get(0).getTunnelId()); } finally { helper.restoreURLConnectionMock(); } } @Test public void testTunnelClose() throws JSONException, EmitError { URLConnectionMock mock = helper.useURLConnectionMock(); try { mock.setResponseBody(new JSONObject().put("code", 0).toString()); Tunnel tunnel = Tunnel.getById("tunnel1"); tunnel.close(); JSONArray packets = helper.resolvePackets(mock.getRequestBody()); assertEquals(1, packets.length()); assertEquals("tunnel1", packets.getJSONObject(0).getJSONArray("tunnelIds").getString(0)); assertEquals("close", packets.getJSONObject(0).getString("type")); } finally { helper.restoreURLConnectionMock(); } } @Test public void testRoomBroadcast() throws JSONException, EmitError { URLConnectionMock mock = helper.useURLConnectionMock(); try { mock.setResponseBody(new JSONObject().put("code", 0).toString()); TunnelRoom room = new TunnelRoom(); room.addTunnel(Tunnel.getById("tunnel1")); room.addTunnel(Tunnel.getById("tunnel2")); assertEquals(2, room.getTunnelCount()); room.removeTunnelById("tunnel1"); assertEquals(1, room.getTunnelCount()); room.addTunnel(Tunnel.getById("tunnel3")); room.broadcast("test-type", "test-message"); JSONArray packets = helper.resolvePackets(mock.getRequestBody()); assertEquals(1, packets.length()); JSONObject firstPacket = packets.getJSONObject(0); assertEquals(2, firstPacket.getJSONArray("tunnelIds").length()); assertEquals("tunnel2", firstPacket.getJSONArray("tunnelIds").get(0)); assertEquals("tunnel3", firstPacket.getJSONArray("tunnelIds").get(1)); assertEquals("message", firstPacket.getString("type")); JSONObject message = new JSONObject(firstPacket.getString("content")); assertEquals("test-type", message.getString("type")); assertEquals("test-message", message.getString("content")); } finally { helper.restoreURLConnectionMock(); } } @Test public void testRoomBroadcastWithInvalidTunnels() throws JSONException, EmitError { URLConnectionMock mock = helper.useURLConnectionMock(); try { mock.setResponseBody(new JSONObject() .put("code", 0) .put("data", new JSONObject() .put("invalidTunnelIds", new JSONArray().put("tunnel1").put("tunnel2")) ) .toString() ); TunnelRoom room = new TunnelRoom(); room.addTunnel(Tunnel.getById("tunnel1")); room.addTunnel(Tunnel.getById("tunnel2")); room.addTunnel(Tunnel.getById("tunnel3")); EmitResult result = room.broadcast("test-type", "test-message"); assertEquals(2, result.getTunnelInvalidInfos().size()); assertEquals("tunnel1", result.getTunnelInvalidInfos().get(0).getTunnelId()); assertEquals("tunnel2", result.getTunnelInvalidInfos().get(1).getTunnelId()); } finally { helper.restoreURLConnectionMock(); } } }