temporary commit

This commit is contained in:
2025-01-23 18:00:47 +08:00
parent d61cfc6ea7
commit 08e79fd833
7 changed files with 448 additions and 56 deletions
+21 -1
View File
@@ -1,11 +1,15 @@
plugins {
id 'java-library'
alias(catalog.plugins.lombok)
alias(catalog.plugins.envelope)
}
import org.gradle.api.attributes.LibraryElements
import static org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE
import static org.gradle.api.attributes.LibraryElements.JAR
import net.woggioni.gradle.envelope.EnvelopeJarTask
import net.woggioni.gradle.envelope.EnvelopePlugin
configurations {
testImplementation {
@@ -25,7 +29,23 @@ java {
modularity.inferModulePath = true
}
Provider<EnvelopeJarTask> envelopeJarTaskProvider = tasks.named(EnvelopePlugin.ENVELOPE_JAR_TASK_NAME, EnvelopeJarTask.class) {
mainModule = "net.woggioni.jwo.lockfile.test"
mainClass = "net.woggioni.jwo.lockfile.test.LockFileTestMain"
}
dependencies {
implementation rootProject
testImplementation catalog.slf4j.api
testImplementation project(':jwo-test-module')
testImplementation project(':')
}
testRuntimeOnly catalog.slf4j.simple
}
test {
dependsOn(envelopeJarTaskProvider)
systemProperty('lockFileTest.executable.jar', envelopeJarTaskProvider.flatMap {it.archiveFile}.get().getAsFile())
systemProperty('org.slf4j.simpleLogger.showDateTime', 'true')
}
+6
View File
@@ -0,0 +1,6 @@
module net.woggioni.jwo.lockfile.test {
requires net.woggioni.jwo;
requires static lombok;
exports net.woggioni.jwo.lockfile.test;
}
@@ -0,0 +1,33 @@
package net.woggioni.jwo.lockfile.test;
import lombok.SneakyThrows;
import net.woggioni.jwo.LockFile;
import net.woggioni.jwo.Run;
import java.nio.file.Path;
import java.nio.file.Paths;
public class LockFileTestMain {
@SneakyThrows
public static void main(String[] args) {
Path lockfilePath = Paths.get(args[0]);
boolean shared = Boolean.parseBoolean(args[1]);
boolean keep = Boolean.parseBoolean(args[2]);
Thread t = new Thread((Run)() -> {
try (AutoCloseable lockfile = LockFile.acquire(lockfilePath, shared)) {
while (keep) {
Thread.sleep(1000);
}
}
});
t.start();
try (AutoCloseable lockfile = LockFile.acquire(lockfilePath, shared)) {
while (keep) {
Thread.sleep(1000);
}
}
t.join();
}
}
+1
View File
@@ -1,4 +1,5 @@
open module net.woggioni.jwo.unit.test {
requires org.slf4j;
requires net.woggioni.jwo;
requires net.woggioni.jwo.test.module;
requires org.junit.jupiter.api;
@@ -0,0 +1,125 @@
package net.woggioni.jwo.test;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import net.woggioni.jwo.JavaProcessBuilder;
import net.woggioni.jwo.LockFile;
import net.woggioni.jwo.Run;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class LockFileTest {
private static Logger log = LoggerFactory.getLogger(LockFileTest.class);
@TempDir
public Path testDir;
private Path executablePath = Paths.get(System.getProperty("lockFileTest.executable.jar"));
@RequiredArgsConstructor
private static class LockFileTestMainArgs {
final Path lockFilePath;
final boolean shared;
final boolean keep;
public List<String> getArgs() {
return Arrays.asList(lockFilePath.toString(), Boolean.toString(shared), Boolean.toString(keep));
}
}
@SneakyThrows
private static void kill(Process p) {
if (p != null && p.isAlive()) p.destroyForcibly().waitFor();
}
@Test
@SneakyThrows
public void testExclusiveLockHeldOnFile() {
Path lockFilePath = Files.createFile(testDir.resolve("file.lock"));
// try to acquire an exclusive lock and check that the process returns immediately
JavaProcessBuilder javaProcessBuilder = new JavaProcessBuilder();
javaProcessBuilder.setExecutableJar(executablePath);
javaProcessBuilder.setCliArgs(new LockFileTestMainArgs(lockFilePath, false, false).getArgs());
Process process = javaProcessBuilder.build()
.inheritIO()
.start();
Assertions.assertTrue(process.waitFor(1, TimeUnit.SECONDS));
Assertions.assertEquals(0, process.exitValue());
Process sharedLockProcess = null;
Process anotherSharedLockProcess = null;
Process exclusiveLockProcess = null;
try {
// try to acquire and keep a shared lock on the file and check that the process does not exit
javaProcessBuilder.setCliArgs(new LockFileTestMainArgs(lockFilePath, true, true).getArgs());
sharedLockProcess = javaProcessBuilder.build()
.inheritIO()
.start();
Assertions.assertFalse(sharedLockProcess.waitFor(1000, TimeUnit.MILLISECONDS));
// try to acquire another shared lock on the file and check that the process is able to terminate
javaProcessBuilder.setCliArgs(new LockFileTestMainArgs(lockFilePath, true, false).getArgs());
anotherSharedLockProcess = javaProcessBuilder.build()
.inheritIO()
.start();
Assertions.assertTrue(anotherSharedLockProcess.waitFor(1, TimeUnit.SECONDS));
// try to acquire an exclusive lock on the file and check that process hangs
javaProcessBuilder.setCliArgs(new LockFileTestMainArgs(lockFilePath, false, false).getArgs());
exclusiveLockProcess = javaProcessBuilder.build()
.inheritIO()
.start();
Assertions.assertFalse(exclusiveLockProcess.waitFor(1, TimeUnit.SECONDS));
// kill the process holding the shared lock and check that the process holding the exclusive lock terminates
sharedLockProcess.destroyForcibly().waitFor();
Assertions.assertTrue(exclusiveLockProcess.waitFor(1, TimeUnit.SECONDS));
Assertions.assertEquals(0, exclusiveLockProcess.exitValue());
} finally {
kill(sharedLockProcess);
kill(anotherSharedLockProcess);
kill(exclusiveLockProcess);
}
}
@Test
@SneakyThrows
public void sameProcessTest(@TempDir Path testDir) {
Path lockfile = testDir.resolve("file.lock");
Run writerRunnable = () -> {
try(AutoCloseable lock = LockFile.acquire(lockfile, false)) {
log.info("Writer start!!!!");
Thread.sleep(1000);
log.info("Writer end!!!!");
}
};
Thread writer = new Thread(writerRunnable);
Run readerRunnable = () -> {
try(AutoCloseable lock = LockFile.acquire(lockfile, true)) {
log.info("reader start");
Thread.sleep(1000);
log.info("reader end");
}
};
Thread t1 = new Thread(readerRunnable);
Thread t2 = new Thread(readerRunnable);
writer.start();
t1.start();
t2.start();
writer.join();
t1.join();
t2.join();
log.info("FINISHED");
}
}