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, numRead = 0;
68          final byte[] b1 = new byte[b0.length];
69          try (InputStream is = Files.newInputStream(file)) {
70              while (count < b0.length && numRead >= 0) {
71                  numRead = is.read(b1, count, b0.length);
72                  count += numRead;
73              }
74              assertEquals(b0.length, count, "Different number of bytes: ");
75              for (int i = 0; i < count; i++) {
76                  assertEquals(b0[i], b1[i], "byte " + i + " differs");
77              }
78          }
79      }
80  
81      /**
82       * Assert that the content of a file is equal to that in a char[].
83       *
84       * @param c0   the expected contents
85       * @param file the file to check
86       * @throws IOException If an I/O error occurs while reading the file contents
87       */
88      public static void assertEqualContent(final char[] c0, final File file) throws IOException {
89          assertEqualContent(c0, file.toPath());
90      }
91  
92      /**
93       * Assert that the content of a file is equal to that in a char[].
94       *
95       * @param c0   the expected contents
96       * @param file the file to check
97       * @throws IOException If an I/O error occurs while reading the file contents
98       */
99      public static void assertEqualContent(final char[] c0, final Path file) throws IOException {
100         int count = 0, numRead = 0;
101         final char[] c1 = new char[c0.length];
102         try (Reader ir = Files.newBufferedReader(file)) {
103             while (count < c0.length && numRead >= 0) {
104                 numRead = ir.read(c1, count, c0.length);
105                 count += numRead;
106             }
107             assertEquals(c0.length, count, "Different number of chars: ");
108             for (int i = 0; i < count; i++) {
109                 assertEquals(c0[i], c1[i], "char " + i + " differs");
110             }
111         }
112     }
113 
114     /**
115      * Assert that the content of two files is the same.
116      */
117     private static void assertEqualContent(final File f0, final File f1)
118             throws IOException {
119         /* This doesn't work because the filesize isn't updated until the file
120          * is closed.
121         assertTrue( "The files " + f0 + " and " + f1 +
122                     " have differing file sizes (" + f0.length() +
123                     " vs " + f1.length() + ")", ( f0.length() == f1.length() ) );
124         */
125         try (InputStream is0 = Files.newInputStream(f0.toPath())) {
126             try (InputStream is1 = Files.newInputStream(f1.toPath())) {
127                 final byte[] buf0 = new byte[1024];
128                 final byte[] buf1 = new byte[1024];
129                 int n0 = 0;
130                 int n1;
131 
132                 while (-1 != n0) {
133                     n0 = is0.read(buf0);
134                     n1 = is1.read(buf1);
135                     assertEquals(n0, n1,
136                             "The files " + f0 + " and " + f1 +
137                             " have differing number of bytes available (" + n0 + " vs " + n1 + ")");
138 
139                     assertArrayEquals(buf0, buf1, "The files " + f0 + " and " + f1 + " have different content");
140                 }
141             }
142         }
143     }
144 
145     public static void checkFile(final File file, final File referenceFile)
146             throws Exception {
147         assertTrue(file.exists(), "Check existence of output file");
148         assertEqualContent(referenceFile, file);
149     }
150 
151     public static void checkWrite(final OutputStream output) {
152         try {
153             new java.io.PrintStream(output).write(0);
154         } catch (final Throwable t) {
155             fail("The copy() method closed the stream when it shouldn't have. " + t.getMessage());
156         }
157     }
158 
159     public static void checkWrite(final Writer output) {
160         try {
161             new java.io.PrintWriter(output).write('a');
162         } catch (final Throwable t) {
163             fail("The copy() method closed the stream when it shouldn't have. " + t.getMessage());
164         }
165     }
166 
167     public static void createFile(final File file, final long size) throws IOException {
168         if (!file.getParentFile().exists()) {
169             throw new IOException("Cannot create file " + file + " as the parent directory does not exist");
170         }
171         try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) {
172             generateTestData(output, size);
173         }
174     }
175 
176     public static void createFile(final Path file, final long size) throws IOException {
177         if (!Files.exists(file.getParent())) {
178             throw new IOException("Cannot create file " + file + " as the parent directory does not exist");
179         }
180         try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file))) {
181             generateTestData(output, size);
182         }
183     }
184 
185     public static void createLineBasedFile(final File file, final String[] data) throws IOException {
186         if (file.getParentFile() != null && !file.getParentFile().exists()) {
187             throw new IOException("Cannot create file " + file + " as the parent directory does not exist");
188         }
189         try (PrintWriter output = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8))) {
190             for (final String element : data) {
191                 output.println(element);
192             }
193         }
194     }
195 
196     public static void deleteFile(final File file) {
197         if (file.exists()) {
198             assertTrue(file.delete(), "Couldn't delete file: " + file);
199         }
200     }
201 
202     public static void generateTestData(final File file, final long size) throws IOException, FileNotFoundException {
203         try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) {
204             generateTestData(output, size);
205         }
206     }
207 
208     public static byte[] generateTestData(final long size) {
209         try {
210             try (ByteArrayOutputStream baout = new ByteArrayOutputStream()) {
211                 generateTestData(baout, size);
212                 return baout.toByteArray();
213             }
214         } catch (final IOException ioe) {
215             throw new IllegalStateException("This should never happen: " + ioe.getMessage(), ioe);
216         }
217     }
218 
219     public static void generateTestData(final OutputStream out, final long size) throws IOException {
220         for (int i = 0; i < size; i++) {
221             // output.write((byte)'X');
222             // nice varied byte pattern compatible with Readers and Writers
223             out.write((byte) (i % 127 + 1));
224         }
225     }
226 
227     public static File newFile(final File testDirectory, final String fileName) throws IOException {
228         final File destination = new File(testDirectory, fileName);
229         /*
230         assertTrue(fileName + "Test output data file shouldn't previously exist",
231                     !destination.exists());
232         */
233         if (destination.exists()) {
234             FileUtils.forceDelete(destination);
235         }
236         return destination;
237     }
238 
239     /**
240      * Sleeps for a guaranteed number of milliseconds unless interrupted.
241      *
242      * This method exists because Thread.sleep(100) can sleep for 0, 70, 100 or 200ms or anything else
243      * it deems appropriate. Read the docs on Thread.sleep for further details.
244      *
245      * @param millis the number of milliseconds to sleep.
246      * @throws InterruptedException if interrupted.
247      */
248     public static void sleep(final long millis) throws InterruptedException {
249         ThreadUtils.sleep(Duration.ofMillis(millis));
250     }
251 
252     /**
253      * Sleeps and swallows InterruptedException.
254      *
255      * @param millis the number of milliseconds to sleep.
256      */
257     public static void sleepQuietly(final long millis) {
258         try {
259             sleep(millis);
260         } catch (final InterruptedException ignored){
261             // ignore InterruptedException.
262         }
263     }
264 
265     private TestUtils() {
266 
267     }
268 
269 }