package edu.stanford.slac.archiverappliance.PB.compression.zipfs; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import java.io.File; import java.io.FileOutputStream; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import junit.framework.TestCase; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.epics.archiverappliance.config.ConfigServiceForTests; import org.epics.archiverappliance.utils.nio.ArchPaths; import org.junit.After; import org.junit.Before; import org.junit.Test; public class ArchPathsTest extends TestCase { private String rootFolderStr = ConfigServiceForTests.getDefaultPBTestFolder() + "/ArchPathsTest"; private static Logger logger = Logger.getLogger(ArchPathsTest.class.getName()); @Before public void setUp() throws Exception { File rootFolder = new File(rootFolderStr); FileUtils.deleteDirectory(rootFolder); rootFolder.mkdirs(); // We create some sample files for testing. for(int filenum = 1; filenum < 100; filenum++) { try(PrintWriter out = new PrintWriter(new FileOutputStream(new File(rootFolderStr + File.separator + "text" + filenum + ".txt")))) { for(int i = 0; i < 1000; i++) { out.println("Line " + i); } } } } @After public void tearDown() throws Exception { // FileUtils.deleteDirectory(new File(rootFolderStr)); } @Test public void testPack() throws Exception { String zipFileName = rootFolderStr + "/pack.zip"; String zipFilePath = "jar:file://" + zipFileName + "!/result/SomeTextFile.txt"; try(ArchPaths arch = new ArchPaths()) { Path sourcePath = arch.get(rootFolderStr + "/text1.txt"); Path destPath = arch.get(zipFilePath, true); Files.copy(sourcePath, destPath, REPLACE_EXISTING); } assertTrue("Zip file does not exist " + zipFileName, new File(zipFileName).exists()); try(ArchPaths validateArchPaths = new ArchPaths()) { assertTrue("Path does not exist after packing " + zipFilePath, Files.exists(validateArchPaths.get(zipFilePath))); } // Now we test adding more files. try(ArchPaths arch= new ArchPaths()) { for(int filenum = 2; filenum < 10; filenum++) { Path sourcePath = arch.get(rootFolderStr + "/text" + filenum + ".txt"); Path destPath = arch.get("jar:file://" + zipFileName + "!/result/SomeTextFile" + filenum + ".txt"); logger.debug("Packing " + sourcePath.toString() + " into " + destPath.toString()); Files.copy(sourcePath, destPath, REPLACE_EXISTING); } } try(ArchPaths validateArchPaths = new ArchPaths()) { for(int filenum = 2; filenum < 10; filenum++) { assertTrue("Path does not exist after packing " + zipFilePath, Files.exists(validateArchPaths.get("jar:file:///" + zipFileName + "!/result/SomeTextFile" + filenum + ".txt"))); } } } @Test public void testConcurrentAccess() throws Exception { // Test to see if we can access the zip file concurrently. // We launch two threads and see if one can add while the other can read final String zipFileName = rootFolderStr + "/concurrpack.zip"; Runnable writer = new Runnable() { @Override public void run() { int exceptionCount = 0; try { for(int filenum = 1; filenum < 100; filenum++) { try(ArchPaths paths = new ArchPaths()) { Path sourcePath = paths.get(rootFolderStr + "/text" + filenum + ".txt"); Path destPath = paths.get("jar:file://" + zipFileName + "!/result/SomeTextFile" + filenum + ".txt", true); logger.debug("Packing " + sourcePath.toString() + " into " + destPath.toString()); Files.copy(sourcePath, destPath, REPLACE_EXISTING); } catch(Exception ex) { exceptionCount++; logger.error("Exception writing file", ex); } Thread.sleep(10); } } catch(Exception ex) { logger.error(ex); } assertTrue("The write thread had " + exceptionCount + " exceptions", exceptionCount == 0); } }; final Thread writerThread = new Thread(writer); writerThread.setName("Writer"); writerThread.start(); Runnable reader = new Runnable() { @Override public void run() { int exceptionCount = 0; boolean checkedAtLeastOnce = false; while(writerThread.isAlive()) { if(new File(zipFileName).exists()) { logger.debug("Checking concurrent access"); try { for(int filenum = 1; filenum < 100; filenum++) { try(ArchPaths paths = new ArchPaths()) { checkedAtLeastOnce = true; Path destPath = paths.get("jar:file://" + zipFileName + "!/result/SomeTextFile" + filenum + ".txt"); Files.exists(destPath); } catch(Exception ex) { exceptionCount++; logger.error("Exception reading file", ex); } } Thread.sleep(10); } catch(Exception ex) { logger.error(ex); } } else { logger.debug("Skipping checking concurrent access"); } } assertTrue("We have not check the reader part even once ", checkedAtLeastOnce); assertTrue("The read thread had " + exceptionCount + " exceptions", exceptionCount == 0); } }; Thread readerthread = new Thread(reader); readerthread.setName("Reader"); readerthread.start(); } }