blob: c44dd447fdd457a99ddc754375ee3ea9336ac200 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2019, 2021 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
******************************************************************************/
package org.eclipse.lsp4j.websocket.jakarta.test;
import java.util.Collection;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
import org.eclipse.lsp4j.websocket.jakarta.WebSocketEndpoint;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MockConnectionTest {
private static final long TIMEOUT = 2000;
private Client client;
private Server server;
@SuppressWarnings("resource")
@Before
public void setup() {
client = new Client();
server = new Server();
MockSession clientSession = new MockSession();
MockSession serverSession = new MockSession();
clientSession.connect(serverSession);
clientSession.open(new ClientSideEndpoint());
serverSession.open(new ServerSideEndpoint());
}
@Test
public void testClientRequest() throws Exception {
CompletableFuture<String> future = client.server.request("foo");
String result = future.get(TIMEOUT, TimeUnit.MILLISECONDS);
Assert.assertEquals("foobar", result);
}
@Test
public void testNotifications() throws Exception {
server.client.notify("12");
await(() -> client.result.length() == 2);
client.server.notify("foo");
await(() -> server.result.length() == 3);
server.client.notify("34");
await(() -> client.result.length() == 4);
client.server.notify("bar");
await(() -> server.result.length() == 6);
server.client.notify("56");
await(() -> client.result.length() == 6);
Assert.assertEquals("foobar", server.result);
Assert.assertEquals("123456", client.result);
}
@Test
public void testChunkedNotification() throws Exception {
StringBuilder messageBuilder = new StringBuilder();
Random random = new Random(1);
for (int i = 0; i < 3 * MockSession.MAX_CHUNK_SIZE; i++) {
messageBuilder.append((char) ('a' + random.nextInt('z' - 'a' + 1)));
}
String message = messageBuilder.toString();
server.client.notify(message);
await(() -> client.result.length() == message.length());
Assert.assertEquals(message, client.result);
}
private void await(Supplier<Boolean> condition) throws InterruptedException {
long startTime = System.currentTimeMillis();
while (!condition.get()) {
Thread.sleep(20);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
Assert.fail("Timeout elapsed while waiting for condition.\n");
}
}
}
private static interface ClientInterface {
@JsonNotification("client/notify")
void notify(String arg);
}
private static class Client implements ClientInterface {
ServerInterface server;
String result = "";
@Override
public void notify(String arg) {
this.result += arg;
}
}
private static interface ServerInterface {
@JsonRequest("server/request")
CompletableFuture<String> request(String arg);
@JsonNotification("server/notify")
void notify(String arg);
}
private static class Server implements ServerInterface {
ClientInterface client;
String result = "";
@Override
public CompletableFuture<String> request(String arg) {
return CompletableFuture.supplyAsync(() -> arg + "bar");
}
@Override
public void notify(String arg) {
this.result += arg;
}
}
private class ClientSideEndpoint extends WebSocketEndpoint<ServerInterface> {
@Override
protected void configure(Launcher.Builder<ServerInterface> builder) {
builder
.setLocalService(client)
.setRemoteInterface(ServerInterface.class);
}
@Override
protected void connect(Collection<Object> localServices, ServerInterface remoteProxy) {
localServices.forEach(s -> ((Client) s).server = remoteProxy);
}
}
private class ServerSideEndpoint extends WebSocketEndpoint<ClientInterface> {
@Override
protected void configure(Launcher.Builder<ClientInterface> builder) {
builder
.setLocalService(server)
.setRemoteInterface(ClientInterface.class);
}
@Override
protected void connect(Collection<Object> localServices, ClientInterface remoteProxy) {
localServices.forEach(s -> ((Server) s).client = remoteProxy);
}
}
}