mirror of
https://github.com/elastic/logstash.git
synced 2025-04-24 14:47:19 -04:00
Add test case for FileLockFactory
This change introduce a test for cross-process/jvm file locking using the FileLockFactory class. It uses a client program that will lock a file aftwards the test case proceed. Fixes #6610 Fixes #7117
This commit is contained in:
parent
47517b8932
commit
95347b6025
4 changed files with 83 additions and 10 deletions
9
bin/lock
9
bin/lock
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/env bin/ruby
|
||||
|
||||
require_relative "../lib/bootstrap/environment"
|
||||
LogStash::Bundler.setup!({:without => [:build, :development]})
|
||||
require "logstash-core"
|
||||
|
||||
lock = Java::OrgLogstash::FileLockFactory.getDefault.obtainLock(ARGV[0], ".lock")
|
||||
puts("locking " + File.join(ARGV[0], ".lock"))
|
||||
sleep
|
|
@ -0,0 +1,23 @@
|
|||
package org.logstash;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* This program is used to test the FileLockFactory in cross-process/JVM.
|
||||
*/
|
||||
public class FileLockFactoryMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
FileLockFactory.getDefault().obtainLock(args[0], args[1]);
|
||||
System.out.println("File locked");
|
||||
// Sleep enough time until this process is killed.
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
} catch (InterruptedException e) {
|
||||
// This process is killed. Do nothing.
|
||||
} catch (IOException e) {
|
||||
// Failed to obtain the lock.
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,24 @@
|
|||
package org.logstash;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
@ -24,9 +32,12 @@ public class FileLockFactoryTest {
|
|||
|
||||
private FileLock lock;
|
||||
|
||||
private ExecutorService executor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
lockDir = temporaryFolder.newFolder("lock").getPath();
|
||||
executor = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
|
||||
@Before
|
||||
|
@ -36,6 +47,14 @@ public class FileLockFactoryTest {
|
|||
assertThat(lock.isShared(), is(equalTo(false)));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
executor.shutdownNow();
|
||||
if (!executor.awaitTermination(2L, TimeUnit.MINUTES)) {
|
||||
throw new IllegalStateException("Failed to shut down Executor");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ObtainLockOnNonLocked() throws IOException {
|
||||
// empty to just test the lone @Before lockFirst() test
|
||||
|
@ -88,4 +107,45 @@ public class FileLockFactoryTest {
|
|||
FileLockFactory.getDefault().releaseLock(lock);
|
||||
FileLockFactory.getDefault().releaseLock(lock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crossJvmObtainLockOnLocked() throws Exception {
|
||||
Process p = null;
|
||||
String lockFile = ".testCrossJvm";
|
||||
FileLock lock = null;
|
||||
|
||||
// Build the command to spawn a children JVM.
|
||||
String[] cmd = {
|
||||
Paths.get(System.getProperty("java.home"), "bin", "java").toString(),
|
||||
"-cp", System.getProperty("java.class.path"),
|
||||
Class.forName("org.logstash.FileLockFactoryMain").getName(),
|
||||
lockDir, lockFile
|
||||
};
|
||||
|
||||
try {
|
||||
// Start the children program that will lock the file.
|
||||
p = new ProcessBuilder(cmd).start();
|
||||
InputStream is = p.getInputStream();
|
||||
/* Wait the children program write to stdout, meaning the file
|
||||
* is locked. Set a timeout to ensure it returns.
|
||||
*/
|
||||
Future<Integer> future = executor.submit(() -> {return is.read();});
|
||||
assertTrue(future.get(30, TimeUnit.SECONDS) > -1);
|
||||
|
||||
// Check the children process is still running.
|
||||
assertThat(p.isAlive(), is(equalTo(true)));
|
||||
|
||||
try {
|
||||
// Try to obtain the lock held by the children process.
|
||||
FileLockFactory.getDefault().obtainLock(lockDir, lockFile);
|
||||
fail("Should have threw an exception");
|
||||
} catch (LockException e) {
|
||||
// Expected exception as the file is already locked.
|
||||
}
|
||||
} finally {
|
||||
if (p != null) {
|
||||
p.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ namespace "artifact" do
|
|||
@exclude_paths << "bin/bundle"
|
||||
@exclude_paths << "bin/rspec"
|
||||
@exclude_paths << "bin/rspec.bat"
|
||||
@exclude_paths << "bin/lock"
|
||||
|
||||
@exclude_paths
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue