package cc.blynk.integration.tcp;
import cc.blynk.integration.IntegrationBase;
import cc.blynk.integration.model.tcp.ClientPair;
import cc.blynk.integration.model.tcp.TestAppClient;
import cc.blynk.integration.model.tcp.TestHardClient;
import cc.blynk.server.application.AppServer;
import cc.blynk.server.core.BaseServer;
import cc.blynk.server.core.dao.ReportingDao;
import cc.blynk.server.core.model.DashBoard;
import cc.blynk.server.core.model.DashboardSettings;
import cc.blynk.server.core.model.Profile;
import cc.blynk.server.core.model.device.Device;
import cc.blynk.server.core.model.enums.GraphType;
import cc.blynk.server.core.model.enums.PinType;
import cc.blynk.server.core.model.enums.Theme;
import cc.blynk.server.core.model.widgets.OnePinWidget;
import cc.blynk.server.core.model.widgets.Widget;
import cc.blynk.server.core.model.widgets.controls.Step;
import cc.blynk.server.core.model.widgets.others.Player;
import cc.blynk.server.core.model.widgets.ui.TimeInput;
import cc.blynk.server.core.protocol.model.messages.BinaryMessage;
import cc.blynk.server.core.protocol.model.messages.ResponseMessage;
import cc.blynk.server.core.protocol.model.messages.StringMessage;
import cc.blynk.server.core.protocol.model.messages.appllication.GetTokenMessage;
import cc.blynk.server.core.protocol.model.messages.common.HardwareConnectedMessage;
import cc.blynk.server.hardware.HardwareServer;
import cc.blynk.utils.ByteUtils;
import cc.blynk.utils.FileUtils;
import cc.blynk.utils.JsonParser;
import io.netty.channel.ChannelFuture;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.runners.MockitoJUnitRunner;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.ZoneId;
import java.util.List;
import static cc.blynk.server.core.protocol.enums.Command.GET_ENERGY;
import static cc.blynk.server.core.protocol.enums.Command.HARDWARE;
import static cc.blynk.server.core.protocol.enums.Response.*;
import static cc.blynk.server.core.protocol.model.messages.MessageFactory.produce;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* The Blynk Project.
* Created by Dmitriy Dumanskiy.
* Created on 2/2/2015.
*
*/
@RunWith(MockitoJUnitRunner.class)
public class MainWorkflowTest extends IntegrationBase {
private BaseServer appServer;
private BaseServer hardwareServer;
private ClientPair clientPair;
@Before
public void init() throws Exception {
this.hardwareServer = new HardwareServer(holder).start();
this.appServer = new AppServer(holder).start();
this.clientPair = initAppAndHardPair();
}
@After
public void shutdown() {
this.appServer.close();
this.hardwareServer.close();
this.clientPair.stop();
}
@Test
public void createBasicProfile() throws Exception {
TestAppClient appClient = new TestAppClient("localhost", tcpAppPort, properties);
appClient.start();
appClient.send("register test@test.com 1");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
appClient.send("login test@test.com 1 Android RC13");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
appClient.send("createDash {\"id\":1, \"createdAt\":1, \"name\":\"test board\"}\"");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
appClient.send("createWidget 1\0{\"id\":1, \"width\":1, \"height\":1, \"x\":0, \"y\":0, \"label\":\"Some Text\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":1}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
appClient.reset();
appClient.send("loadProfileGzipped");
Profile profile = parseProfile(appClient.getBody());
profile.dashBoards[0].updatedAt = 0;
assertEquals("{\"dashBoards\":[{\"id\":1,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board\",\"createdAt\":1,\"updatedAt\":0,\"widgets\":[{\"type\":\"BUTTON\",\"id\":1,\"x\":0,\"y\":0,\"color\":0,\"width\":1,\"height\":1,\"tabId\":0,\"label\":\"Some Text\",\"isEnabled\":true,\"isDefaultColor\":false,\"deviceId\":0,\"pinType\":\"DIGITAL\",\"pin\":1,\"pwmMode\":false,\"rangeMappingOn\":false,\"min\":0,\"max\":0,\"pushMode\":false}],\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":false}]}", profile.toString());
appClient.send("createWidget 1\0{\"id\":2, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":2}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
appClient.reset();
appClient.send("loadProfileGzipped");
profile = parseProfile(appClient.getBody());
profile.dashBoards[0].updatedAt = 0;
assertEquals("{\"dashBoards\":[{\"id\":1,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board\",\"createdAt\":1,\"updatedAt\":0,\"widgets\":[{\"type\":\"BUTTON\",\"id\":1,\"x\":0,\"y\":0,\"color\":0,\"width\":1,\"height\":1,\"tabId\":0,\"label\":\"Some Text\",\"isEnabled\":true,\"isDefaultColor\":false,\"deviceId\":0,\"pinType\":\"DIGITAL\",\"pin\":1,\"pwmMode\":false,\"rangeMappingOn\":false,\"min\":0,\"max\":0,\"pushMode\":false},{\"type\":\"BUTTON\",\"id\":2,\"x\":2,\"y\":2,\"color\":0,\"width\":1,\"height\":1,\"tabId\":0,\"label\":\"Some Text 2\",\"isEnabled\":true,\"isDefaultColor\":false,\"deviceId\":0,\"pinType\":\"DIGITAL\",\"pin\":2,\"pwmMode\":false,\"rangeMappingOn\":false,\"min\":0,\"max\":0,\"pushMode\":false}],\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":false}]}", profile.toString());
appClient.send("updateWidget 1\0{\"id\":2, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"new label\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":3}\"");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
appClient.reset();
appClient.send("loadProfileGzipped");
profile = parseProfile(appClient.getBody());
profile.dashBoards[0].updatedAt = 0;
assertEquals("{\"dashBoards\":[{\"id\":1,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board\",\"createdAt\":1,\"updatedAt\":0,\"widgets\":[{\"type\":\"BUTTON\",\"id\":1,\"x\":0,\"y\":0,\"color\":0,\"width\":1,\"height\":1,\"tabId\":0,\"label\":\"Some Text\",\"isEnabled\":true,\"isDefaultColor\":false,\"deviceId\":0,\"pinType\":\"DIGITAL\",\"pin\":1,\"pwmMode\":false,\"rangeMappingOn\":false,\"min\":0,\"max\":0,\"pushMode\":false},{\"type\":\"BUTTON\",\"id\":2,\"x\":2,\"y\":2,\"color\":0,\"width\":1,\"height\":1,\"tabId\":0,\"label\":\"new label\",\"isEnabled\":true,\"isDefaultColor\":false,\"deviceId\":0,\"pinType\":\"DIGITAL\",\"pin\":3,\"pwmMode\":false,\"rangeMappingOn\":false,\"min\":0,\"max\":0,\"pushMode\":false}],\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":false}]}", profile.toString());
appClient.send("deleteWidget 1\0" + "3");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, ILLEGAL_COMMAND)));
appClient.send("deleteWidget 1\0" + "1");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
appClient.send("deleteWidget 1\0" + "2");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
appClient.reset();
appClient.send("loadProfileGzipped");
profile = parseProfile(appClient.getBody());
profile.dashBoards[0].updatedAt = 0;
assertEquals("{\"dashBoards\":[{\"id\":1,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board\",\"createdAt\":1,\"updatedAt\":0,\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":false}]}", profile.toString());
}
@Test
public void doNotAllowUsersWithQuestionMark() throws Exception {
TestAppClient appClient = new TestAppClient("localhost", tcpAppPort, properties);
appClient.start();
appClient.send("register te?st@test.com 1");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, ILLEGAL_COMMAND)));
}
@Test
public void createDashWithDevices() throws Exception {
TestAppClient appClient = new TestAppClient("localhost", tcpAppPort, properties);
appClient.start();
appClient.send("register test@test.com 1");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
appClient.send("login test@test.com 1 Android RC13");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
DashBoard dash = new DashBoard();
dash.id = 1;
dash.name = "AAAa";
Device device = new Device();
device.id = 0;
device.name = "123";
dash.devices = new Device[] {device};
appClient.send("createDash no_token\0" + dash.toString());
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
appClient.send("getDevices 1");
String response = appClient.getBody(4);
Device[] devices = JsonParser.mapper.readValue(response, Device[].class);
assertNotNull(devices);
assertEquals(1, devices.length);
assertEquals(0, devices[0].id);
assertEquals("123", devices[0].name);
assertNull(devices[0].token);
}
@Test
public void testConnectAppAndHardware() throws Exception {
// we just test that app and hardware can actually connect
}
@Test
public void testRegisterWithAnotherApp() throws Exception {
TestAppClient appClient = new TestAppClient("localhost", tcpAppPort, properties);
appClient.start();
appClient.send("register test@test.com 1 MyApp");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
appClient.send("login test@test.com 1 Android 1.13.3 MyApp");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
appClient.send("createDash {\"id\":1, \"createdAt\":1, \"name\":\"test board\"}\"");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
appClient.send("createWidget 1\0{\"id\":1, \"width\":1, \"height\":1, \"x\":0, \"y\":0, \"label\":\"Some Text\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":1}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
appClient.reset();
appClient.send("loadProfileGzipped");
Profile profile = parseProfile(appClient.getBody());
profile.dashBoards[0].updatedAt = 0;
assertEquals("{\"dashBoards\":[{\"id\":1,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board\",\"createdAt\":1,\"updatedAt\":0,\"widgets\":[{\"type\":\"BUTTON\",\"id\":1,\"x\":0,\"y\":0,\"color\":0,\"width\":1,\"height\":1,\"tabId\":0,\"label\":\"Some Text\",\"isEnabled\":true,\"isDefaultColor\":false,\"deviceId\":0,\"pinType\":\"DIGITAL\",\"pin\":1,\"pwmMode\":false,\"rangeMappingOn\":false,\"min\":0,\"max\":0,\"pushMode\":false}],\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":false}]}", profile.toString());
}
@Test
public void testDoubleLogin() throws Exception {
clientPair.hardwareClient.send("login " + DEFAULT_TEST_USER + " 1");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, USER_ALREADY_REGISTERED)));
}
@Test
public void testValueForPWMPinForStteperIsAccepted() throws Exception {
clientPair.appClient.send("createWidget 1\0{\"id\":743, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"STEP\", \"pwmMode\":true, \"pinType\":\"DIGITAL\", \"pin\":24}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(ok(1)));
clientPair.appClient.send("hardware 1 aw 24 100");
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("aw 24 100"))));
clientPair.appClient.send("loadProfileGzipped");
Profile profile = parseProfile(clientPair.appClient.getBody(2));
assertNotNull(profile);
Widget widget = profile.dashBoards[0].findWidgetByPin(0, (byte) 24, PinType.DIGITAL);
assertNotNull(widget);
assertTrue(widget instanceof Step);
assertEquals("100", ((OnePinWidget) widget).value);
}
@Test
public void testNoEnergyDrainForBusinessApps() throws Exception {
TestAppClient appClient = new TestAppClient("localhost", tcpAppPort, properties);
appClient.start();
appClient.send("register test@test.com 1 MyApp");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
appClient.send("login test@test.com 1 Android 1.13.3 MyApp");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
appClient.send("createDash {\"id\":2, \"createdAt\":1458856800001, \"name\":\"test board\"}\"");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
appClient.send("getEnergy");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(4, GET_ENERGY, "2000")));
appClient.send("createWidget 2\0{\"id\":2, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"LCD\", \"pinType\":\"DIGITAL\", \"pin\":2}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(5, OK)));
appClient.send("createWidget 2\0{\"id\":3, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"LCD\", \"pinType\":\"DIGITAL\", \"pin\":2}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(6, OK)));
appClient.send("createWidget 2\0{\"id\":4, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"LCD\", \"pinType\":\"DIGITAL\", \"pin\":2}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(7, OK)));
appClient.send("createWidget 2\0{\"id\":5, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"LCD\", \"pinType\":\"DIGITAL\", \"pin\":2}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(8, OK)));
appClient.send("createWidget 2\0{\"id\":6, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"LCD\", \"pinType\":\"DIGITAL\", \"pin\":2}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(9, OK)));
appClient.send("createWidget 2\0{\"id\":7, \"width\":1, \"height\":1, \"x\":2, \"y\":2, \"label\":\"Some Text 2\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":2}");
verify(appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(10, OK)));
}
@Test
public void testPingCommandWorks() throws Exception {
clientPair.appClient.send("ping");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
}
@Test
public void testAddAndRemoveTabs() throws Exception {
clientPair.appClient.send("loadProfileGzipped");
Profile profile = parseProfile(clientPair.appClient.getBody());
assertEquals(16, profile.dashBoards[0].widgets.length);
clientPair.appClient.send("getEnergy");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(2, GET_ENERGY, "7500")));
clientPair.appClient.send("createWidget 1\0{\"id\":100, \"width\":1, \"height\":1, \"x\":0, \"y\":0, \"tabs\":[{\"label\":\"tab 1\"}, {\"label\":\"tab 2\"}, {\"label\":\"tab 3\"}], \"type\":\"TABS\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
clientPair.appClient.send("createWidget 1\0{\"id\":101, \"width\":1, \"height\":1, \"x\":15, \"y\":0, \"tabId\":1, \"label\":\"Some Text\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":18}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
clientPair.appClient.send("createWidget 1\0{\"id\":102, \"width\":1, \"height\":1, \"x\":5, \"y\":0, \"tabId\":0, \"label\":\"Some Text\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":17}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(5, OK)));
clientPair.appClient.send("getEnergy");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(6, GET_ENERGY, "7100")));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
assertEquals(19, profile.dashBoards[0].widgets.length);
clientPair.appClient.send("deleteWidget 1\0" + "100");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
clientPair.appClient.send("getEnergy");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(3, GET_ENERGY, "7300")));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
assertEquals(17, profile.dashBoards[0].widgets.length);
assertNotNull(profile.dashBoards[0].findWidgetByPin(0, (byte) 17, PinType.DIGITAL));
}
@Test
public void testAddAndUpdateTabs() throws Exception {
clientPair.appClient.send("loadProfileGzipped");
Profile profile = parseProfile(clientPair.appClient.getBody());
assertEquals(16, profile.dashBoards[0].widgets.length);
clientPair.appClient.send("getEnergy");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(2, GET_ENERGY, "7500")));
clientPair.appClient.send("createWidget 1\0{\"id\":100, \"width\":1, \"height\":1, \"x\":0, \"y\":0, \"tabs\":[{\"label\":\"tab 1\"}, {\"label\":\"tab 2\"}, {\"label\":\"tab 3\"}], \"type\":\"TABS\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
clientPair.appClient.send("createWidget 1\0{\"id\":101, \"width\":1, \"height\":1, \"x\":15, \"y\":0, \"tabId\":1, \"label\":\"Some Text\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":18}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
clientPair.appClient.send("createWidget 1\0{\"id\":102, \"width\":1, \"height\":1, \"x\":5, \"y\":0, \"tabId\":2, \"label\":\"Some Text\", \"type\":\"BUTTON\", \"pinType\":\"DIGITAL\", \"pin\":17}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(5, OK)));
clientPair.appClient.send("getEnergy");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(6, GET_ENERGY, "7100")));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
assertEquals(19, profile.dashBoards[0].widgets.length);
clientPair.appClient.send("updateWidget 1\0{\"id\":100, \"width\":1, \"height\":1, \"x\":0, \"y\":0, \"tabs\":[{\"label\":\"tab 1\"}, {\"label\":\"tab 2\"}], \"type\":\"TABS\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
clientPair.appClient.send("getEnergy");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(3, GET_ENERGY, "7300")));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
assertEquals(18, profile.dashBoards[0].widgets.length);
assertNull(profile.dashBoards[0].findWidgetByPin(0, (byte) 17, PinType.DIGITAL));
assertNotNull(profile.dashBoards[0].findWidgetByPin(0, (byte) 18, PinType.DIGITAL));
}
@Test
public void testPurchaseEnergy() throws Exception {
clientPair.appClient.send("addEnergy " + "1000" + "\0" + "5262996016779471529.4493624392154338");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, NOT_ALLOWED)));
clientPair.appClient.send("addEnergy " + "1000" + "\0" + "A3B93EE9-BC65-499E-A660-F2A84F2AF1FC");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, NOT_ALLOWED)));
clientPair.appClient.send("addEnergy " + "1000" + "\0" + "com.blynk.energy.280001461578468247");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, NOT_ALLOWED)));
clientPair.appClient.send("addEnergy " + "1000");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, NOT_ALLOWED)));
clientPair.appClient.send("addEnergy " + "1000" + "\0");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(5, NOT_ALLOWED)));
clientPair.appClient.send("addEnergy " + "1000" + "\0" + "150000195113772");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(6, OK)));
clientPair.appClient.send("addEnergy " + "1000" + "\0" + "1370-3990-1414-55681");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(7, OK)));
}
@Test
@Ignore
public void testProfileMetadata() throws Exception {
clientPair.appClient.send("saveMetadata {\"lat\":123.123,\"lon\":124.124}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.appClient.reset();
clientPair.appClient.send("getMetadata");
String token = clientPair.appClient.getBody();
assertNotNull(token);
assertEquals("{\"lat\":123.123,\"lon\":124.124}", token);
}
@Test
public void testApplicationPingCommandOk() throws Exception {
clientPair.appClient.send("ping");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.appClient.reset();
clientPair.appClient.send("ping");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
}
@Test
public void testHardPingCommandOk() throws Exception {
clientPair.hardwareClient.send("ping");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.hardwareClient.send("ping");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
}
@Test
public void testDashCommands() throws Exception {
clientPair.appClient.send("updateDash {\"id\":10, \"name\":\"test board update\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, ILLEGAL_COMMAND)));
clientPair.appClient.send("createDash {\"id\":10, \"name\":\"test board\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
clientPair.appClient.send("createDash {\"id\":10, \"name\":\"test board\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, NOT_ALLOWED)));
clientPair.appClient.send("updateDash {\"id\":10, \"name\":\"test board update\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
clientPair.hardwareClient.send("ping");
clientPair.appClient.send("deleteDash 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(5, OK)));
clientPair.appClient.send("deleteDash 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(6, ILLEGAL_COMMAND)));
Profile responseProfile;
DashBoard responseDash;
clientPair.appClient.send("loadProfileGzipped");
responseProfile = parseProfile(clientPair.appClient.getBody(7));
responseProfile.dashBoards[0].updatedAt = 0;
responseProfile.dashBoards[0].createdAt = 0;
assertEquals("{\"dashBoards\":[{\"id\":10,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board update\",\"createdAt\":0,\"updatedAt\":0,\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":false}]}", responseProfile.toString());
clientPair.appClient.send("loadProfileGzipped 10");
responseDash = JsonParser.parseDashboard(clientPair.appClient.getBody(8));
responseDash.updatedAt = 0;
responseDash.createdAt = 0;
assertEquals("{\"id\":10,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board update\",\"createdAt\":0,\"updatedAt\":0,\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":false}", responseDash.toString());
clientPair.appClient.send("loadProfileGzipped 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(9, ILLEGAL_COMMAND)));
clientPair.appClient.send("activate 10");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(10, DEVICE_NOT_IN_NETWORK)));
clientPair.appClient.send("loadProfileGzipped");
responseProfile = parseProfile(clientPair.appClient.getBody(11));
responseProfile.dashBoards[0].updatedAt = 0;
responseProfile.dashBoards[0].createdAt = 0;
String expectedProfile = "{\"dashBoards\":[{\"id\":10,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board update\",\"createdAt\":0,\"updatedAt\":0,\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":true}]}";
assertEquals(expectedProfile, responseProfile.toString());
clientPair.appClient.send("updateDash {\"id\":10,\"name\":\"test board update\",\"keepScreenOn\":false,\"isShared\":false,\"isActive\":false}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
expectedProfile = "{\"dashBoards\":[{\"id\":10,\"parentId\":-1,\"isPreview\":false,\"name\":\"test board update\",\"createdAt\":0,\"updatedAt\":0,\"theme\":\"Blynk\",\"keepScreenOn\":false,\"isAppConnectedOn\":false,\"isShared\":false,\"isActive\":true}]}";
clientPair.appClient.send("loadProfileGzipped");
responseProfile = parseProfile(clientPair.appClient.getBody(13));
responseProfile.dashBoards[0].updatedAt = 0;
responseProfile.dashBoards[0].createdAt = 0;
assertEquals(expectedProfile, responseProfile.toString());
}
@Test
public void testHardwareChannelClosedOnDashRemoval() throws Exception {
clientPair.appClient.send("deleteDash 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
assertTrue(clientPair.hardwareClient.isClosed());
}
@Test
public void deleteDashDeletesTokensAlso() throws Exception {
clientPair.appClient.send("createDash {\"id\":10, \"name\":\"test board\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.appClient.reset();
clientPair.appClient.send("getToken 10");
String token = clientPair.appClient.getBody();
assertNotNull(token);
clientPair.appClient.reset();
clientPair.appClient.send("getShareToken 10");
String sharedToken = clientPair.appClient.getBody();
assertNotNull(sharedToken);
clientPair.appClient.send("deleteDash 10");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
//todo on delete also close existing connections?
TestHardClient newHardClient = new TestHardClient("localhost", tcpHardPort);
newHardClient.start();
newHardClient.send("login " + token);
verify(newHardClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, INVALID_TOKEN)));
TestAppClient newAppClient = new TestAppClient("localhost", tcpAppPort, properties);
newAppClient.start();
newAppClient.send("shareLogin " + "dima@mail.ua " + sharedToken + " Android 24");
verify(newAppClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(1, NOT_ALLOWED)));
}
@Test
public void loadGzippedProfile() throws Exception{
String expected = readTestUserProfile();
clientPair.appClient.send("loadProfileGzipped");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), any());
Profile profile = parseProfile(clientPair.appClient.getBody());
profile.dashBoards[0].updatedAt = 0;
//todo fix
profile.dashBoards[0].devices = null;
assertEquals(expected, profile.toString());
}
@Test
public void settingsUpdateCommand() throws Exception{
DashboardSettings settings = new DashboardSettings();
settings.name = "New Name";
settings.isAppConnectedOn = true;
settings.isShared = true;
settings.keepScreenOn = true;
settings.theme = Theme.BlynkLight;
clientPair.appClient.send("updateSettings 1\0" + JsonParser.toJson(settings));
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(ok(1)));
clientPair.appClient.send("loadProfileGzipped");
Profile profile = parseProfile(clientPair.appClient.getBody(2));
DashBoard dashBoard = profile.dashBoards[0];
assertNotNull(dashBoard);
assertEquals(settings.name, dashBoard.name);
assertEquals(settings.isAppConnectedOn, dashBoard.isAppConnectedOn);
assertEquals(settings.isShared, dashBoard.isShared);
assertEquals(settings.keepScreenOn, dashBoard.keepScreenOn);
assertEquals(settings.theme, dashBoard.theme);
}
@Test
public void testGetGraphDataFor1Pin() throws Exception {
String tempDir = holder.props.getProperty("data.folder");
final Path userReportFolder = Paths.get(tempDir, "data", DEFAULT_TEST_USER);
if (Files.notExists(userReportFolder)) {
Files.createDirectories(userReportFolder);
}
Path pinReportingDataPath = Paths.get(tempDir, "data", DEFAULT_TEST_USER, ReportingDao.generateFilename(1, 0, PinType.DIGITAL.pintTypeChar, (byte) 8, GraphType.HOURLY));
FileUtils.write(pinReportingDataPath, 1.11D, 1111111);
FileUtils.write(pinReportingDataPath, 1.22D, 2222222);
clientPair.appClient.send("getgraphdata 1 d 8 24 h");
ArgumentCaptor<BinaryMessage> objectArgumentCaptor = ArgumentCaptor.forClass(BinaryMessage.class);
verify(clientPair.appClient.responseMock, timeout(1000)).channelRead(any(), objectArgumentCaptor.capture());
BinaryMessage graphDataResponse = objectArgumentCaptor.getValue();
assertNotNull(graphDataResponse);
byte[] decompressedGraphData = ByteUtils.decompress(graphDataResponse.getBytes());
ByteBuffer bb = ByteBuffer.wrap(decompressedGraphData);
assertEquals(1, bb.getInt());
assertEquals(2, bb.getInt());
assertEquals(1.11D, bb.getDouble(), 0.1);
assertEquals(1111111, bb.getLong());
assertEquals(1.22D, bb.getDouble(), 0.1);
assertEquals(2222222, bb.getLong());
}
@Test
public void testDeleteGraphCommandWorks() throws Exception {
clientPair.appClient.send("getgraphdata 1 d 8 del");
verify(clientPair.appClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(1, OK)));
}
@Test
public void testExportDataFromHistoryGraph() throws Exception {
clientPair.appClient.send("export 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, ILLEGAL_COMMAND)));
clientPair.appClient.send("export 1 666");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, ILLEGAL_COMMAND)));
clientPair.appClient.send("export 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, ILLEGAL_COMMAND)));
clientPair.appClient.send("export 1 14");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, NO_DATA)));
//generate fake reporting data
Path userReportDirectory = Paths.get(holder.props.getProperty("data.folder"), "data", DEFAULT_TEST_USER);
Files.createDirectories(userReportDirectory);
Path userReportFile = Paths.get(userReportDirectory.toString(), ReportingDao.generateFilename(1, 0, PinType.ANALOG.pintTypeChar, (byte) 7, GraphType.MINUTE));
FileUtils.write(userReportFile, 1.1, 1L);
FileUtils.write(userReportFile, 2.2, 2L);
clientPair.appClient.send("export 1 14");
verify(mailWrapper, timeout(1000)).sendHtml(eq(DEFAULT_TEST_USER), eq("History graph data for project My Dashboard"), contains("/dima@mail.ua_1_a7.csv.gz"));
}
@Test
@Ignore
public void testLargeMessageIsNotAccepted() throws Exception {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 32 * 1024 + 1; i++) {
sb.append("a");
}
clientPair.hardwareClient.send("hardware vw 1 " + sb.toString());
verify(clientPair.appClient.responseMock, after(500).never()).channelRead(any(), any());
}
@Test
public void testSendUnicodeChar() throws Exception {
clientPair.hardwareClient.send("hardware vw 1 °F");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("1 vw 1 °F"))));
}
@Test
public void testAppSendAnyHardCommandAndBack() throws Exception {
clientPair.appClient.send("hardware 1 dw 1 1");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("dw 1 1"))));
clientPair.hardwareClient.send("hardware ar 1");
ArgumentCaptor<StringMessage> objectArgumentCaptor = ArgumentCaptor.forClass(StringMessage.class);
verify(clientPair.appClient.responseMock, timeout(500).times(1)).channelRead(any(), objectArgumentCaptor.capture());
List<StringMessage> arguments = objectArgumentCaptor.getAllValues();
StringMessage hardMessage = arguments.get(0);
assertEquals(1, hardMessage.id);
assertEquals(HARDWARE, hardMessage.command);
assertEquals(6, hardMessage.length);
assertEquals(b("1 ar 1"), hardMessage.body);
}
@Test
public void testAppNoActiveDashForHard() throws Exception {
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("1 aw 1 1"))));
clientPair.appClient.send("deactivate 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, after(500).never()).channelRead(any(), eq(new ResponseMessage(2, NO_ACTIVE_DASHBOARD)));
}
@Test
public void testHardwareSendsWrongCommand() throws Exception {
clientPair.hardwareClient.send("hardware aw 1 ");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, ILLEGAL_COMMAND)));
clientPair.hardwareClient.send("hardware aw 1");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, ILLEGAL_COMMAND)));
}
@Test
public void testAppChangeActiveDash() throws Exception {
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("1 aw 1 1"))));
clientPair.appClient.send("deactivate 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
Profile newProfile = parseProfile(readTestUserProfile("user_profile_json_3_dashes.txt"));
clientPair.appClient.send("createDash " + newProfile.dashBoards[1]);
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, after(500).never()).channelRead(any(), eq(new ResponseMessage(2, NO_ACTIVE_DASHBOARD)));
clientPair.appClient.send("activate 2");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, DEVICE_NOT_IN_NETWORK)));
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, after(500).never()).channelRead(any(), eq(new ResponseMessage(3, NO_ACTIVE_DASHBOARD)));
clientPair.appClient.send("activate 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(4, HARDWARE, b("1 aw 1 1"))));
}
@Test
public void testActive2AndDeactivate1() throws Exception {
TestHardClient hardClient2 = new TestHardClient("localhost", tcpHardPort);
hardClient2.start();
Profile newProfile = parseProfile(readTestUserProfile("user_profile_json_3_dashes.txt"));
clientPair.appClient.send("createDash " + newProfile.dashBoards[1]);
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.appClient.send("activate 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, OK)));
clientPair.appClient.send("activate 2");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, DEVICE_NOT_IN_NETWORK)));
clientPair.appClient.reset();
clientPair.appClient.send("getToken 2");
String token2 = clientPair.appClient.getBody();
hardClient2.send("login " + token2);
verify(hardClient2.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.appClient.reset();
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("1 aw 1 1"))));
hardClient2.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(2, HARDWARE, b("2 aw 1 1"))));
clientPair.appClient.send("deactivate 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, after(500).never()).channelRead(any(), eq(new ResponseMessage(2, NO_ACTIVE_DASHBOARD)));
hardClient2.send("hardware aw 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(3, HARDWARE, b("2 aw 1 1"))));
hardClient2.stop().awaitUninterruptibly();
}
@Test
public void testActivateWorkflow() throws Exception {
clientPair.appClient.send("activate 2");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, ILLEGAL_COMMAND)));
clientPair.appClient.send("deactivate 2");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, ILLEGAL_COMMAND)));
clientPair.appClient.send("hardware 1 ar 1 1");
//todo check no response
verify(clientPair.appClient.responseMock, never()).channelRead(any(), eq(new ResponseMessage(3, OK)));
clientPair.appClient.send("activate 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, OK)));
}
@Test
public void testTweetNotWorks() throws Exception {
reset(blockingIOProcessor);
clientPair.hardwareClient.send("tweet");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, NOTIFICATION_INVALID_BODY)));
clientPair.hardwareClient.send("tweet ");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, NOTIFICATION_INVALID_BODY)));
StringBuilder a = new StringBuilder();
for (int i = 0; i < 141; i++) {
a.append("a");
}
clientPair.hardwareClient.send("tweet " + a);
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, NOTIFICATION_INVALID_BODY)));
clientPair.appClient.send("deactivate 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.hardwareClient.send("tweet yo");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, NOTIFICATION_NOT_AUTHORIZED)));
}
@Test
public void testSmsWorks() throws Exception {
reset(blockingIOProcessor);
clientPair.hardwareClient.send("sms");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, NOTIFICATION_INVALID_BODY)));
//no sms widget
clientPair.hardwareClient.send("sms yo");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, NOTIFICATION_NOT_AUTHORIZED)));
//adding sms widget
clientPair.appClient.send("createWidget 1\0{\"id\":432, \"width\":1, \"height\":1, \"to\":\"3809683423423\", \"x\":0, \"y\":0, \"type\":\"SMS\"}");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.hardwareClient.send("sms yo");
verify(smsWrapper, timeout(500)).send(eq("3809683423423"), eq("yo"));
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(3, OK)));
clientPair.hardwareClient.send("sms yo");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(4, QUOTA_LIMIT)));
}
@Test
public void testTweetWorks() throws Exception {
reset(blockingIOProcessor);
clientPair.hardwareClient.send("tweet yo");
verify(twitterWrapper, timeout(500)).send(eq("token"), eq("secret"), eq("yo"));
clientPair.hardwareClient.send("tweet yo");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(2, QUOTA_LIMIT)));
}
@Test
public void testPlayerUpdateWorksAsExpected() throws Exception {
clientPair.appClient.send(("createWidget 1\0{\"type\":\"PLAYER\",\"id\":99, \"pin\":99, \"pinType\":\"VIRTUAL\", " +
"\"x\":0,\"y\":0,\"width\":1,\"height\":1}"));
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(ok(1)));
clientPair.appClient.send("hardware 1 vw 99 play");
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 play"))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
Profile profile = parseProfile(clientPair.appClient.getBody());
Player player = (Player) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(player);
assertTrue(player.isOnPlay);
clientPair.appClient.send("hardware 1 vw 99 stop");
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 stop"))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
player = (Player) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(player);
assertFalse(player.isOnPlay);
}
@Test
public void testTimeInputUpdateWorksAsExpected() throws Exception {
clientPair.appClient.send(("createWidget 1\0{\"type\":\"TIME_INPUT\",\"id\":99, \"pin\":99, \"pinType\":\"VIRTUAL\", " +
"\"x\":0,\"y\":0,\"width\":1,\"height\":1}"));
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(ok(1)));
clientPair.appClient.send("hardware 1 vw " + b("99 82800 82860 Europe/Kiev 1"));
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 82800 82860 Europe/Kiev 1"))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
Profile profile = parseProfile(clientPair.appClient.getBody());
TimeInput timeInput = (TimeInput) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(timeInput);
assertEquals(82800, timeInput.startAt);
assertEquals(82860, timeInput.stopAt);
assertEquals(ZoneId.of("Europe/Kiev"), timeInput.tzName);
assertArrayEquals(new int[] {1}, timeInput.days);
clientPair.appClient.send("hardware 1 vw " + b("99 82800 82860 Europe/Kiev "));
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 82800 82860 Europe/Kiev "))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
timeInput = (TimeInput) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(timeInput);
assertEquals(82800, timeInput.startAt);
assertEquals(82860, timeInput.stopAt);
assertEquals(ZoneId.of("Europe/Kiev"), timeInput.tzName);
assertNull(timeInput.days);
clientPair.appClient.send("hardware 1 vw " + b("99 82800 Europe/Kiev "));
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 82800 Europe/Kiev "))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
timeInput = (TimeInput) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(timeInput);
assertEquals(82800, timeInput.startAt);
assertEquals(-1, timeInput.stopAt);
assertEquals(ZoneId.of("Europe/Kiev"), timeInput.tzName);
assertNull(timeInput.days);
clientPair.appClient.send("hardware 1 vw " + b("99 82800 Europe/Kiev 1,2,3,4"));
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 82800 Europe/Kiev 1,2,3,4"))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
timeInput = (TimeInput) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(timeInput);
assertEquals(82800, timeInput.startAt);
assertEquals(-1, timeInput.stopAt);
assertEquals(ZoneId.of("Europe/Kiev"), timeInput.tzName);
assertArrayEquals(new int[]{1,2,3,4}, timeInput.days);
clientPair.appClient.send("hardware 1 vw " + b("99 Europe/Kiev 1,2,3,4"));
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 Europe/Kiev 1,2,3,4"))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
timeInput = (TimeInput) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(timeInput);
assertEquals(-1, timeInput.startAt);
assertEquals(-1, timeInput.stopAt);
assertEquals(ZoneId.of("Europe/Kiev"), timeInput.tzName);
assertArrayEquals(new int[]{1,2,3,4}, timeInput.days);
clientPair.appClient.send("hardware 1 vw " + b("99 82800 82800 Europe/Kiev 10800"));
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 82800 82800 Europe/Kiev 10800"))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
timeInput = (TimeInput) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(timeInput);
assertEquals(82800, timeInput.startAt);
assertEquals(82800, timeInput.stopAt);
assertEquals(ZoneId.of("Europe/Kiev"), timeInput.tzName);
assertNull(timeInput.days);
clientPair.appClient.send("hardware 1 vw " + b("99 ss sr Europe/Kiev 10800"));
verify(clientPair.hardwareClient.responseMock, timeout(500).times(1)).channelRead(any(), eq(produce(2, HARDWARE, b("vw 99 ss sr Europe/Kiev 10800"))));
clientPair.appClient.reset();
clientPair.appClient.send("loadProfileGzipped");
profile = parseProfile(clientPair.appClient.getBody());
timeInput = (TimeInput) profile.dashBoards[0].findWidgetByPin(0, (byte) 99, PinType.VIRTUAL);
assertNotNull(timeInput);
assertEquals(-2, timeInput.startAt);
assertEquals(-3, timeInput.stopAt);
assertEquals(ZoneId.of("Europe/Kiev"), timeInput.tzName);
assertNull(timeInput.days);
}
@Test
public void testWrongCommandForAggregation() throws Exception {
clientPair.hardwareClient.send("hardware vw 10 aaaa");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("1 vw 10 aaaa"))));
}
@Test
public void testWrongPin() throws Exception {
clientPair.hardwareClient.send("hardware vw x aaaa");
verify(clientPair.hardwareClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, ILLEGAL_COMMAND)));
}
@Test
public void testAppSendWAwWorks() throws Exception {
String body = "aw 8 333";
clientPair.hardwareClient.send("hardware " + body);
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("1 aw 8 333"))));
}
@Test
public void testClosedConnectionWhenNotLogged() throws Exception {
TestAppClient appClient2 = new TestAppClient("localhost", tcpAppPort, properties);
appClient2.start();
appClient2.send("getToken 1");
verify(appClient2.responseMock, after(600).never()).channelRead(any(), any());
assertTrue(appClient2.isClosed());
appClient2.send("login dima@mail.ua 1 Android 1RC7");
verify(appClient2.responseMock, after(200).never()).channelRead(any(), any());
}
@Test
public void testSendPinModeCommandWhenHardwareGoesOnline() throws Exception {
ChannelFuture channelFuture = clientPair.hardwareClient.stop();
channelFuture.await();
assertTrue(channelFuture.isDone());
String body = "vw 13 1";
clientPair.appClient.send("hardware 1 " + body);
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, DEVICE_NOT_IN_NETWORK)));
TestHardClient hardClient = new TestHardClient("localhost", tcpHardPort);
hardClient.start();
hardClient.send("login " + clientPair.token);
verify(hardClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(1, OK)));
verify(hardClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b("pm 1 out 2 out 3 out 5 out 6 in 7 in 30 in 8 in"))));
verify(hardClient.responseMock, times(2)).channelRead(any(), any());
hardClient.stop().awaitUninterruptibly();
}
@Test
public void testSendGeneratedPinModeCommandWhenHardwareGoesOnline() throws Exception {
ChannelFuture channelFuture = clientPair.hardwareClient.stop();
channelFuture.awaitUninterruptibly();
assertTrue(channelFuture.isDone());
clientPair.appClient.send("hardware 1 vw 1 1");
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, DEVICE_NOT_IN_NETWORK)));
TestHardClient hardClient = new TestHardClient("localhost", tcpHardPort);
hardClient.start();
hardClient.send("login " + clientPair.token);
verify(hardClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(1, OK)));
String expectedBody = "pm 1 out 2 out 3 out 5 out 6 in 7 in 30 in 8 in";
verify(hardClient.responseMock, timeout(500)).channelRead(any(), eq(produce(1, HARDWARE, b(expectedBody))));
verify(hardClient.responseMock, times(2)).channelRead(any(), any());
hardClient.stop().awaitUninterruptibly();
}
@Test
public void testSendHardwareCommandToNotActiveDashboard() throws Exception {
clientPair.appClient.send("createDash " + "{\"id\":2,\"name\":\"My Dashboard2\"}");
verify(clientPair.appClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.appClient.reset();
clientPair.appClient.send("getToken 2");
//getting token for second GetTokenMessage
ArgumentCaptor<GetTokenMessage> objectArgumentCaptor = ArgumentCaptor.forClass(GetTokenMessage.class);
verify(clientPair.appClient.responseMock, timeout(2000).times(1)).channelRead(any(), objectArgumentCaptor.capture());
List<GetTokenMessage> arguments = objectArgumentCaptor.getAllValues();
GetTokenMessage getTokenMessage = arguments.get(0);
String token = getTokenMessage.body;
clientPair.appClient.reset();
//connecting separate hardware to non active dashboard
TestHardClient nonActiveDashHardClient = new TestHardClient("localhost", tcpHardPort);
nonActiveDashHardClient.start();
nonActiveDashHardClient.send("login " + token);
verify(nonActiveDashHardClient.responseMock, timeout(2000)).channelRead(any(), eq(new ResponseMessage(1, OK)));
nonActiveDashHardClient.reset();
//sending hardware command from hardware that has no active dashboard
nonActiveDashHardClient.send("hardware aw 1 1");
//verify(nonActiveDashHardClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(1, NO_ACTIVE_DASHBOARD)));
verify(clientPair.appClient.responseMock, timeout(1000).times(1)).channelRead(any(), any());
verify(clientPair.appClient.responseMock, timeout(1000).times(1)).channelRead(any(), eq(new HardwareConnectedMessage(1, "2-0")));
clientPair.hardwareClient.send("hardware aw 1 1");
verify(clientPair.hardwareClient.responseMock, after(1000).never()).channelRead(any(), any());
verify(clientPair.appClient.responseMock, timeout(1000)).channelRead(any(), eq(produce(1, HARDWARE, b("1 aw 1 1"))));
nonActiveDashHardClient.stop().awaitUninterruptibly();
}
@Test
public void testConnectAppAndHardwareAndSendCommands() throws Exception {
for (int i = 0; i < 100; i++) {
clientPair.appClient.send("hardware 1 aw 1 1");
}
verify(clientPair.hardwareClient.responseMock, timeout(500).times(100)).channelRead(any(), any());
}
@Test
public void testTryReachQuotaLimit() throws Exception {
String body = "aw 100 100";
//within 1 second sending more messages than default limit 100.
for (int i = 0; i < 200; i++) {
clientPair.hardwareClient.send("hardware " + body);
sleep(5);
}
ArgumentCaptor<ResponseMessage> objectArgumentCaptor = ArgumentCaptor.forClass(ResponseMessage.class);
verify(clientPair.hardwareClient.responseMock, timeout(1000)).channelRead(any(), objectArgumentCaptor.capture());
List<ResponseMessage> arguments = objectArgumentCaptor.getAllValues();
ResponseMessage responseMessage = arguments.get(0);
assertTrue(responseMessage.id > 100);
//at least 100 iterations should be
for (int i = 0; i < 100; i++) {
verify(clientPair.appClient.responseMock).channelRead(any(), eq(produce(i+1, HARDWARE, b("1 " + body))));
}
clientPair.appClient.reset();
clientPair.hardwareClient.reset();
//check no more accepted
for (int i = 0; i < 10; i++) {
clientPair.hardwareClient.send("hardware " + body);
sleep(9);
}
verify(clientPair.hardwareClient.responseMock, never()).channelRead(any(), eq(new ResponseMessage(1, QUOTA_LIMIT)));
verify(clientPair.appClient.responseMock, never()).channelRead(any(), eq(produce(1, HARDWARE, b(body))));
}
@Test
public void testCreateProjectWithDevicesGeneratesNewTokens() throws Exception {
DashBoard dashBoard = new DashBoard();
dashBoard.id = 2;
dashBoard.name = "Test Dash";
Device device = new Device();
device.id = 1;
device.name = "MyDevice";
device.token = "aaa";
dashBoard.devices = new Device[] {
device
};
clientPair.appClient.send("createDash " + dashBoard.toString());
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, OK)));
clientPair.appClient.send("getDevices 2");
String response = clientPair.appClient.getBody(2);
Device[] devices = JsonParser.mapper.readValue(response, Device[].class);
assertNotNull(devices);
assertEquals(1, devices.length);
assertEquals(1, devices[0].id);
assertEquals("MyDevice", devices[0].name);
assertNotEquals("aaa", devices[0].token);
}
@Test
@Ignore("hard to test this case...")
public void testTryReachQuotaLimitAndWarningExceededLimit() throws Exception {
String body = "1 ar 100 100";
//within 1 second sending more messages than default limit 100.
for (int i = 0; i < 1000 / 9; i++) {
clientPair.appClient.send("hardware " + body, 1);
sleep(9);
}
verify(clientPair.appClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(1, QUOTA_LIMIT)));
verify(clientPair.hardwareClient.responseMock, atLeast(100)).channelRead(any(), eq(produce(1, HARDWARE, b(body))));
clientPair.appClient.reset();
clientPair.hardwareClient.reset();
//waiting to avoid limit.
sleep(1000);
for (int i = 0; i < 100000 / 9; i++) {
clientPair.appClient.send("hardware " + body, 1);
sleep(9);
}
verify(clientPair.appClient.responseMock, timeout(500)).channelRead(any(), eq(new ResponseMessage(1, QUOTA_LIMIT)));
verify(clientPair.hardwareClient.responseMock, atLeast(100)).channelRead(any(), eq(produce(1, HARDWARE, b(body))));
}
}