mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-08 17:17:38 +00:00
Use UNIX Sockets for IPC
This commit is contained in:
@@ -3,7 +3,6 @@ package org.cryptomator.common;
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
@@ -14,7 +13,6 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@DisplayName("Environment Variables Test")
|
||||
public class EnvironmentTest {
|
||||
@@ -43,7 +41,7 @@ public class EnvironmentTest {
|
||||
public void testIpcPortPath() {
|
||||
System.setProperty("cryptomator.ipcPortPath", "~/.config/Cryptomator/ipcPort.bin:~/.Cryptomator/ipcPort.bin");
|
||||
|
||||
List<Path> result = env.getIpcPortPath().toList();
|
||||
List<Path> result = env.ipcSocketPath().toList();
|
||||
MatcherAssert.assertThat(result, Matchers.hasSize(2));
|
||||
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/.config/Cryptomator/ipcPort.bin"), //
|
||||
Paths.get("/home/testuser/.Cryptomator/ipcPort.bin")));
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.cryptomator.ipc;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.List;
|
||||
|
||||
public class HandleLaunchArgsMessageTest {
|
||||
|
||||
@Test
|
||||
public void testSendAndReceive(@TempDir Path tmpDir) throws IOException {
|
||||
var message = new HandleLaunchArgsMessage(List.of("hello world", "foo bar"));
|
||||
|
||||
var file = tmpDir.resolve("tmp.file");
|
||||
try (var ch = FileChannel.open(file, StandardOpenOption.CREATE_NEW, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||
message.send(ch);
|
||||
ch.position(0);
|
||||
if (IpcMessage.receive(ch) instanceof HandleLaunchArgsMessage received) {
|
||||
Assertions.assertArrayEquals(message.args().toArray(), received.args().toArray());
|
||||
} else {
|
||||
Assertions.fail("Received message of unexpected class");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceiveEmpty(@TempDir Path tmpDir) throws IOException {
|
||||
var message = new HandleLaunchArgsMessage(List.of());
|
||||
|
||||
var file = tmpDir.resolve("tmp.file");
|
||||
try (var ch = FileChannel.open(file, StandardOpenOption.CREATE_NEW, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||
message.send(ch);
|
||||
ch.position(0);
|
||||
if (IpcMessage.receive(ch) instanceof HandleLaunchArgsMessage received) {
|
||||
Assertions.assertArrayEquals(message.args().toArray(), received.args().toArray());
|
||||
} else {
|
||||
Assertions.fail("Received message of unexpected class");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.cryptomator.ipc;
|
||||
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class IpcCommunicatorTest {
|
||||
|
||||
@Test
|
||||
public void testSendAndReceive(@TempDir Path tmpDir) throws IOException, InterruptedException {
|
||||
var socketPath = tmpDir.resolve("foo.sock");
|
||||
try (var server = IpcCommunicator.create(List.of(socketPath));
|
||||
var client = IpcCommunicator.create(List.of(socketPath))) {
|
||||
Assertions.assertNotSame(server, client);
|
||||
|
||||
var cdl = new CountDownLatch(1);
|
||||
var executor = Executors.newSingleThreadExecutor();
|
||||
server.listen(new IpcMessageListener() {
|
||||
@Override
|
||||
public void revealRunningApp() {
|
||||
cdl.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLaunchArgs(List<String> args) {
|
||||
|
||||
}
|
||||
}, executor);
|
||||
client.sendRevealRunningApp();
|
||||
|
||||
Assertions.assertTimeoutPreemptively(Duration.ofMillis(300), (Executable) cdl::await);
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.cryptomator.ipc;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class LoopbackCommunicatorTest {
|
||||
|
||||
@Test
|
||||
public void testSendAndReceive() {
|
||||
try (var communicator = new LoopbackCommunicator()) {
|
||||
var cdl = new CountDownLatch(1);
|
||||
var executor = Executors.newSingleThreadExecutor();
|
||||
communicator.listen(new IpcMessageListener() {
|
||||
@Override
|
||||
public void revealRunningApp() {
|
||||
cdl.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLaunchArgs(List<String> args) {
|
||||
|
||||
}
|
||||
}, executor);
|
||||
communicator.sendRevealRunningApp();
|
||||
|
||||
Assertions.assertTimeoutPreemptively(Duration.ofMillis(300), (Executable) cdl::await);
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.cryptomator.ipc;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.List;
|
||||
|
||||
public class RevealRunningAppMessageTest {
|
||||
|
||||
@Test
|
||||
public void testSendAndReceive(@TempDir Path tmpDir) throws IOException {
|
||||
var message = new RevealRunningAppMessage();
|
||||
|
||||
var file = tmpDir.resolve("tmp.file");
|
||||
try (var ch = FileChannel.open(file, StandardOpenOption.CREATE_NEW, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||
message.send(ch);
|
||||
ch.position(0);
|
||||
if (IpcMessage.receive(ch) instanceof RevealRunningAppMessage received) {
|
||||
Assertions.assertNotNull(received);
|
||||
} else {
|
||||
Assertions.fail("Received message of unexpected class");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
@@ -38,7 +39,7 @@ public class FileOpenRequestHandlerTest {
|
||||
@Test
|
||||
@DisplayName("./cryptomator.exe foo bar")
|
||||
public void testOpenArgsWithCorrectPaths() {
|
||||
inTest.handleLaunchArgs(new String[]{"foo", "bar"});
|
||||
inTest.handleLaunchArgs(List.of("foo", "bar"));
|
||||
|
||||
AppLaunchEvent evt = queue.poll();
|
||||
Assertions.assertNotNull(evt);
|
||||
@@ -51,7 +52,7 @@ public class FileOpenRequestHandlerTest {
|
||||
public void testOpenArgsWithIncorrectPaths() {
|
||||
FileSystem fs = Mockito.mock(FileSystem.class);
|
||||
Mockito.when(fs.getPath("foo")).thenThrow(new InvalidPathException("foo", "foo is not a path"));
|
||||
inTest.handleLaunchArgs(fs, new String[]{"foo"});
|
||||
inTest.handleLaunchArgs(fs, List.of("foo"));
|
||||
|
||||
AppLaunchEvent evt = queue.poll();
|
||||
Assertions.assertNull(evt);
|
||||
@@ -63,7 +64,7 @@ public class FileOpenRequestHandlerTest {
|
||||
queue.add(new AppLaunchEvent(AppLaunchEvent.EventType.OPEN_FILE, Collections.emptyList()));
|
||||
Assumptions.assumeTrue(queue.remainingCapacity() == 0);
|
||||
|
||||
inTest.handleLaunchArgs(new String[]{"foo"});
|
||||
inTest.handleLaunchArgs(List.of("foo"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the accompanying LICENSE file.
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.launcher;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.launcher.IpcFactory.IpcEndpoint;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class IpcFactoryTest {
|
||||
|
||||
private Environment environment = Mockito.mock(Environment.class);
|
||||
private IpcProtocolImpl protocolHandler = Mockito.mock(IpcProtocolImpl.class);
|
||||
|
||||
@Test
|
||||
@DisplayName("Without IPC port files")
|
||||
public void testNoIpcWithoutPortFile() throws IOException {
|
||||
IpcFactory inTest = new IpcFactory(environment, protocolHandler);
|
||||
|
||||
Mockito.when(environment.getIpcPortPath()).thenReturn(Stream.empty());
|
||||
try (IpcEndpoint endpoint1 = inTest.create()) {
|
||||
Assertions.assertEquals(IpcFactory.SelfEndpoint.class, endpoint1.getClass());
|
||||
Assertions.assertFalse(endpoint1.isConnectedToRemote());
|
||||
Assertions.assertSame(protocolHandler, endpoint1.getRemote());
|
||||
try (IpcEndpoint endpoint2 = inTest.create()) {
|
||||
Assertions.assertEquals(IpcFactory.SelfEndpoint.class, endpoint2.getClass());
|
||||
Assertions.assertNotSame(endpoint1, endpoint2);
|
||||
Assertions.assertFalse(endpoint2.isConnectedToRemote());
|
||||
Assertions.assertSame(protocolHandler, endpoint2.getRemote());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Start server and client with port shared via file")
|
||||
public void testInterProcessCommunication(@TempDir Path tmpDir) throws IOException {
|
||||
Path portFile = tmpDir.resolve("testPortFile");
|
||||
Mockito.when(environment.getIpcPortPath()).thenReturn(Stream.of(portFile));
|
||||
IpcFactory inTest = new IpcFactory(environment, protocolHandler);
|
||||
|
||||
Assertions.assertFalse(Files.exists(portFile));
|
||||
try (IpcEndpoint endpoint1 = inTest.create()) {
|
||||
Assertions.assertEquals(IpcFactory.ServerEndpoint.class, endpoint1.getClass());
|
||||
Assertions.assertFalse(endpoint1.isConnectedToRemote());
|
||||
Assertions.assertTrue(Files.exists(portFile));
|
||||
Assertions.assertSame(protocolHandler, endpoint1.getRemote());
|
||||
Mockito.verifyZeroInteractions(protocolHandler);
|
||||
try (IpcEndpoint endpoint2 = inTest.create()) {
|
||||
Assertions.assertEquals(IpcFactory.ClientEndpoint.class, endpoint2.getClass());
|
||||
Assertions.assertNotSame(endpoint1, endpoint2);
|
||||
Assertions.assertTrue(endpoint2.isConnectedToRemote());
|
||||
Assertions.assertNotSame(protocolHandler, endpoint2.getRemote());
|
||||
Mockito.verifyZeroInteractions(protocolHandler);
|
||||
endpoint2.getRemote().handleLaunchArgs(new String[]{"foo"});
|
||||
Mockito.verify(protocolHandler).handleLaunchArgs(new String[]{"foo"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user