| package com.gemstone.gemfire.internal.process; |
| |
| import static org.junit.Assert.*; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.Future; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| |
| import org.jmock.Mockery; |
| import org.jmock.lib.legacy.ClassImposteriser; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| import org.junit.rules.ExpectedException; |
| import org.junit.rules.TemporaryFolder; |
| |
| import com.gemstone.gemfire.internal.util.StopWatch; |
| import com.gemstone.gemfire.test.junit.categories.UnitTest; |
| import com.gemstone.gemfire.test.junit.rules.ExpectedTimeout; |
| |
| /** |
| * Unit tests the PidFile class. |
| * |
| * @author Kirk Lund |
| * @since 8.2 |
| */ |
| @Category(UnitTest.class) |
| public class PidFileJUnitTest { |
| |
| @Rule |
| public TemporaryFolder testFolder = new TemporaryFolder(); |
| |
| @Rule |
| public ExpectedException thrown = ExpectedException.none(); |
| |
| @Rule |
| public ExpectedTimeout timeout = ExpectedTimeout.none(); |
| |
| protected Mockery mockContext; |
| private ExecutorService futures; |
| |
| @Before |
| public void before() { |
| mockContext = new Mockery() {{ |
| setImposteriser(ClassImposteriser.INSTANCE); |
| }}; |
| this.futures = Executors.newFixedThreadPool(2); |
| } |
| |
| @After |
| public void after() { |
| mockContext.assertIsSatisfied(); |
| assertTrue(this.futures.shutdownNow().isEmpty()); |
| } |
| |
| @Test |
| public void readsIntFromFile() throws Exception { |
| final File file = testFolder.newFile("my.pid"); |
| final String value = "42"; |
| writeToFile(file, value); |
| |
| final int readValue = new PidFile(file).readPid(); |
| assertEquals(Integer.parseInt(value), readValue); |
| } |
| |
| @Test |
| public void readingEmptyFileThrowsIllegalArgumentException() throws Exception { |
| final File file = testFolder.newFile("my.pid"); |
| |
| thrown.expect(IllegalArgumentException.class); |
| thrown.expectMessage("Invalid pid 'null' found"); |
| |
| new PidFile(file).readPid(); |
| } |
| |
| @Test |
| public void readingFileWithNonIntegerThrowsIllegalArgumentException() throws Exception { |
| final File file = testFolder.newFile("my.pid"); |
| final String value = "fortytwo"; |
| writeToFile(file, value); |
| |
| thrown.expect(IllegalArgumentException.class); |
| thrown.expectMessage("Invalid pid '" + value + "' found"); |
| |
| new PidFile(file).readPid(); |
| } |
| |
| @Test |
| public void readingFileWithNegativeIntegerThrowsIllegalArgumentException() throws Exception { |
| final File file = testFolder.newFile("my.pid"); |
| final String value = "-42"; |
| writeToFile(file, value); |
| |
| thrown.expect(IllegalArgumentException.class); |
| thrown.expectMessage("Invalid pid '" + value + "' found"); |
| |
| new PidFile(file).readPid(); |
| } |
| |
| @Test |
| public void readingNullFileThrowsNullPointerException() throws Exception { |
| final File file = null; |
| |
| thrown.expect(NullPointerException.class); |
| |
| new PidFile(file).readPid(); |
| } |
| |
| @Test |
| public void timesOutReadingFromEmptyFile() throws Exception { |
| final File file = testFolder.newFile("my.pid"); |
| |
| timeout.expect(TimeoutException.class); |
| timeout.expectMessage("Invalid pid 'null' found"); |
| timeout.expectMinimumDuration(1000); |
| timeout.expectMaximumDuration(2000); |
| timeout.expectTimeUnit(TimeUnit.MILLISECONDS); |
| |
| new PidFile(file).readPid(1500, TimeUnit.MILLISECONDS); |
| } |
| |
| @Test |
| public void readsIntBeforeTimeout() throws Exception { |
| final int AWAIT_LATCH_TIMEOUT_MILLIS = 10*1000; |
| final int OPEN_LATCH_DELAY_MILLIS = 2*1000; |
| final int FUTURE_GET_TIMEOUT_MILLIS = 2*1000; |
| final int READ_PID_TIMEOUT_MILLIS = 2*OPEN_LATCH_DELAY_MILLIS; |
| |
| final File file = testFolder.newFile("my.pid"); |
| final FileWriter writer = new FileWriter(file); |
| |
| final CountDownLatch writePidLatch = new CountDownLatch(1); |
| final String value = "42"; |
| |
| // start Future to write the pid later but before timeout |
| Future<Boolean> futureWritePid = this.futures.submit(new Callable<Boolean>() { |
| @Override |
| public Boolean call() throws Exception { |
| writePidLatch.await(AWAIT_LATCH_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| writeToFile(file, value); |
| return true; |
| } |
| }); |
| |
| // start Future to sleep and release the delay |
| Future<Boolean> futureOpenLatch = this.futures.submit(new Callable<Boolean>() { |
| @Override |
| public Boolean call() throws Exception { |
| Thread.sleep(OPEN_LATCH_DELAY_MILLIS); |
| writePidLatch.countDown(); |
| return true; |
| } |
| }); |
| |
| StopWatch stopWatch = new StopWatch(true); |
| final int readValue = new PidFile(file).readPid(READ_PID_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| assertEquals(Integer.parseInt(value), readValue); |
| |
| long duration = stopWatch.elapsedTimeMillis(); |
| assertTrue(duration > OPEN_LATCH_DELAY_MILLIS); |
| assertTrue(duration < READ_PID_TIMEOUT_MILLIS); |
| |
| assertEquals(0, writePidLatch.getCount()); |
| assertTrue(futureOpenLatch.get(FUTURE_GET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); |
| assertTrue(futureWritePid.get(FUTURE_GET_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); |
| } |
| |
| @Test |
| public void findsCorrectFile() throws Exception { |
| final File directory = testFolder.getRoot(); |
| |
| final String fileNames[] = new String[] { "other.txt", "my.txt", "a.log", "b.log" }; |
| for (String fileName : fileNames) { |
| testFolder.newFile(fileName); |
| } |
| |
| final int pidValue = 42; |
| final File file = testFolder.newFile("my.pid"); |
| writeToFile(file, String.valueOf(pidValue)); |
| |
| final File other = testFolder.newFile("other.pid"); |
| writeToFile(other, "43"); |
| |
| final File[] files = directory.listFiles(); |
| assertEquals(fileNames.length + 2, files.length); |
| |
| PidFile pidFile = new PidFile(directory, file.getName()); |
| assertEquals(file, pidFile.getFile()); |
| |
| int value = pidFile.readPid(); |
| assertEquals(pidValue, value); |
| } |
| |
| @Test |
| public void missingFileInEmptyDirectoryThrowsFileNotFoundException() throws Exception { |
| final File directory = testFolder.getRoot(); |
| |
| final String pidFileName = "my.pid"; |
| |
| thrown.expect(FileNotFoundException.class); |
| thrown.expectMessage("Unable to find PID file '" + pidFileName + "' in directory " + directory); |
| |
| new PidFile(directory, pidFileName); |
| } |
| |
| @Test |
| public void missingFileThrowsFileNotFoundException() throws Exception { |
| final String pidFileName = "my.pid"; |
| |
| final File directory = testFolder.getRoot(); |
| final File file = new File(directory, pidFileName); |
| |
| thrown.expect(FileNotFoundException.class); |
| thrown.expectMessage("Unable to find PID file '" + file + "'"); |
| |
| new PidFile(file); |
| } |
| |
| @Test |
| public void missingFileInFullDirectoryThrowsFileNotFoundException() throws Exception { |
| final File directory = testFolder.getRoot(); |
| |
| final String fileNames[] = new String[] { "other.txt", "my.txt", "a.log", "b.log" }; |
| for (String fileName : fileNames) { |
| testFolder.newFile(fileName); |
| } |
| |
| final File other = testFolder.newFile("other.pid"); |
| writeToFile(other, "43"); |
| |
| final File[] files = directory.listFiles(); |
| assertEquals(fileNames.length + 1, files.length); |
| |
| final String pidFileName = "my.pid"; |
| |
| thrown.expect(FileNotFoundException.class); |
| thrown.expectMessage("Unable to find PID file '" + pidFileName + "' in directory " + directory); |
| |
| new PidFile(directory, pidFileName); |
| } |
| |
| private void writeToFile(final File file, String value) throws IOException { |
| final FileWriter writer = new FileWriter(file); |
| writer.write(value); |
| writer.flush(); |
| writer.close(); |
| } |
| } |