package cc.blynk.integration.tcp; import cc.blynk.integration.IntegrationBase; import cc.blynk.integration.model.MockHolder; import cc.blynk.integration.model.tcp.TestAppClient; import cc.blynk.server.application.AppServer; import cc.blynk.server.core.BaseServer; import cc.blynk.server.core.model.Profile; import cc.blynk.server.core.protocol.enums.Command; import cc.blynk.server.core.protocol.model.messages.ResponseMessage; import cc.blynk.server.core.stats.GlobalStats; import cc.blynk.server.db.DBManager; import cc.blynk.server.workers.ProfileSaverWorker; import cc.blynk.utils.ReflectionUtil; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.OngoingStubbing; import java.io.BufferedReader; import java.util.Collection; import java.util.Collections; import java.util.Map; import static cc.blynk.server.core.protocol.enums.Command.APP_SYNC; import static cc.blynk.server.core.protocol.enums.Response.*; import static org.mockito.Mockito.*; /** * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 2/2/2015. * * Basic integration test. Allows to test base commands workflow. Thus netty is asynchronous * test is little bit complex, but I don't know right now how to make it better and simpler. * */ @RunWith(MockitoJUnitRunner.class) public class AppProtocolCommandsTest extends IntegrationBase { @Mock public BufferedReader bufferedReader; private BaseServer appServer; @Before public void init() throws Exception { this.appServer = new AppServer(holder).start(); ProfileSaverWorker profileSaverWorker = new ProfileSaverWorker(holder.userDao, holder.fileManager, new DBManager(blockingIOProcessor, holder.props.getBoolProperty("enable.db"))); new Thread(profileSaverWorker).start(); } @After public void shutdown() { this.appServer.close(); } @Test public void testCommandsIndexOk() { Map<Short, String> commandCodes = ReflectionUtil.generateMapOfValueNameShort(Command.class); Collection<Short> codes = commandCodes.keySet(); Short maxShort = Collections.max(codes); GlobalStats stat = new GlobalStats(); stat.mark(maxShort); } @Test public void testAppNotRegistered() throws Exception { makeCommands("login dmitriy@mail.ua 1").check(new ResponseMessage(1, USER_NOT_REGISTERED)); } @Test public void testIllegalCommandForHardLoginOnAppChannel() throws Exception { makeCommands("login dasdsadasdasdasdasdas").check(new ResponseMessage(1, ILLEGAL_COMMAND)); } @Test public void testLogin2Times() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands(1, "login dmitriy@mail.ua 1", "login dmitriy@mail.ua 1").check(1, OK); } @Test public void testLogin2TimesAndWork() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands(2, "login dmitriy@mail.ua 1", "login dmitriy@mail.ua 1", "getToken 1").check(1, OK).check(new ResponseMessage(1, ILLEGAL_COMMAND)); } @Test public void testGetTokenForNonExistentDashId() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login dmitriy@mail.ua 1", "getToken 1").check(OK).check(new ResponseMessage(1, ILLEGAL_COMMAND)); } @Test public void testRefreshToken() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); Profile profile = parseProfile(readTestUserProfile()); makeCommands("login dmitriy@mail.ua 1", "addEnergy 5000" + "\0" + "1235555", "createDash " + profile.dashBoards[0]).check(3, OK); //todo fix? makeCommands("login dmitriy@mail.ua 1", "getToken 1", "refreshToken 1") .check(OK); //.check(2, produce(1, REFRESH_TOKEN, "12345678901234567890123456789012")); } @Test @Ignore //todo fix public void testProfileWithManyDashes() throws Exception { makeCommands("register dmitriy@mail.ua 1", "login dmitriy@mail.ua 1", "addEnergy 5000").check(3, OK); Profile profile = parseProfile(readTestUserProfile("user_profile_json_many_dashes.txt")); String[] cmds = new String[profile.dashBoards.length + 1]; cmds[0] = "login dmitriy@mail.ua 1"; for (int i = 0; i < profile.dashBoards.length; i++) { cmds[i + 1] = "createDash " + profile.dashBoards[i]; } makeCommands(cmds).check(profile.dashBoards.length, OK).check(new ResponseMessage(1, QUOTA_LIMIT)); } @Test public void testPassNotValid() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login dmitriy@mail.ua 2").check(new ResponseMessage(1, USER_NOT_AUTHENTICATED)); } @Test public void testActivateWrongFormat() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login dmitriy@mail.ua 1", "activate ").check(new ResponseMessage(1, ILLEGAL_COMMAND)); } @Test @Ignore //todo fix? public void testActivateWorks() throws Exception { String userProfileString = readTestUserProfile(); makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login dmitriy@mail.ua 1", "saveProfile " + userProfileString).check(2, OK); makeCommands("activate 1").check(10, APP_SYNC); } @Test public void testActivateWrongDashId() throws Exception { Profile profile = parseProfile(readTestUserProfile()); makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login dmitriy@mail.ua 1", "addEnergy 5000" + "\0" + "123444", "createDash " + profile.dashBoards[0], "activate 2").check(3, OK).check(new ResponseMessage(1, ILLEGAL_COMMAND)); } @Test public void testActivateBadId() throws Exception { Profile profile = parseProfile(readTestUserProfile()); makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login dmitriy@mail.ua 1", "addEnergy 5000" + "\0" + "123333", "createDash " + profile.dashBoards[0], "activate xxx").check(3, OK).check(new ResponseMessage(1, ILLEGAL_COMMAND)); } @Test public void testTryHardLoginInAppChannel() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login adsadasdasdasdas").check(new ResponseMessage(1, ILLEGAL_COMMAND)); } @Test //all commands together cause all operations requires register and then login =(. public void testPingOk() throws Exception { makeCommands("register dmitriy@mail.ua 1").check(OK); makeCommands("login dmitriy@mail.ua 1", "ping").check(2, OK); } /** * 1) Creates client socket; * 2) Sends commands; * 3) Sleeps for 100ms between every command send; * 4) Checks that sever response is OK; * 5) Closing socket. */ private MockHolder makeCommands(int expected, String... commands) throws Exception { TestAppClient appClient = new TestAppClient("localhost", tcpAppPort); OngoingStubbing<String> ongoingStubbing = when(bufferedReader.readLine()); for (String cmd : commands) { ongoingStubbing = ongoingStubbing.thenReturn(cmd); } ongoingStubbing.thenAnswer(invocation -> { //todo think how to avoid this sleep(400); return "quit"; }); appClient.start(bufferedReader); verify(appClient.responseMock, times(expected)).channelRead(any(), any()); return new MockHolder(appClient.responseMock); } private MockHolder makeCommands(String... commands) throws Exception { return makeCommands(commands.length, commands); } }