1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.io; 18 19 import com.google.errorprone.annotations.CanIgnoreReturnValue; 20 import java.io.File; 21 import java.io.FileOutputStream; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.OutputStream; 25 import java.net.URL; 26 import java.util.HashSet; 27 import java.util.Set; 28 import java.util.logging.Level; 29 import java.util.logging.Logger; 30 import junit.framework.TestCase; 31 import org.checkerframework.checker.nullness.qual.Nullable; 32 33 /** 34 * Base test case class for I/O tests. 35 * 36 * @author Chris Nokleberg 37 * @author Colin Decker 38 */ 39 public abstract class IoTestCase extends TestCase { 40 41 private static final Logger logger = Logger.getLogger(IoTestCase.class.getName()); 42 43 static final String I18N = 44 "\u00CE\u00F1\u0163\u00E9\u0072\u00F1\u00E5\u0163\u00EE\u00F6" 45 + "\u00F1\u00E5\u013C\u00EE\u017E\u00E5\u0163\u00EE\u00F6\u00F1"; 46 47 static final String ASCII = 48 " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" 49 + "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; 50 51 private File testDir; 52 private File tempDir; 53 54 private final Set<File> filesToDelete = new HashSet<>(); 55 56 @Override tearDown()57 protected void tearDown() { 58 for (File file : filesToDelete) { 59 if (file.exists()) { 60 delete(file); 61 } 62 } 63 filesToDelete.clear(); 64 } 65 getTestDir()66 private File getTestDir() throws IOException { 67 if (testDir != null) { 68 return testDir; 69 } 70 71 URL testFileUrl = IoTestCase.class.getResource("testdata/i18n.txt"); 72 if (testFileUrl == null) { 73 throw new RuntimeException("unable to locate testdata directory"); 74 } 75 76 if (testFileUrl.getProtocol().equals("file")) { 77 try { 78 File testFile = new File(testFileUrl.toURI()); 79 testDir = testFile.getParentFile(); // the testdata directory 80 } catch (Exception ignore) { 81 // probably URISyntaxException or IllegalArgumentException 82 // fall back to copying URLs to files in the testDir == null block below 83 } 84 } 85 86 if (testDir == null) { 87 // testdata resources aren't file:// urls, so create a directory to store them in and then 88 // copy the resources to the filesystem as needed 89 testDir = createTempDir(); 90 } 91 92 return testDir; 93 } 94 95 /** Returns the file with the given name under the testdata directory. */ getTestFile(String name)96 protected final @Nullable File getTestFile(String name) throws IOException { 97 File file = new File(getTestDir(), name); 98 if (!file.exists()) { 99 URL resourceUrl = IoTestCase.class.getResource("testdata/" + name); 100 if (resourceUrl == null) { 101 return null; 102 } 103 copy(resourceUrl, file); 104 } 105 106 return file; 107 } 108 109 /** 110 * Creates a new temp dir for testing. The returned directory and all contents of it will be 111 * deleted in the tear-down for this test. 112 */ createTempDir()113 protected final File createTempDir() throws IOException { 114 File tempFile = File.createTempFile("IoTestCase", ""); 115 if (!tempFile.delete() || !tempFile.mkdir()) { 116 throw new IOException("failed to create temp dir"); 117 } 118 filesToDelete.add(tempFile); 119 return tempFile; 120 } 121 122 /** 123 * Gets a temp dir for testing. The returned directory and all contents of it will be deleted in 124 * the tear-down for this test. Subsequent invocations of this method will return the same 125 * directory. 126 */ getTempDir()127 protected final File getTempDir() throws IOException { 128 if (tempDir == null) { 129 tempDir = createTempDir(); 130 } 131 132 return tempDir; 133 } 134 135 /** 136 * Creates a new temp file in the temp directory returned by {@link #getTempDir()}. The file will 137 * be deleted in the tear-down for this test. 138 */ createTempFile()139 protected final File createTempFile() throws IOException { 140 return File.createTempFile("test", null, getTempDir()); 141 } 142 143 /** Returns a byte array of length size that has values 0 .. size - 1. */ newPreFilledByteArray(int size)144 static byte[] newPreFilledByteArray(int size) { 145 return newPreFilledByteArray(0, size); 146 } 147 148 /** Returns a byte array of length size that has values offset .. offset + size - 1. */ newPreFilledByteArray(int offset, int size)149 static byte[] newPreFilledByteArray(int offset, int size) { 150 byte[] array = new byte[size]; 151 for (int i = 0; i < size; i++) { 152 array[i] = (byte) (offset + i); 153 } 154 return array; 155 } 156 copy(URL url, File file)157 private static void copy(URL url, File file) throws IOException { 158 InputStream in = url.openStream(); 159 try { 160 OutputStream out = new FileOutputStream(file); 161 try { 162 byte[] buf = new byte[4096]; 163 for (int read = in.read(buf); read != -1; read = in.read(buf)) { 164 out.write(buf, 0, read); 165 } 166 } finally { 167 out.close(); 168 } 169 } finally { 170 in.close(); 171 } 172 } 173 174 @CanIgnoreReturnValue delete(File file)175 private boolean delete(File file) { 176 if (file.isDirectory()) { 177 File[] files = file.listFiles(); 178 if (files != null) { 179 for (File f : files) { 180 if (!delete(f)) { 181 return false; 182 } 183 } 184 } 185 } 186 187 if (!file.delete()) { 188 logger.log(Level.WARNING, "couldn't delete file: {0}", new Object[] {file}); 189 return false; 190 } 191 192 return true; 193 } 194 } 195