• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 static com.google.common.base.StandardSystemProperty.JAVA_IO_TMPDIR;
20 import static com.google.common.base.StandardSystemProperty.OS_NAME;
21 import static com.google.common.truth.Truth.assertThat;
22 import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
23 import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
24 import static org.junit.Assert.assertThrows;
25 
26 import java.io.File;
27 import java.io.IOException;
28 import java.io.OutputStream;
29 import java.nio.file.attribute.PosixFileAttributeView;
30 import java.nio.file.attribute.PosixFileAttributes;
31 import java.util.Arrays;
32 
33 /**
34  * Unit tests for {@link FileBackedOutputStream}.
35  *
36  * <p>For a tiny bit more testing, see {@link FileBackedOutputStreamAndroidIncompatibleTest}.
37  *
38  * @author Chris Nokleberg
39  */
40 public class FileBackedOutputStreamTest extends IoTestCase {
41 
42 
testThreshold()43   public void testThreshold() throws Exception {
44     testThreshold(0, 100, true, false);
45     testThreshold(10, 100, true, false);
46     testThreshold(100, 100, true, false);
47     testThreshold(1000, 100, true, false);
48     testThreshold(0, 100, false, false);
49     testThreshold(10, 100, false, false);
50     testThreshold(100, 100, false, false);
51     testThreshold(1000, 100, false, false);
52   }
53 
testThreshold( int fileThreshold, int dataSize, boolean singleByte, boolean resetOnFinalize)54   private void testThreshold(
55       int fileThreshold, int dataSize, boolean singleByte, boolean resetOnFinalize)
56       throws IOException {
57     byte[] data = newPreFilledByteArray(dataSize);
58     FileBackedOutputStream out = new FileBackedOutputStream(fileThreshold, resetOnFinalize);
59     ByteSource source = out.asByteSource();
60     int chunk1 = Math.min(dataSize, fileThreshold);
61     int chunk2 = dataSize - chunk1;
62 
63     // Write just enough to not trip the threshold
64     if (chunk1 > 0) {
65       write(out, data, 0, chunk1, singleByte);
66       assertTrue(ByteSource.wrap(data).slice(0, chunk1).contentEquals(source));
67     }
68     File file = out.getFile();
69     assertNull(file);
70 
71     // Write data to go over the threshold
72     if (chunk2 > 0) {
73       if (JAVA_IO_TMPDIR.value().equals("/sdcard")) {
74         assertThrows(IOException.class, () -> write(out, data, chunk1, chunk2, singleByte));
75         return;
76       }
77       write(out, data, chunk1, chunk2, singleByte);
78       file = out.getFile();
79       assertEquals(dataSize, file.length());
80       assertTrue(file.exists());
81       assertThat(file.getName()).contains("FileBackedOutputStream");
82       if (!isAndroid() && !isWindows()) {
83         PosixFileAttributes attributes =
84             java.nio.file.Files.getFileAttributeView(file.toPath(), PosixFileAttributeView.class)
85                 .readAttributes();
86         assertThat(attributes.permissions()).containsExactly(OWNER_READ, OWNER_WRITE);
87       }
88     }
89     out.close();
90 
91     // Check that source returns the right data
92     assertTrue(Arrays.equals(data, source.read()));
93 
94     // Make sure that reset deleted the file
95     out.reset();
96     if (file != null) {
97       assertFalse(file.exists());
98     }
99   }
100 
101 
testThreshold_resetOnFinalize()102   public void testThreshold_resetOnFinalize() throws Exception {
103     testThreshold(0, 100, true, true);
104     testThreshold(10, 100, true, true);
105     testThreshold(100, 100, true, true);
106     testThreshold(1000, 100, true, true);
107     testThreshold(0, 100, false, true);
108     testThreshold(10, 100, false, true);
109     testThreshold(100, 100, false, true);
110     testThreshold(1000, 100, false, true);
111   }
112 
write(OutputStream out, byte[] b, int off, int len, boolean singleByte)113   static void write(OutputStream out, byte[] b, int off, int len, boolean singleByte)
114       throws IOException {
115     if (singleByte) {
116       for (int i = off; i < off + len; i++) {
117         out.write(b[i]);
118       }
119     } else {
120       out.write(b, off, len);
121     }
122     out.flush(); // for coverage
123   }
124 
125   // TODO(chrisn): only works if we ensure we have crossed file threshold
126 
testWriteErrorAfterClose()127   public void testWriteErrorAfterClose() throws Exception {
128     byte[] data = newPreFilledByteArray(100);
129     FileBackedOutputStream out = new FileBackedOutputStream(50);
130     ByteSource source = out.asByteSource();
131 
132     if (JAVA_IO_TMPDIR.value().equals("/sdcard")) {
133       assertThrows(IOException.class, () -> out.write(data));
134       return;
135     }
136     out.write(data);
137     assertTrue(Arrays.equals(data, source.read()));
138 
139     out.close();
140     assertThrows(IOException.class, () -> out.write(42));
141 
142     // Verify that write had no effect
143     assertTrue(Arrays.equals(data, source.read()));
144     out.reset();
145   }
146 
testReset()147   public void testReset() throws Exception {
148     byte[] data = newPreFilledByteArray(100);
149     FileBackedOutputStream out = new FileBackedOutputStream(Integer.MAX_VALUE);
150     ByteSource source = out.asByteSource();
151 
152     out.write(data);
153     assertTrue(Arrays.equals(data, source.read()));
154 
155     out.reset();
156     assertTrue(Arrays.equals(new byte[0], source.read()));
157 
158     out.write(data);
159     assertTrue(Arrays.equals(data, source.read()));
160 
161     out.close();
162   }
163 
isAndroid()164   private static boolean isAndroid() {
165     return System.getProperty("java.runtime.name", "").contains("Android");
166   }
167 
isWindows()168   private static boolean isWindows() {
169     return OS_NAME.value().startsWith("Windows");
170   }
171 }
172