From d2c3c7e004fdb61ad5146841a4e7a8ca7bdf449f Mon Sep 17 00:00:00 2001 From: Dominik Stadler Date: Thu, 5 Jul 2018 19:53:44 +0000 Subject: [PATCH] Add a test with a threaded TempFileCreationStrategy, remove duplicated constant. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1835182 13f79535-47bb-0310-9956-ffa450edef68 --- .../util/DefaultTempFileCreationStrategy.java | 5 +- .../apache/poi/util/TestTempFileThreaded.java | 188 ++++++++++++++++++ 2 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 src/ooxml/testcases/org/apache/poi/util/TestTempFileThreaded.java diff --git a/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java b/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java index f14871daf8..5a17d04a1d 100644 --- a/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java +++ b/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java @@ -21,6 +21,8 @@ import java.io.File; import java.io.IOException; import java.security.SecureRandom; +import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR; + /** * Default implementation of the {@link TempFileCreationStrategy} used by {@link TempFile}: * Files are collected into one directory and by default are deleted on exit from the VM. @@ -34,9 +36,6 @@ import java.security.SecureRandom; * processes or limited temporary storage. */ public class DefaultTempFileCreationStrategy implements TempFileCreationStrategy { - /** Define a constant for this property as it is sometimes mistypes as "tempdir" otherwise - * This is private to avoid having two public-visible constants ({@link TempFile#JAVA_IO_TMPDIR}). */ - private static final String JAVA_IO_TMPDIR = TempFile.JAVA_IO_TMPDIR; /*package*/ static final String POIFILES = "poifiles"; /** To keep files after JVM exit, set the -Dpoi.keep.tmp.files JVM property */ diff --git a/src/ooxml/testcases/org/apache/poi/util/TestTempFileThreaded.java b/src/ooxml/testcases/org/apache/poi/util/TestTempFileThreaded.java new file mode 100644 index 0000000000..e154adcdc5 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/util/TestTempFileThreaded.java @@ -0,0 +1,188 @@ +/* ==================================================================== + 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; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +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 static org.apache.poi.util.DefaultTempFileCreationStrategy.POIFILES; +import static org.apache.poi.util.TempFile.JAVA_IO_TMPDIR; +import static org.junit.Assert.assertEquals; + +public 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"); + } + }; + } + + @BeforeClass + 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"))); + } + + @Before + public void setUp() { + // Initialize array to allow to summarize afterwards + executions = new int[NUMBER_OF_THREADS]; + } + + @Test + public void runTest() throws Throwable { + List 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("Thread " + i + + " did not execute all iterations", NUMBER_OF_TESTS, + executions[i]); + } + } + + private static class TestRunnable { + Map> files = new HashMap<>(); + + public TestRunnable() { + for (int i = 0; i < NUMBER_OF_THREADS; i++) { + files.put(i, new ArrayList<>()); + } + } + + public 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"); + } + } + } + + public 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); + + if (iter % 30 == 0) { + System.out.println("thread: " + threadNum + ", iter: " + iter + ": " + 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; + } +} -- 2.39.5