| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| package org.apache.poi.util.tests; |
| |
| import static org.apache.poi.util.DefaultTempFileCreationStrategy.POIFILES; |
| import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR; |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.poi.ss.usermodel.Cell; |
| import org.apache.poi.ss.usermodel.Row; |
| import org.apache.poi.util.TempFile; |
| import org.apache.poi.util.TempFileCreationStrategy; |
| import org.apache.poi.xssf.streaming.SXSSFSheet; |
| import org.apache.poi.xssf.streaming.SXSSFWorkbook; |
| import org.junit.jupiter.api.BeforeAll; |
| import org.junit.jupiter.api.BeforeEach; |
| import org.junit.jupiter.api.Test; |
| |
| class TestTempFileThreaded { |
| private static final int NUMBER_OF_THREADS = 10; |
| private static final int NUMBER_OF_TESTS = 200; |
| |
| private volatile Throwable exception; |
| private int[] executions; |
| |
| // the actual thread-safe temp-file strategy |
| private static TempFileCreationStrategy createTempFileCreationStrategy(File poiTempFileDirectory) { |
| return new TempFileCreationStrategy() { |
| @Override |
| public File createTempFile(String prefix, String suffix) throws IOException { |
| long threadId = Thread.currentThread().getId(); |
| File threadDir = new File(poiTempFileDirectory, Long.toString(threadId)); |
| if (!threadDir.exists()) { |
| if (!threadDir.mkdirs()) { |
| throw new IOException("mkdir of " + threadDir + " failed"); |
| } |
| } |
| |
| File file = File.createTempFile(prefix, suffix, threadDir); |
| file.deleteOnExit(); |
| return file; |
| } |
| |
| @Override |
| public File createTempDirectory(String prefix) { |
| throw new UnsupportedOperationException("createTempDirectory"); |
| } |
| }; |
| } |
| |
| @BeforeAll |
| public static void setUpClass() throws IOException { |
| String tmpDir = System.getProperty(JAVA_IO_TMPDIR); |
| if (tmpDir == null) { |
| throw new IOException("Systems temporary directory not defined - set the -D" + JAVA_IO_TMPDIR + " jvm property!"); |
| } |
| |
| TempFile.setTempFileCreationStrategy(createTempFileCreationStrategy(new File(new File(tmpDir, POIFILES), "TestTempFileThreaded"))); |
| } |
| |
| @BeforeEach |
| void setUp() { |
| // Initialize array to allow to summarize afterwards |
| executions = new int[NUMBER_OF_THREADS]; |
| } |
| |
| @Test |
| void runTest() throws Throwable { |
| List<Thread> threads = new LinkedList<>(); |
| |
| // start all threads |
| for (int i = 0; i < NUMBER_OF_THREADS; i++) { |
| Thread t = startThread(i, new TestRunnable()); |
| threads.add(t); |
| } |
| |
| // wait for all threads |
| for (int i = 0; i < NUMBER_OF_THREADS; i++) { |
| threads.get(i).join(); |
| } |
| |
| // report exceptions if there were any |
| if (exception != null) { |
| throw exception; |
| } |
| |
| // make sure the resulting number of executions is correct |
| for (int i = 0; i < NUMBER_OF_THREADS; i++) { |
| // check if enough items were performed |
| assertEquals(NUMBER_OF_TESTS, executions[i], "Thread " + i + " did not execute all iterations"); |
| } |
| } |
| |
| private static class TestRunnable { |
| Map<Integer, List<File>> files = new HashMap<>(); |
| |
| public TestRunnable() { |
| for (int i = 0; i < NUMBER_OF_THREADS; i++) { |
| files.put(i, new ArrayList<>()); |
| } |
| } |
| |
| void doEnd(int threadNum) { |
| for (File file : files.get(threadNum)) { |
| if (!file.exists()) { |
| throw new IllegalStateException("File " + file + " does not exist"); |
| } |
| if (!file.delete()) { |
| throw new IllegalStateException("Deletion of " + file + " failed"); |
| } |
| } |
| } |
| |
| void run(int threadNum, int iter) throws Exception { |
| try (SXSSFWorkbook wb = new SXSSFWorkbook()) { |
| SXSSFSheet sheet = wb.createSheet("test"); |
| |
| for (int i = 0; i < 100; i++) { |
| Row row = sheet.createRow(i); |
| for (int j = 0; j < 10; j++) { |
| Cell cell = row.createCell(j); |
| cell.setCellValue("123"); |
| } |
| } |
| |
| File file = TempFile.createTempFile("TestTempFile-" + threadNum + "-" + iter + "-", ".xlsx"); |
| try (OutputStream outputStream = new FileOutputStream(file)) { |
| wb.write(outputStream); |
| } |
| |
| files.get(threadNum).add(file); |
| } |
| } |
| } |
| |
| private Thread startThread(final int threadNum, final TestRunnable run) { |
| Thread t1 = new Thread(() -> { |
| try { |
| for (int iter = 0; iter < NUMBER_OF_TESTS && exception == null; iter++) { |
| // call the actual test-code |
| run.run(threadNum, iter); |
| |
| executions[threadNum]++; |
| } |
| |
| // do end-work here, we don't do this in a finally as we log |
| // Exception |
| // then anyway |
| run.doEnd(threadNum); |
| } catch (Throwable e) { |
| exception = e; |
| } |
| |
| }, "ThreadTestHelper-Thread " + threadNum + ": " + run.getClass().getName()); |
| |
| t1.start(); |
| |
| return t1; |
| } |
| } |