View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.io.test;
18  
19  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  import static org.junit.jupiter.api.Assertions.fail;
23  
24  import java.io.BufferedOutputStream;
25  import java.io.File;
26  import java.io.FileNotFoundException;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.OutputStream;
30  import java.io.OutputStreamWriter;
31  import java.io.PrintWriter;
32  import java.io.Reader;
33  import java.io.Writer;
34  import java.nio.charset.StandardCharsets;
35  import java.nio.file.Files;
36  import java.nio.file.Path;
37  import java.time.Duration;
38  
39  import org.apache.commons.io.FileUtils;
40  import org.apache.commons.io.output.ByteArrayOutputStream;
41  import org.apache.commons.lang3.ThreadUtils;
42  
43  /**
44   * Base class for tests doing tests with files.
45   */
46  public abstract class TestUtils {
47  
48      /**
49       * Assert that the content of a file is equal to that in a byte[].
50       *
51       * @param b0   the expected contents
52       * @param file the file to check
53       * @throws IOException If an I/O error occurs while reading the file contents
54       */
55      public static void assertEqualContent(final byte[] b0, final File file) throws IOException {
56          assertEqualContent(b0, file.toPath());
57      }
58  
59      /**
60       * Assert that the content of a file is equal to that in a byte[].
61       *
62       * @param b0   the expected contents
63       * @param file the file to check
64       * @throws IOException If an I/O error occurs while reading the file contents
65       */
66      public static void assertEqualContent(final byte[] b0, final Path file) throws IOException {
67          int count = 0;
68          int numRead = 0;
69          final byte[] b1 = new byte[b0.length];
70          try (InputStream is = Files.newInputStream(file)) {
71              while (count < b0.length && numRead >= 0) {
72                  numRead = is.read(b1, count, b0.length);
73                  count += numRead;
74              }
75              assertEquals(b0.length, count, "Different number of bytes: ");
76              for (int i = 0; i < count; i++) {
77                  assertEquals(b0[i], b1[i], "byte " + i + " differs");
78              }
79          }
80      }
81  
82      /**
83       * Assert that the content of a file is equal to that in a char[].
84       *
85       * @param c0   the expected contents
86       * @param file the file to check
87       * @throws IOException If an I/O error occurs while reading the file contents
88       */
89      public static void assertEqualContent(final char[] c0, final File file) throws IOException {
90          assertEqualContent(c0, file.toPath());
91      }
92  
93      /**
94       * Assert that the content of a file is equal to that in a char[].
95       *
96       * @param c0   the expected contents
97       * @param file the file to check
98       * @throws IOException If an I/O error occurs while reading the file contents
99       */
100     public static void assertEqualContent(final char[] c0, final Path file) throws IOException {
101         int count = 0;
102         int numRead = 0;
103         final char[] c1 = new char[c0.length];
104         try (Reader ir = Files.newBufferedReader(file)) {
105             while (count < c0.length && numRead >= 0) {
106                 numRead = ir.read(c1, count, c0.length);
107                 count += numRead;
108             }
109             assertEquals(c0.length, count, "Different number of chars: ");
110             for (int i = 0; i < count; i++) {
111                 assertEquals(c0[i], c1[i], "char " + i + " differs");
112             }
113         }
114     }
115 
116     /**
117      * Assert that the content of two files is the same.
118      */
119     private static void assertEqualContent(final File f0, final File f1)
120             throws IOException {
121         /* This doesn't work because the file size isn't updated until the file
122          * is closed.
123         assertTrue( "The files " + f0 + " and " + f1 +
124                     " have differing file sizes (" + f0.length() +
125                     " vs " + f1.length() + ")", ( f0.length() == f1.length() ) );
126         */
127         try (InputStream is0 = Files.newInputStream(f0.toPath())) {
128             try (InputStream is1 = Files.newInputStream(f1.toPath())) {
129                 final byte[] buf0 = new byte[1024];
130                 final byte[] buf1 = new byte[1024];
131                 int n0 = 0;
132                 int n1;
133 
134                 while (-1 != n0) {
135                     n0 = is0.read(buf0);
136                     n1 = is1.read(buf1);
137                     assertEquals(n0, n1,
138                             "The files " + f0 + " and " + f1 +
139                             " have differing number of bytes available (" + n0 + " vs " + n1 + ")");
140 
141                     assertArrayEquals(buf0, buf1, "The files " + f0 + " and " + f1 + " have different content");
142                 }
143             }
144         }
145     }
146 
147     public static void checkFile(final File file, final File referenceFile)
148             throws Exception {
149         assertTrue(file.exists(), "Check existence of output file");
150         assertEqualContent(referenceFile, file);
151     }
152 
153     public static void checkWrite(final OutputStream output) {
154         try {
155             new java.io.PrintStream(output).write(0);
156         } catch (final Throwable t) {
157             fail("The copy() method closed the stream when it shouldn't have. " + t.getMessage());
158         }
159     }
160 
161     public static void checkWrite(final Writer output) {
162         try {
163             new java.io.PrintWriter(output).write('a');
164         } catch (final Throwable t) {
165             fail("The copy() method closed the stream when it shouldn't have. " + t.getMessage());
166         }
167     }
168 
169     public static void createFile(final File file, final long size) throws IOException {
170         if (!file.getParentFile().exists()) {
171             throw new IOException("Cannot create file " + file + " as the parent directory does not exist");
172         }
173         try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) {
174             generateTestData(output, size);
175         }
176     }
177 
178     public static void createFile(final Path file, final long size) throws IOException {
179         if (!Files.exists(file.getParent())) {
180             throw new IOException("Cannot create file " + file + " as the parent directory does not exist");
181         }
182         try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file))) {
183             generateTestData(output, size);
184         }
185     }
186 
187     public static void createLineFileUtf8(final File file, final String[] data) throws IOException {
188         if (file.getParentFile() != null && !file.getParentFile().exists()) {
189             throw new IOException("Cannot create file " + file + " as the parent directory does not exist");
190         }
191         try (PrintWriter output = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8))) {
192             for (final String element : data) {
193                 output.println(element);
194             }
195         }
196     }
197 
198     public static void deleteFile(final File file) {
199         if (file.exists()) {
200             assertTrue(file.delete(), "Couldn't delete file: " + file);
201         }
202     }
203 
204     public static void generateTestData(final File file, final long size) throws IOException, FileNotFoundException {
205         try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) {
206             generateTestData(output, size);
207         }
208     }
209 
210     public static byte[] generateTestData(final long size) {
211         try {
212             try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) {
213                 generateTestData(baout, size);
214                 return baout.toByteArray();
215             }
216         } catch (final IOException ioe) {
217             throw new IllegalStateException("This should never happen: " + ioe.getMessage(), ioe);
218         }
219     }
220 
221     public static void generateTestData(final OutputStream out, final long size) throws IOException {
222         for (int i = 0; i < size; i++) {
223             // output.write((byte)'X');
224             // nice varied byte pattern compatible with Readers and Writers
225             out.write((byte) (i % 127 + 1));
226         }
227     }
228 
229     public static File newFile(final File testDirectory, final String fileName) throws IOException {
230         final File destination = new File(testDirectory, fileName);
231         /*
232         assertTrue(fileName + "Test output data file shouldn't previously exist",
233                     !destination.exists());
234         */
235         if (destination.exists()) {
236             FileUtils.forceDelete(destination);
237         }
238         return destination;
239     }
240 
241     /**
242      * Sleeps for a guaranteed number of milliseconds unless interrupted.
243      *
244      * This method exists because Thread.sleep(100) can sleep for 0, 70, 100 or 200ms or anything else
245      * it deems appropriate. Read the docs on Thread.sleep for further details.
246      *
247      * @param millis the number of milliseconds to sleep.
248      * @throws InterruptedException if interrupted.
249      */
250     public static void sleep(final long millis) throws InterruptedException {
251         ThreadUtils.sleep(Duration.ofMillis(millis));
252     }
253 
254     /**
255      * Sleeps and swallows InterruptedException.
256      *
257      * @param millis the number of milliseconds to sleep.
258      */
259     public static void sleepQuietly(final long millis) {
260         try {
261             sleep(millis);
262         } catch (final InterruptedException ignored) {
263             // ignore InterruptedException.
264         }
265     }
266 
267     private TestUtils() {
268 
269     }
270 
271 }