package org.nextrtc.signalingserver.performance; import lombok.extern.slf4j.Slf4j; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.stream.IntStream; import static java.lang.String.format; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.stream.Collectors.toList; import static org.awaitility.Awaitility.await; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; @Ignore @Slf4j @RunWith(Parameterized.class) public class PerformanceTest { @Parameters(name = "{0}: on url {1}") public static Collection<Object[]> data() { return Arrays.asList(new Object[][]{ //{"RatPack", uri("localhost:5050")}, {"Spring", uri("localhost:8080")}//,{"Standalone", uri("localhost:8090")} }); } private URI uri; private static URI uri(String uri) { try { return new URI(format("wss://%s/signaling", uri)); } catch (Exception e) { throw new RuntimeException(e); } } public PerformanceTest(String type, URI uri) { this.uri = uri; } @Test public void scenario1_meshConversationWith64Participant() throws Exception { // given int size = 64; List<Tuple<Peer>> peers = IntStream.range(0, size) .mapToObj(Peer::new) .map(this::openSession) .collect(toList()); // when peers.parallelStream() .map(Tuple::getSocket) .forEach(s -> s.join("x")); peers.stream() .map(Tuple::getSocket) .forEach(p -> await() .atMost(1, MINUTES) .until(() -> p.getJoinedTo() != null)); // then List<Peer> result = peers.stream().map(Tuple::getSocket).collect(toList()); List<String> allNames = result.stream().map(Peer::getName).collect(toList()); peers.stream() .map(Tuple::getSocket) .forEach(p -> await() .atMost(1, MINUTES) .until(() -> p.getJoined().size() == size - 1)); result.forEach(p -> assertThat(p.getName() + ": Some members were missed", p.getJoined(), containsInAnyOrder(without(allNames, p.getName())))); result.forEach(p -> assertThat(p.getName() + " doesn't have all participant!", p.getJoined(), hasSize(size - 1))); result.forEach(p -> assertThat(p.getName() + " has joined to himself!", p.getJoined(), not(containsInAnyOrder(p.getName())))); result.forEach(p -> await() .atMost(1, MINUTES) .until(() -> p.getCandidates().size() == size - 1)); result.forEach(p -> assertThat(p.getName() + " didn't exchange all candidates", p.getCandidates().size(), equalTo(size - 1))); result.forEach(p -> assertThat(" there are errors for " + p.getName() + ": " + p.getErrors(), p.getErrors(), hasSize(0))); peers.forEach(this::stop); } @Test public void scenario2_broadcastConversationWith64Participant() throws Exception { // given int size = 64; List<Tuple<Peer>> peers = IntStream.range(0, size + 1) .mapToObj(Peer::new) .map(this::openSession) .collect(toList()); // when Tuple<Peer> masterTuple = peers.remove(0); Peer master = masterTuple.getSocket(); master.createConv("broadcast"); await() .atMost(1, MINUTES) .until(() -> master.getJoinedTo() != null); peers.parallelStream() .map(Tuple::getSocket) .forEach(s -> s.join("broadcast")); peers.stream() .map(Tuple::getSocket) .forEach(p -> await() .atMost(1, MINUTES) .until(() -> p.getJoinedTo() != null)); await() .atMost(1, MINUTES) .until(() -> master.getCandidates().size() == size); // then assertThat(master.getOfferRequests().size(), is(size)); assertThat(master.getFinalized().size(), is(size)); assertThat(master.getCandidates().size(), is(size)); List<Peer> result = peers.stream().map(Tuple::getSocket).collect(toList()); List<String> allNames = result.stream().map(Peer::getName).collect(toList()); assertThat(master.getCandidates().size(), is(size)); master.getCandidates().forEach((k, v) -> assertThat(allNames.contains(k), is(true))); result.forEach(p -> { assertThat(p.getJoinedTo(), is("broadcast")); assertThat(p.getJoined().size(), is(1)); assertThat(p.getCandidates().size(), is(1)); assertThat(p.getCandidates().keySet(), containsInAnyOrder(master.getName())); }); peers.forEach(this::stop); stop(masterTuple); } private String[] without(List<String> allNames, String name) { List<String> mod = new ArrayList<>(allNames); mod.remove(name); return mod.toArray(new String[0]); } private void stop(Tuple<Peer> p) { try { p.getClient().stop(); } catch (Exception e) { e.printStackTrace(); } } private <T> Tuple<T> openSession(T socket) { WebSocketClient client = new WebSocketClient(); try { client.start(); client.connect(socket, uri); } catch (Exception e) { throw new RuntimeException(e); } return new Tuple<>(client, socket); } }