Skip to content

Commit

Permalink
Disable the tests that involve NIO.2 WatchService on old JRE (#4903)
Browse files Browse the repository at this point in the history
Motivation:

At least on macOS 13.4 (and probably other OSes), `WatchService` seems not to notify the file changes quickly enough. As a result, we see the following tests fail:

- `FileWatcherRegistryTest.runnableWithExceptionContinuesRun`
- `PropertiesEndpointGroupTest.endpointChangePropagatesToListeners`
- `PropertiesEndpointGroupTest.propertiesFileRestart`
- `PropertiesEndpointGroupTest.propertiesFileUpdatesCorrectly`

Modifications:

- Migrated `FileWatcherRegistryTest` and `PropertiesEndpointGroupTest` from JUnit 4 to 5
- Added `@EnabledForJreRange` annotation on the problematic tests

Result:

- Build is more stable on the environment where `WatchService` is not very responsive.
- Fixes #3474 and #3075
  • Loading branch information
trustin committed Jun 2, 2023
1 parent f4b223a commit 436cf73
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 100 deletions.
Expand Up @@ -19,40 +19,42 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.awaitility.Awaitility;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.io.TempDir;

import com.linecorp.armeria.client.endpoint.FileWatcherRegistry.FileWatchRegisterKey;

public class FileWatcherRegistryTest {
class FileWatcherRegistryTest {

@BeforeClass
public static void before() {
@BeforeAll
static void before() {
Awaitility.setDefaultTimeout(1, TimeUnit.MINUTES);
}

@AfterClass
public static void after() {
@AfterAll
static void after() {
Awaitility.setDefaultTimeout(10, TimeUnit.SECONDS);
}

Expand All @@ -62,7 +64,7 @@ private static Path createMockedPath() throws Exception {
final FileSystem fileSystem = mock(FileSystem.class);
final WatchService watchService = mock(WatchService.class);
final WatchKey watchKey = mock(WatchKey.class);
when(path.toRealPath()).thenReturn(path);
lenient().when(path.toRealPath()).thenReturn(path);
when(path.getParent()).thenReturn(path);
when(path.getFileSystem()).thenReturn(fileSystem);
when(fileSystem.newWatchService()).thenReturn(watchService);
Expand All @@ -73,47 +75,47 @@ private static Path createMockedPath() throws Exception {
}
return watchKey;
});
when(watchKey.reset()).thenReturn(true);
lenient().when(watchKey.reset()).thenReturn(true);
return path;
}

@After
public void tearDown() throws Exception {
@AfterEach
void tearDown() throws Exception {
PropertiesEndpointGroup.resetRegistry();
}

@Rule
public TemporaryFolder folder = new TemporaryFolder();
@TempDir
Path folder;

@Test
public void emptyGroupStopsBackgroundThread() throws Exception {
void emptyGroupStopsBackgroundThread() throws Exception {

final File file = folder.newFile("temp-file.properties");
final File file2 = folder.newFile("temp-file2.properties");
final Path file = Files.createFile(folder.resolve("temp-file.properties"));
final Path file2 = Files.createFile(folder.resolve("temp-file2.properties"));

final FileWatcherRegistry fileWatcherRegistry =
new FileWatcherRegistry();
final FileWatchRegisterKey key1 = fileWatcherRegistry.register(file.toPath(), () -> {});
final FileWatchRegisterKey key2 = fileWatcherRegistry.register(file2.toPath(), () -> {});
try (FileWatcherRegistry fileWatcherRegistry = new FileWatcherRegistry()) {
final FileWatchRegisterKey key1 = fileWatcherRegistry.register(file, () -> {});
final FileWatchRegisterKey key2 = fileWatcherRegistry.register(file2, () -> {});

assertThat(fileWatcherRegistry.isRunning()).isTrue();
assertThat(fileWatcherRegistry.isRunning()).isTrue();

fileWatcherRegistry.unregister(key1);
fileWatcherRegistry.unregister(key1);

assertThat(fileWatcherRegistry.isRunning()).isTrue();
assertThat(fileWatcherRegistry.isRunning()).isTrue();

fileWatcherRegistry.unregister(key2);
fileWatcherRegistry.unregister(key2);

assertThat(fileWatcherRegistry.isRunning()).isFalse();
assertThat(fileWatcherRegistry.isRunning()).isFalse();
}
}

@Test
public void closeEndpointGroupStopsRegistry() throws Exception {
void closeEndpointGroupStopsRegistry() throws Exception {

final File file = folder.newFile("temp-file.properties");
final Path file = Files.createFile(folder.resolve("temp-file.properties"));

final FileWatcherRegistry fileWatcherRegistry = new FileWatcherRegistry();
fileWatcherRegistry.register(file.toPath(), () -> {});
fileWatcherRegistry.register(file, () -> {});

assertThat(fileWatcherRegistry.isRunning()).isTrue();

Expand All @@ -123,31 +125,32 @@ public void closeEndpointGroupStopsRegistry() throws Exception {
}

@Test
public void runnableWithExceptionContinuesRun() throws Exception {
@EnabledForJreRange(min = JRE.JAVA_17) // NIO.2 WatchService doesn't work reliably on older Java.
void runnableWithExceptionContinuesRun() throws Exception {

final File file = folder.newFile("temp-file.properties");
final Path file = Files.createFile(folder.resolve("temp-file.properties"));
final FileWatcherRegistry fileWatcherRegistry = new FileWatcherRegistry();

final AtomicInteger val = new AtomicInteger(0);
final FileWatchRegisterKey key = fileWatcherRegistry.register(file.toPath(), () -> {
final FileWatchRegisterKey key = fileWatcherRegistry.register(file, () -> {
try {
final BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
final BufferedReader bufferedReader = new BufferedReader(new FileReader(file.toFile()));
val.set(Integer.valueOf(bufferedReader.readLine()));
} catch (IOException e) {
// do nothing
}
throw new RuntimeException();
});

PrintWriter printWriter = new PrintWriter(file);
PrintWriter printWriter = new PrintWriter(file.toFile());
printWriter.print(1);
printWriter.close();

await().untilAsserted(() -> assertThat(val.get()).isEqualTo(1));

assertThat(fileWatcherRegistry.isRunning()).isTrue();

printWriter = new PrintWriter(file);
printWriter = new PrintWriter(file.toFile());
printWriter.print(2);
printWriter.close();

Expand All @@ -163,21 +166,22 @@ public void runnableWithExceptionContinuesRun() throws Exception {
}

@Test
public void testMultipleFileSystems() throws Exception {

final FileWatcherRegistry fileWatcherRegistry = new FileWatcherRegistry();

final Path path1 = createMockedPath();
final Path path2 = createMockedPath();

final FileWatchRegisterKey key1 = fileWatcherRegistry.register(path1, () -> {});
final FileWatchRegisterKey key2 = fileWatcherRegistry.register(path2, () -> {});
assertThat(fileWatcherRegistry.isRunning()).isTrue();

fileWatcherRegistry.unregister(key1);
assertThat(fileWatcherRegistry.isRunning()).isTrue();

fileWatcherRegistry.unregister(key2);
assertThat(fileWatcherRegistry.isRunning()).isFalse();
void testMultipleFileSystems() throws Exception {
try (FileWatcherRegistry fileWatcherRegistry = new FileWatcherRegistry()) {
final Path path1 = createMockedPath();
final Path path2 = createMockedPath();

final FileWatchRegisterKey key1 = fileWatcherRegistry.register(path1, () -> {
});
final FileWatchRegisterKey key2 = fileWatcherRegistry.register(path2, () -> {
});
assertThat(fileWatcherRegistry.isRunning()).isTrue();

fileWatcherRegistry.unregister(key1);
assertThat(fileWatcherRegistry.isRunning()).isTrue();

fileWatcherRegistry.unregister(key2);
assertThat(fileWatcherRegistry.isRunning()).isFalse();
}
}
}

0 comments on commit 436cf73

Please sign in to comment.