/* * Copyright (c) 2011-2015 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package io.vertx.ext.stomp.impl; import com.jayway.awaitility.Awaitility; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.json.JsonObject; import io.vertx.ext.stomp.*; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.VertxUnitRunner; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * A couple of load tests that needs to be launched manually. * * @author <a href="http://escoffier.me">Clement Escoffier</a> */ @RunWith(VertxUnitRunner.class) @Ignore("Manual launch only") public class LoadTest { private Vertx vertx; private StompServer server; private List<StompClient> clients = new ArrayList<>(); private List<Frame> acked = new ArrayList<>(); private List<Frame> nacked = new ArrayList<>(); @Before public void setUp(TestContext context) { vertx = Vertx.vertx(); server = StompServer.create(vertx, new StompServerOptions().setHeartbeat( new JsonObject().put("x", 0).put("y", 0))) .handler(StompServerHandler.create(vertx) .onAckHandler(acknowledgement -> acked.addAll(acknowledgement.frames())) .onNackHandler(acknowledgement -> nacked.addAll(acknowledgement.frames()))) .listen(context.asyncAssertSuccess()); } @After public void tearDown(TestContext context) { System.out.println("Closing clients"); clients.forEach(StompClient::close); System.out.println("Closing server"); server.close(context.asyncAssertSuccess()); vertx.close(context.asyncAssertSuccess()); } @Test public void testWithMultiplePublisherAndConsumerOnOneDestination() { int publisher = 100; int consumer = 100; String dest = "/queue"; int numberOfMessagePerPublisher = 100; AtomicInteger received = new AtomicInteger(); AtomicInteger started = new AtomicInteger(); // Init consumers for (int i = 0; i < consumer; i++) { clients.add(StompClient.create(vertx) .connect(ar -> { if (ar.failed()) { System.err.println("Consumer connection error " + ar.cause().getMessage()); ar.cause().printStackTrace(); return; } ar.result() .errorHandler(frame -> System.err.println("Consumer Error : " + frame)) .subscribe(dest, frame -> { received.incrementAndGet(); }, frame -> started.incrementAndGet() ); })); } Awaitility.waitAtMost(1, TimeUnit.MINUTES).until(() -> started.get() == consumer); long begin = System.currentTimeMillis(); // Init producers AtomicInteger global = new AtomicInteger(); for (int i = 0; i < publisher; i++) { String p = Integer.toString(i); clients.add(StompClient.create(vertx).connect(ar -> { final StompClientConnection connection = ar.result(); connection.errorHandler(frame -> System.err.println("Producer Error : " + frame)); AtomicInteger count = new AtomicInteger(); vertx.setPeriodic(10, id -> { connection.send(dest, Buffer.buffer("Hello")); global.incrementAndGet(); if (count.incrementAndGet() == numberOfMessagePerPublisher) { vertx.cancelTimer(id); connection.disconnect(); } }); })); } Awaitility.await().atMost(1, TimeUnit.MINUTES).until(() -> { int size = received.get(); return size == publisher * numberOfMessagePerPublisher * consumer; }); long end = System.currentTimeMillis(); System.out.println(received.get() + " messages delivered in " + (end - begin) + " ms"); } @Test public void testWithASinglePublisherAndMultipleConsumersOnOneDestination() { int publisher = 1; int consumer = 200; String dest = "/queue"; int numberOfMessagePerPublisher = 800; AtomicInteger received = new AtomicInteger(); AtomicInteger started = new AtomicInteger(); // Init consumers for (int i = 0; i < consumer; i++) { clients.add(StompClient.create(vertx) .connect(ar -> { if (ar.failed()) { System.err.println("Consumer connection error " + ar.cause().getMessage()); ar.cause().printStackTrace(); return; } ar.result() .errorHandler(frame -> System.err.println("Consumer Error : " + frame)) .subscribe(dest, frame -> { received.incrementAndGet(); }, frame -> started.incrementAndGet() ); })); } Awaitility.waitAtMost(1, TimeUnit.MINUTES).until(() -> started.get() == consumer); long begin = System.currentTimeMillis(); // Init producers AtomicInteger global = new AtomicInteger(); for (int i = 0; i < publisher; i++) { String p = Integer.toString(i); clients.add(StompClient.create(vertx).connect(ar -> { final StompClientConnection connection = ar.result(); connection.errorHandler(frame -> System.err.println("Producer Error : " + frame)); AtomicInteger count = new AtomicInteger(); vertx.setPeriodic(10, id -> { connection.send(dest, Buffer.buffer("Hello")); global.incrementAndGet(); if (count.incrementAndGet() == numberOfMessagePerPublisher) { vertx.cancelTimer(id); } }); })); } Awaitility.await().atMost(1, TimeUnit.MINUTES).until(() -> { int size = received.get(); return size == publisher * numberOfMessagePerPublisher * consumer; }); long end = System.currentTimeMillis(); System.out.println(received.get() + " messages delivered in " + (end - begin) + " ms"); } }