Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add duplex test #19

Merged
merged 5 commits into from
Jun 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
name: CI
on:
pull_request:
push:
on: [ pull_request, push ]

jobs:
linux-test:
Expand Down
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@
**/target

# Eclipse/VsCode
.apt_generated
.classpath
.factorypath
.project
.settings

# VsCode
.vscode

# Metals
.metals

49 changes: 49 additions & 0 deletions src/test/java/org/scalasbt/ipcsocket/BaseSocketSetup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.scalasbt.ipcsocket;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

public abstract class BaseSocketSetup {

final boolean isWin = System.getProperty("os.name", "").toLowerCase().startsWith("win");

Random rand = new Random();

boolean useJNI() {
return false;
}

public static interface MayThrow {
void accept(String string) throws IOException, InterruptedException;
}

protected void withSocket(final MayThrow consumer) throws IOException, InterruptedException {
Path tempDir = isWin ? null : Files.createTempDirectory("ipcsocket");
Path socketPath = tempDir != null ? tempDir.resolve("foo" + rand.nextInt() + ".sock") : null;
String socket =
socketPath != null ? socketPath.toString() : "\\\\.\\pipe\\ipcsockettest" + rand.nextInt();
try {
consumer.accept(socket);
} finally {
if (socketPath != null) Files.deleteIfExists(socketPath);
if (tempDir != null) Files.deleteIfExists(socketPath);
}
}

protected ServerSocket newServerSocket(String socketName) throws IOException {
return isWin
? new Win32NamedPipeServerSocket(socketName, useJNI(), Win32SecurityLevel.LOGON_DACL)
: new UnixDomainServerSocket(socketName, useJNI());
}

protected Socket newClientSocket(String socketName) throws IOException {
return isWin
? new Win32NamedPipeSocket(socketName, useJNI())
: new UnixDomainSocket(socketName, useJNI());
}
}
38 changes: 1 addition & 37 deletions src/test/java/org/scalasbt/ipcsocket/SocketTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,8 @@
import java.net.Socket;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.Random;

public class SocketTest {
boolean useJNI() {
return false;
}

final boolean isWin = System.getProperty("os.name", "").toLowerCase().startsWith("win");

interface MayThrow {
void accept(String string) throws IOException, InterruptedException;
}

final void withSocket(final MayThrow consumer) throws IOException, InterruptedException {
Random rand = new Random();
Path tempDir = isWin ? null : Files.createTempDirectory("ipcsocket");
Path socketPath = tempDir != null ? tempDir.resolve("foo" + rand.nextInt() + ".sock") : null;
String socket =
socketPath != null ? socketPath.toString() : "\\\\.\\pipe\\ipcsockettest" + rand.nextInt();
try {
consumer.accept(socket);
} finally {
if (socketPath != null) Files.deleteIfExists(socketPath);
if (tempDir != null) Files.deleteIfExists(socketPath);
}
}

ServerSocket newServerSocket(String socketName) throws IOException {
return isWin
? new Win32NamedPipeServerSocket(socketName, useJNI(), Win32SecurityLevel.LOGON_DACL)
: new UnixDomainServerSocket(socketName, useJNI());
}

Socket newClientSocket(String socketName) throws IOException {
return isWin
? new Win32NamedPipeSocket(socketName, useJNI())
: new UnixDomainSocket(socketName, useJNI());
}
public class SocketTest extends BaseSocketSetup {

@Test
public void testAssertEquals() throws IOException, InterruptedException {
Expand Down
37 changes: 37 additions & 0 deletions src/test/java/org/scalasbt/ipcsocket/duplex/DuplexClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.scalasbt.ipcsocket.duplex;

import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import org.scalasbt.ipcsocket.BaseSocketSetup;

public class DuplexClient extends BaseSocketSetup {

private final String pipeName;
private final int sendMessages;

public Sender sender;
public Receiver receiver;

public DuplexClient(String pipeName, int sendMessages) {
this.pipeName = pipeName;
this.sendMessages = sendMessages;
}

public void startAndAwait() {
ExecutorService pool = Executors.newFixedThreadPool(2);

try (Socket socket = newClientSocket(pipeName)) {
sender = new Sender("client", socket, sendMessages);
receiver = new Receiver("client", socket);
pool.execute(sender);
pool.execute(receiver);

Thread.sleep(sendMessages * 1000);
pool.shutdownNow();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
}
41 changes: 41 additions & 0 deletions src/test/java/org/scalasbt/ipcsocket/duplex/DuplexServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.scalasbt.ipcsocket.duplex;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import org.scalasbt.ipcsocket.BaseSocketSetup;

public class DuplexServer extends BaseSocketSetup {

private final String pipeName;
private final int sendMessages;

public Sender sender;
public Receiver receiver;

public DuplexServer(String pipeName, int sendMessages) {
this.pipeName = pipeName;
this.sendMessages = sendMessages;
}

public void startAndAwait() {
ExecutorService pool = Executors.newFixedThreadPool(10);

System.out.println("DuplexServer started. Waiting for client...");
try (ServerSocket serverSocket = newServerSocket(pipeName);
Socket socket = serverSocket.accept()) {

sender = new Sender("server", socket, sendMessages);
receiver = new Receiver("server", socket);
pool.execute(sender);
pool.execute(receiver);

Thread.sleep((sendMessages + 2) * 1000);
pool.shutdownNow();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
}
38 changes: 38 additions & 0 deletions src/test/java/org/scalasbt/ipcsocket/duplex/DuplexTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.scalasbt.ipcsocket.duplex;

import static org.junit.Assert.assertEquals;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
import org.scalasbt.ipcsocket.BaseSocketSetup;

public class DuplexTest extends BaseSocketSetup {

@Test
public void testDuplexCommunication() throws Exception {
withSocket(
socketName -> {
ExecutorService pool = Executors.newFixedThreadPool(2);

// start server
int serverSendMessages = 15;
DuplexServer server = new DuplexServer(socketName, serverSendMessages);
pool.execute(() -> server.startAndAwait());

// wait for pipe to be instantiated
Thread.sleep(2000);

// start client
int clientSendMessages = 7;
DuplexClient client = new DuplexClient(socketName, clientSendMessages);
pool.execute(() -> client.startAndAwait());

// wait client and server to terminate
Thread.sleep((Math.max(serverSendMessages, clientSendMessages) + 1) * 1000);
pool.shutdown();

assertEquals(serverSendMessages, client.receiver.receivedMessages);
assertEquals(clientSendMessages, server.receiver.receivedMessages);
});
}
}
34 changes: 34 additions & 0 deletions src/test/java/org/scalasbt/ipcsocket/duplex/Receiver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.scalasbt.ipcsocket.duplex;

import java.io.IOException;
import java.net.Socket;
import java.util.Random;
import java.util.Scanner;

public class Receiver implements Runnable {

private final String name;
private final Socket socket;
public volatile int receivedMessages;
private final Random random = new Random();

public Receiver(String name, Socket socket) {
this.name = name;
this.socket = socket;
}

@Override
public void run() {
try (Scanner in = new Scanner(socket.getInputStream())) {
while (true) {
while (in.hasNextLine()) {
System.out.println("[" + name + "] got a message: " + in.nextLine());
receivedMessages++;
}
Thread.sleep(Math.abs(random.nextInt(1000)));
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
33 changes: 33 additions & 0 deletions src/test/java/org/scalasbt/ipcsocket/duplex/Sender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.scalasbt.ipcsocket.duplex;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Random;

public class Sender implements Runnable {

private final String name;
private final Socket socket;
private final int sendMessages;
private final Random random = new Random();

public Sender(String name, Socket socket, int sendMessages) {
this.name = name;
this.socket = socket;
this.sendMessages = sendMessages;
}

@Override
public void run() {
try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
for (int i = 0; i < sendMessages; i++) {
System.out.println("[" + name + "] sending msg: " + i);
out.println("hello" + i);
Thread.sleep(Math.abs(random.nextInt(1000)));
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}