diff --git a/pom.xml b/pom.xml index e9900f3571..442caef8ee 100755 --- a/pom.xml +++ b/pom.xml @@ -69,10 +69,6 @@ 2.19.1 3.0.2 2.6.1 - 2.2.3 - 1.0.0 - 2.2.1 - 3.2.2 @@ -285,16 +281,6 @@ - - net.alchim31.maven - scala-maven-plugin - ${scala-maven-plugin.version} - - - io.gatling - gatling-maven-plugin - ${gatling-plugin.version} - @@ -703,18 +689,6 @@ springfox-swagger2 ${springfox-swagger.version} - - io.gatling.highcharts - gatling-charts-highcharts - ${gatling.version} - test - - - com.github.mnogu - gatling-mqtt - ${gatling-mqtt.version} - test - diff --git a/tools/pom.xml b/tools/pom.xml index 46549fc07c..2c978f0662 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -35,61 +35,6 @@ ${basedir}/.. - - - org.thingsboard.common - data - - - org.springframework.boot - spring-boot-starter-web - - - org.eclipse.paho - org.eclipse.paho.client.mqttv3 - - - org.slf4j - slf4j-api - - - org.slf4j - log4j-over-slf4j - - - ch.qos.logback - logback-core - - - ch.qos.logback - logback-classic - - - org.springframework - spring-test - - - junit - junit - test - - - org.mockito - mockito-all - test - - - io.gatling.highcharts - gatling-charts-highcharts - test - - - com.github.mnogu - gatling-mqtt - test - - - @@ -124,14 +69,6 @@ - - net.alchim31.maven - scala-maven-plugin - - - io.gatling - gatling-maven-plugin - diff --git a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestClient.java b/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestClient.java deleted file mode 100644 index 3b6fca98da..0000000000 --- a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestClient.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * 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 org.thingsboard.client.tools; - -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.eclipse.paho.client.mqttv3.*; -import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; - -/** - * @author Andrew Shvayka - */ -@Slf4j -public class MqttStressTestClient { - - @Getter - private final String deviceToken; - @Getter - private final String clientId; - private final MqttClientPersistence persistence; - private final MqttAsyncClient client; - private final ResultAccumulator results; - - public MqttStressTestClient(ResultAccumulator results, String brokerUri, String deviceToken) throws MqttException { - this.results = results; - this.clientId = MqttAsyncClient.generateClientId(); - this.deviceToken = deviceToken; - this.persistence = new MemoryPersistence(); - this.client = new MqttAsyncClient(brokerUri, clientId, persistence); - } - - public IMqttToken connect() throws MqttException { - MqttConnectOptions options = new MqttConnectOptions(); - options.setUserName(deviceToken); - return client.connect(options, null, new IMqttActionListener() { - @Override - public void onSuccess(IMqttToken iMqttToken) { - log.info("OnSuccess"); - } - - @Override - public void onFailure(IMqttToken iMqttToken, Throwable e) { - log.info("OnFailure", e); - } - }); - } - - public void disconnect() throws MqttException { - client.disconnect(); - } - - - - public void warmUp(byte[] data) throws MqttException { - MqttMessage msg = new MqttMessage(data); - client.publish("v1/devices/me/telemetry", msg, null, new IMqttActionListener() { - @Override - public void onSuccess(IMqttToken asyncActionToken) { - } - - @Override - public void onFailure(IMqttToken asyncActionToken, Throwable exception) { - } - }).waitForCompletion(); - } - - - public void publishTelemetry(byte[] data) throws MqttException { - long sendTime = System.currentTimeMillis(); - MqttMessage msg = new MqttMessage(data); - client.publish("v1/devices/me/telemetry", msg, null, new IMqttActionListener() { - @Override - public void onSuccess(IMqttToken asyncActionToken) { - long ackTime = System.currentTimeMillis(); - results.onResult(true, ackTime - sendTime); - } - - @Override - public void onFailure(IMqttToken asyncActionToken, Throwable exception) { - long failTime = System.currentTimeMillis(); - results.onResult(false, failTime - sendTime); - } - }); - } -} diff --git a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestTool.java b/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestTool.java deleted file mode 100644 index b957f138a3..0000000000 --- a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestTool.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * 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 org.thingsboard.client.tools; - -import lombok.extern.slf4j.Slf4j; -import org.eclipse.paho.client.mqttv3.IMqttToken; -import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.security.DeviceCredentials; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -/** - * @author Andrew Shvayka - */ -@Slf4j -public class MqttStressTestTool { - - private static byte[] data = "{\"longKey\":73}".getBytes(StandardCharsets.UTF_8); - private static ResultAccumulator results = new ResultAccumulator(); - private static List clients = new ArrayList<>(); - private static List connectTokens = new ArrayList<>(); - - public static void main(String[] args) throws Exception { - TestParams params = new TestParams(); - ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10); - - if (params.getDuration() % params.getIterationInterval() != 0) { - throw new IllegalArgumentException("Test Duration % Iteration Interval != 0"); - } - - if ((params.getIterationInterval() * 1000) % params.getDeviceCount() != 0) { - throw new IllegalArgumentException("Iteration Interval % Device Count != 0"); - } - - createDevices(params); - - long startTime = System.currentTimeMillis(); - int iterationsCount = (int) (params.getDuration() / params.getIterationInterval()); - int subIterationMicroSeconds = (int) ((params.getIterationInterval() * 1000) / params.getDeviceCount()); - - List> iterationFutures = new ArrayList<>(); - for (int i = 0; i < iterationsCount; i++) { - long delay = i * params.getIterationInterval(); - iterationFutures.add(scheduler.schedule((Callable) () -> { - long sleepMicroSeconds = 0L; - for (MqttStressTestClient client : clients) { - client.publishTelemetry(data); - sleepMicroSeconds += subIterationMicroSeconds; - if (sleepMicroSeconds > 1000) { - Thread.sleep(sleepMicroSeconds / 1000); - sleepMicroSeconds = sleepMicroSeconds % 1000; - } - } - return null; - }, delay, TimeUnit.MILLISECONDS)); - } - - for (ScheduledFuture future : iterationFutures) { - future.get(); - } - - Thread.sleep(1000); - - for (MqttStressTestClient client : clients) { - client.disconnect(); - } - log.info("Results: {} took {}ms", results, System.currentTimeMillis() - startTime); - scheduler.shutdownNow(); - } - - /** - * Returns list of device credential IDs - * - * @param params - * @return - * @throws Exception - */ - public static List createDevices(TestParams params) throws Exception { - AtomicLong value = new AtomicLong(Long.MAX_VALUE); - log.info("value: {} ", value.incrementAndGet()); - - RestClient restClient = new RestClient(params.getRestApiUrl()); - restClient.login(params.getUsername(), params.getPassword()); - - List deviceCredentialsIds = new ArrayList<>(); - for (int i = 0; i < params.getDeviceCount(); i++) { - Device device = restClient.createDevice("Device " + UUID.randomUUID()); - DeviceCredentials credentials = restClient.getCredentials(device.getId()); - String[] mqttUrls = params.getMqttUrls(); - String mqttURL = mqttUrls[i % mqttUrls.length]; - MqttStressTestClient client = new MqttStressTestClient(results, mqttURL, credentials.getCredentialsId()); - - deviceCredentialsIds.add(credentials.getCredentialsId()); - - connectTokens.add(client.connect()); - clients.add(client); - } - - for (IMqttToken tokens : connectTokens) { - tokens.waitForCompletion(); - } - - for (MqttStressTestClient client : clients) { - client.warmUp(data); - } - - Thread.sleep(1000); - - return deviceCredentialsIds; - } -} diff --git a/tools/src/main/java/org/thingsboard/client/tools/RestClient.java b/tools/src/main/java/org/thingsboard/client/tools/RestClient.java deleted file mode 100644 index cb1b5fb890..0000000000 --- a/tools/src/main/java/org/thingsboard/client/tools/RestClient.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * 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 org.thingsboard.client.tools; - -import com.fasterxml.jackson.databind.JsonNode; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpRequest; -import org.springframework.http.ResponseEntity; -import org.springframework.http.client.ClientHttpRequestExecution; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.client.support.HttpRequestWrapper; -import org.springframework.web.client.RestTemplate; -import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.security.DeviceCredentials; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Andrew Shvayka - */ -@RequiredArgsConstructor -public class RestClient implements ClientHttpRequestInterceptor { - private static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization"; - private final RestTemplate restTemplate = new RestTemplate(); - private String token; - private final String baseURL; - - public void login(String username, String password) { - Map loginRequest = new HashMap<>(); - loginRequest.put("username", username); - loginRequest.put("password", password); - ResponseEntity tokenInfo = restTemplate.postForEntity(baseURL + "/api/auth/login", loginRequest, JsonNode.class); - this.token = tokenInfo.getBody().get("token").asText(); - restTemplate.setInterceptors(Collections.singletonList(this)); - } - - public Device createDevice(String name) { - Device device = new Device(); - device.setName(name); - return restTemplate.postForEntity(baseURL + "/api/device", device, Device.class).getBody(); - } - - public DeviceCredentials getCredentials(DeviceId id) { - return restTemplate.getForEntity(baseURL + "/api/device/" + id.getId().toString() + "/credentials", DeviceCredentials.class).getBody(); - } - - public RestTemplate getRestTemplate() { - return restTemplate; - } - - @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] bytes, ClientHttpRequestExecution execution) throws IOException { - HttpRequest wrapper = new HttpRequestWrapper(request); - wrapper.getHeaders().set(JWT_TOKEN_HEADER_PARAM, "Bearer " + token); - return execution.execute(wrapper, bytes); - } - -} diff --git a/tools/src/main/java/org/thingsboard/client/tools/ResultAccumulator.java b/tools/src/main/java/org/thingsboard/client/tools/ResultAccumulator.java deleted file mode 100644 index 2530ed13ff..0000000000 --- a/tools/src/main/java/org/thingsboard/client/tools/ResultAccumulator.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * 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 org.thingsboard.client.tools; - -import lombok.extern.slf4j.Slf4j; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * @author Andrew Shvayka - */ -@Slf4j -public class ResultAccumulator { - - private AtomicLong minTime = new AtomicLong(Long.MAX_VALUE); - private AtomicLong maxTime = new AtomicLong(Long.MIN_VALUE); - private AtomicLong timeSpentCount = new AtomicLong(); - private AtomicInteger successCount = new AtomicInteger(); - private AtomicInteger errorCount = new AtomicInteger(); - - public void onResult(boolean success, long timeSpent) { - if (success) { - successCount.incrementAndGet(); - } else { - errorCount.incrementAndGet(); - } - timeSpentCount.addAndGet(timeSpent); - - while (!setMax(timeSpent)) ; - while (!setMin(timeSpent)) ; - } - - private boolean setMax(long timeSpent) { - long curMax = maxTime.get(); - long newMax = Math.max(curMax, timeSpent); - return maxTime.compareAndSet(curMax, newMax); - } - - private boolean setMin(long timeSpent) { - long curMin = minTime.get(); - long newMin = Math.min(curMin, timeSpent); - return minTime.compareAndSet(curMin, newMin); - } - - - public int getSuccessCount() { - return successCount.get(); - } - - public int getErrorCount() { - return errorCount.get(); - } - - public long getTimeSpent() { - return timeSpentCount.get(); - } - - public double getAvgTimeSpent() { - return ((double) getTimeSpent()) / (getSuccessCount() + getErrorCount()); - } - - @Override - public String toString() { - return "Result {" + - "successCount=" + getSuccessCount() + - ", errorCount=" + getErrorCount() + - ", totalTime=" + getTimeSpent() + - ", avgTime=" + getAvgTimeSpent() + - ", minTime=" + minTime.get() + - ", maxTime=" + maxTime.get() + - '}'; - } -} diff --git a/tools/src/main/java/org/thingsboard/client/tools/TestParams.java b/tools/src/main/java/org/thingsboard/client/tools/TestParams.java deleted file mode 100644 index 24b860d9c1..0000000000 --- a/tools/src/main/java/org/thingsboard/client/tools/TestParams.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * 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 org.thingsboard.client.tools; - -import lombok.extern.slf4j.Slf4j; - -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URL; -import java.util.Properties; -import java.util.concurrent.TimeUnit; - -@Slf4j -public class TestParams { - static final String TEST_PROPERTIES = "test.properties"; - static final long DEFAULT_TEST_DURATION = TimeUnit.SECONDS.toMillis(1); - static final long DEFAULT_TEST_INTERVAL = TimeUnit.MILLISECONDS.toMillis(100); - static final int DEFAULT_DEVICE_COUNT = 2000; - static final String DEFAULT_REST_URL = "http://localhost:8080"; - static final String DEFAULT_MQTT_URLS = "tcp://localhost:1883"; - static final String DEFAULT_USERNAME = "tenant@thingsboard.org"; - static final String DEFAULT_PASSWORD = "tenant"; - - private Properties params = new Properties(); - - public TestParams() throws IOException { - try { - params.load(TestParams.class.getClassLoader().getResourceAsStream(TEST_PROPERTIES)); - } catch (Exception e) { - log.warn("Failed to read " + TEST_PROPERTIES); - } - } - - public long getDuration() { - return Long.valueOf(params.getProperty("durationMs", Long.toString(DEFAULT_TEST_DURATION))); - } - - public long getIterationInterval() { - return Long.valueOf(params.getProperty("iterationIntervalMs", Long.toString(DEFAULT_TEST_INTERVAL))); - } - - public int getDeviceCount() { - return Integer.valueOf(params.getProperty("deviceCount", Integer.toString(DEFAULT_DEVICE_COUNT))); - } - - public String getRestApiUrl() { - return params.getProperty("restUrl", DEFAULT_REST_URL); - } - - public String[] getMqttUrls() { - return params.getProperty("mqttUrls", DEFAULT_MQTT_URLS).split(","); - } - - public String getUsername() { - return params.getProperty("username", DEFAULT_USERNAME); - } - - public String getPassword() { - return params.getProperty("password", DEFAULT_PASSWORD); - } -} diff --git a/tools/src/main/resources/logback.xml b/tools/src/main/resources/logback.xml deleted file mode 100644 index 518f474e4e..0000000000 --- a/tools/src/main/resources/logback.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - \ No newline at end of file diff --git a/tools/src/main/resources/test.properties b/tools/src/main/resources/test.properties deleted file mode 100644 index d55c1fc205..0000000000 --- a/tools/src/main/resources/test.properties +++ /dev/null @@ -1,5 +0,0 @@ -restUrl=http://localhost:8080 -mqttUrls=tcp://localhost:1883 -deviceCount=100 -durationMs=60000 -iterationIntervalMs=1000 \ No newline at end of file diff --git a/tools/src/test/scala/org/thingsboard/client/tools/MqttSimulation.scala b/tools/src/test/scala/org/thingsboard/client/tools/MqttSimulation.scala deleted file mode 100644 index 0d92b74f10..0000000000 --- a/tools/src/test/scala/org/thingsboard/client/tools/MqttSimulation.scala +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright © 2016 The Thingsboard Authors - * - * 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 org.thingsboard.client.tools - -import com.github.mnogu.gatling.mqtt.Predef._ -import io.gatling.core.Predef._ -import org.fusesource.mqtt.client.QoS -import scala.collection.JavaConverters._ - -import scala.concurrent.duration._ - -class MqttSimulation extends Simulation { - - val testParams = new TestParams() - - val deviceCredentialsIds: Array[String] = MqttStressTestTool.createDevices(testParams).asScala.toArray - - val mqttConf = mqtt - .host("tcp://localhost:1883") - .userName("${deviceCredentialsId}") - - val connect = exec(mqtt("connect") - .connect()) - - val publish = repeat(100) { - exec(mqtt("publish") - .publish("v1/devices/me/telemetry", "{\"key1\":\"value1\", \"key2\":\"value2\"}", QoS.AT_LEAST_ONCE, retain = false)) - .pause(100 milliseconds) - } - - val deviceCredentialsIdsFeeder = deviceCredentialsIds.map( x => {Map("deviceCredentialsId" -> x)}) - - val scn = scenario("Scenario Name") - .feed(deviceCredentialsIdsFeeder) - .exec(connect, publish) - - setUp( - scn - .inject(constantUsersPerSec(testParams.getDeviceCount) during (1 seconds)) - ).protocols(mqttConf) - -} \ No newline at end of file