package cc.blynk.integration; 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.core.model.DashBoard; import cc.blynk.server.core.model.Pin; import cc.blynk.server.core.model.Profile; import cc.blynk.server.core.model.widgets.MultiPinWidget; import cc.blynk.server.core.model.widgets.OnePinWidget; import cc.blynk.server.core.model.widgets.Widget; import cc.blynk.server.core.protocol.model.messages.ResponseMessage; import cc.blynk.server.core.protocol.model.messages.appllication.GetTokenMessage; import cc.blynk.server.core.protocol.model.messages.common.HardwareConnectedMessage; import cc.blynk.server.notifications.push.android.AndroidGCMMessage; import cc.blynk.server.notifications.push.android.GCMData; import cc.blynk.utils.JsonParser; import cc.blynk.utils.ServerProperties; import cc.blynk.utils.StringUtils; import com.fasterxml.jackson.databind.ObjectReader; import org.mockito.ArgumentCaptor; import java.io.InputStream; import java.lang.reflect.Field; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import static cc.blynk.server.core.protocol.enums.Response.NOT_ALLOWED; import static cc.blynk.server.core.protocol.enums.Response.OK; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; /** * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 2/4/2015. */ public abstract class IntegrationBase extends BaseTest { public static final String DEFAULT_TEST_USER = "dima@mail.ua"; private static final ObjectReader profileReader = JsonParser.init().readerFor(Profile.class); public static Profile parseProfile(InputStream reader) throws Exception { return profileReader.readValue(reader); } public static Profile parseProfile(String reader) throws Exception { return profileReader.readValue(reader); } public static String readTestUserProfile(String fileName) throws Exception{ if (fileName == null) { fileName = "user_profile_json.txt"; } InputStream is = IntegrationBase.class.getResourceAsStream("/json_test/" + fileName); Profile profile = parseProfile(is); return profile.toString(); } public static String readTestUserProfile() throws Exception { return readTestUserProfile(null); } protected static GetTokenMessage getGetTokenMessage(List<Object> arguments) { for (Object obj : arguments) { if (obj instanceof GetTokenMessage) { return (GetTokenMessage) obj; } } throw new RuntimeException("Get token message wasn't retrieved."); } public static void saveProfile(TestAppClient appClient, DashBoard... dashBoards) { for (DashBoard dash : dashBoards) { appClient.send("createDash " + dash.toString()); } } public static String b(String body) { return body.replaceAll(" ", StringUtils.BODY_SEPARATOR_STRING); } public static ResponseMessage ok(int msgId) { return new ResponseMessage(msgId, OK); } public static ResponseMessage notAllowed(int msgId) { return new ResponseMessage(msgId, NOT_ALLOWED); } public static ClientPair initAppAndHardPair(String host, int appPort, int hardPort, String user, String jsonProfile, ServerProperties properties, int energy) throws Exception { TestAppClient appClient = new TestAppClient(host, appPort, properties); TestHardClient hardClient = new TestHardClient(host, hardPort); return initAppAndHardPair(appClient, hardClient, user, jsonProfile, energy); } public static ClientPair initAppAndHardPair(TestAppClient appClient, TestHardClient hardClient, String user, String jsonProfile, int energy) throws Exception { appClient.start(); hardClient.start(); String userProfileString = readTestUserProfile(jsonProfile); Profile profile = parseProfile(userProfileString); int expectedSyncCommandsCount = 0; for (Widget widget : profile.dashBoards[0].widgets) { if (widget instanceof OnePinWidget) { if (((OnePinWidget) widget).makeHardwareBody() != null) { expectedSyncCommandsCount++; } } else if (widget instanceof MultiPinWidget) { MultiPinWidget multiPinWidget = (MultiPinWidget) widget; if (multiPinWidget.pins != null) { if (multiPinWidget.isSplitMode()) { for (Pin pin : multiPinWidget.pins) { if (pin.notEmpty()) { expectedSyncCommandsCount++; } } } else { if (multiPinWidget.pins[0].notEmpty()) { expectedSyncCommandsCount++; } } } } } int dashId = profile.dashBoards[0].id; appClient.send("register " + user); appClient.send("login " + user + " Android" + "\0" + "1.10.4"); int rand = ThreadLocalRandom.current().nextInt(); appClient.send("addEnergy " + energy + "\0" + String.valueOf(rand)); //we should wait until login finished. Only after that we can send commands verify(appClient.responseMock, timeout(1000)).channelRead(any(), eq(new ResponseMessage(2, OK))); saveProfile(appClient, profile.dashBoards); appClient.send("activate " + dashId); appClient.send("getToken " + dashId); ArgumentCaptor<Object> objectArgumentCaptor = ArgumentCaptor.forClass(Object.class); verify(appClient.responseMock, timeout(2000).times(5 + profile.dashBoards.length + expectedSyncCommandsCount)).channelRead(any(), objectArgumentCaptor.capture()); List<Object> arguments = objectArgumentCaptor.getAllValues(); String token = getGetTokenMessage(arguments).body; hardClient.send("login " + token); verify(hardClient.responseMock, timeout(2000)).channelRead(any(), eq(new ResponseMessage(1, OK))); verify(appClient.responseMock, timeout(2000)).channelRead(any(), eq(new HardwareConnectedMessage(1, "" + dashId + "-0"))); appClient.reset(); hardClient.reset(); return new ClientPair(appClient, hardClient, token); } public static ClientPair initAppAndHardPair(int tcpAppPort, int tcpHartPort, ServerProperties properties) throws Exception { return initAppAndHardPair("localhost", tcpAppPort, tcpHartPort, DEFAULT_TEST_USER + " 1", null, properties, 10000); } public static ClientPair initAppAndHardPair() throws Exception { return initAppAndHardPair("localhost", tcpAppPort, tcpHardPort, DEFAULT_TEST_USER + " 1", null, properties, 10000); } public static ClientPair initAppAndHardPair(int energy) throws Exception { return initAppAndHardPair("localhost", tcpAppPort, tcpHardPort, DEFAULT_TEST_USER + " 1", null, properties, energy); } public static ClientPair initAppAndHardPair(String jsonProfile) throws Exception { return initAppAndHardPair("localhost", tcpAppPort, tcpHardPort, DEFAULT_TEST_USER + " 1", jsonProfile, properties, 10000); } private static Object getPrivateField(Object o, Class<?> clazz, String fieldName) throws Exception { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field.get(o); } public static long getPrivateAndroidTSField(Object o) { try { GCMData gcmData = (GCMData) getPrivateField(o, AndroidGCMMessage.class, "data"); return (long) getPrivateField(gcmData, GCMData.class, "ts"); } catch (Exception e) { //ignore return 0; } } }