1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.output;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
23 import static org.junit.jupiter.api.Assertions.assertThrows;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25
26 import java.io.IOException;
27 import java.io.OutputStream;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 import java.util.concurrent.atomic.AtomicInteger;
30
31 import org.junit.jupiter.api.Test;
32
33
34
35
36
37
38 class ThresholdingOutputStreamTest {
39
40
41
42
43
44
45
46
47 static void assertThresholdingInitialState(final ThresholdingOutputStream out, final int expectedThreshold, final int expectedByeCount) {
48 assertFalse(out.isThresholdExceeded());
49 assertEquals(expectedThreshold, out.getThreshold());
50 assertEquals(expectedByeCount, out.getByteCount());
51 }
52
53 @Test
54 void testResetByteCount() throws IOException {
55 final int threshold = 1;
56 final AtomicInteger counter = new AtomicInteger();
57 try (ByteArrayOutputStream os = new ByteArrayOutputStream(); ThresholdingOutputStream out = new ThresholdingOutputStream(threshold, tos -> {
58 counter.incrementAndGet();
59 tos.resetByteCount();
60 }, o -> os)) {
61 assertThresholdingInitialState(out, threshold, 0);
62 assertEquals(0, counter.get());
63 out.write('a');
64 assertFalse(out.isThresholdExceeded());
65 out.write('a');
66 assertEquals(1, counter.get());
67 assertFalse(out.isThresholdExceeded());
68 out.write('a');
69 out.write('a');
70 assertEquals(3, counter.get());
71 }
72 }
73
74 @Test
75 void testResetByteCountBrokenOutputStream() throws IOException {
76 final int threshold = 1;
77 final AtomicInteger counter = new AtomicInteger();
78 final IOException e = assertThrows(IOException.class, () -> {
79 try (ByteArrayOutputStream os = new ByteArrayOutputStream(); ThresholdingOutputStream out = new ThresholdingOutputStream(threshold, tos -> {
80 counter.incrementAndGet();
81 tos.resetByteCount();
82 }, o -> BrokenOutputStream.INSTANCE)) {
83 assertThresholdingInitialState(out, threshold, 0);
84 assertEquals(0, counter.get());
85 assertThrows(IOException.class, () -> out.write('a'));
86 assertFalse(out.isThresholdExceeded());
87 assertThrows(IOException.class, () -> out.write('a'));
88 assertEquals(0, counter.get());
89 assertFalse(out.isThresholdExceeded());
90 assertThrows(IOException.class, () -> out.write('a'));
91 assertThrows(IOException.class, () -> out.write('a'));
92 assertEquals(0, counter.get());
93 }
94 });
95
96 assertEquals("Broken output stream: close()", e.getMessage());
97 }
98
99 @Test
100 void testSetByteCountOutputStream() throws IOException {
101 final AtomicBoolean reached = new AtomicBoolean();
102 final int initCount = 2;
103 final int threshold = 3;
104 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold) {
105 {
106 setByteCount(initCount);
107 }
108
109 @Override
110 protected OutputStream getOutputStream() throws IOException {
111 return new ByteArrayOutputStream(4);
112 }
113
114 @Override
115 protected void thresholdReached() throws IOException {
116 reached.set(true);
117 }
118 }) {
119 assertThresholdingInitialState(out, threshold, initCount);
120 out.write('a');
121 assertFalse(reached.get());
122 assertFalse(out.isThresholdExceeded());
123 out.write('a');
124 assertTrue(reached.get());
125 assertTrue(out.isThresholdExceeded());
126 }
127 }
128
129 @Test
130 void testSetByteCountStream() throws IOException {
131 final AtomicBoolean reached = new AtomicBoolean();
132 final int initCount = 2;
133 final int threshold = 3;
134 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold) {
135 {
136 setByteCount(initCount);
137 }
138
139 @Override
140 protected OutputStream getStream() throws IOException {
141 return new ByteArrayOutputStream(4);
142 }
143
144 @Override
145 protected void thresholdReached() throws IOException {
146 reached.set(true);
147 }
148 }) {
149 assertThresholdingInitialState(out, threshold, initCount);
150 out.write('a');
151 assertFalse(reached.get());
152 assertFalse(out.isThresholdExceeded());
153 out.write('a');
154 assertTrue(reached.get());
155 assertTrue(out.isThresholdExceeded());
156 }
157 }
158
159 @Test
160 void testThresholdIOConsumer() throws IOException {
161 final int threshold = 1;
162
163 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold, null,
164 os -> new ByteArrayOutputStream(4))) {
165 assertThresholdingInitialState(out, threshold, 0);
166 out.write('a');
167 assertFalse(out.isThresholdExceeded());
168 out.write('a');
169 assertTrue(out.isThresholdExceeded());
170 }
171
172 final AtomicBoolean reached = new AtomicBoolean();
173 reached.set(false);
174 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold, os -> reached.set(true), null)) {
175 assertThresholdingInitialState(out, threshold, 0);
176 out.write('a');
177 assertFalse(reached.get());
178 assertFalse(out.isThresholdExceeded());
179 out.write('a');
180 assertTrue(reached.get());
181 assertTrue(out.isThresholdExceeded());
182 }
183
184 reached.set(false);
185 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold, os -> reached.set(true),
186 os -> new ByteArrayOutputStream(4))) {
187 assertThresholdingInitialState(out, threshold, 0);
188 out.write('a');
189 assertFalse(reached.get());
190 assertFalse(out.isThresholdExceeded());
191 out.write('a');
192 assertTrue(reached.get());
193 assertTrue(out.isThresholdExceeded());
194 }
195 }
196
197 @Test
198 void testThresholdIOConsumerIOException() throws IOException {
199 final int threshold = 1;
200 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold, os -> {
201 throw new IOException("Threshold reached.");
202 }, os -> new ByteArrayOutputStream(4))) {
203 assertThresholdingInitialState(out, threshold, 0);
204 out.write('a');
205 assertFalse(out.isThresholdExceeded());
206 assertThrows(IOException.class, () -> out.write('a'));
207 assertFalse(out.isThresholdExceeded());
208 }
209 }
210
211 @Test
212 void testThresholdIOConsumerUncheckedException() throws IOException {
213 final int threshold = 1;
214 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold, os -> {
215 throw new IllegalStateException("Threshold reached.");
216 }, os -> new ByteArrayOutputStream(4))) {
217 assertThresholdingInitialState(out, threshold, 0);
218 out.write('a');
219 assertFalse(out.isThresholdExceeded());
220 assertThrows(IllegalStateException.class, () -> out.write('a'));
221 assertFalse(out.isThresholdExceeded());
222 assertInstanceOf(ByteArrayOutputStream.class, out.getOutputStream());
223 assertFalse(out.isThresholdExceeded());
224 }
225 }
226
227
228
229
230
231 @Test
232 void testThresholdLessThanZero() throws IOException {
233 final AtomicBoolean reached = new AtomicBoolean();
234 try (ThresholdingOutputStream out = new ThresholdingOutputStream(-1) {
235 @Override
236 protected void thresholdReached() throws IOException {
237 reached.set(true);
238 }
239 }) {
240 assertThresholdingInitialState(out, 0, 0);
241 assertFalse(reached.get());
242 out.write(89);
243 assertTrue(reached.get());
244 assertTrue(out.isThresholdExceeded());
245 assertInstanceOf(NullOutputStream.class, out.getOutputStream());
246 assertTrue(out.isThresholdExceeded());
247 }
248 }
249
250 @Test
251 void testThresholdZero() throws IOException {
252 final AtomicBoolean reached = new AtomicBoolean();
253 final int threshold = 0;
254 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold) {
255 @Override
256 protected void thresholdReached() throws IOException {
257 reached.set(true);
258 }
259 }) {
260 assertThresholdingInitialState(out, threshold, 0);
261 out.write(89);
262 assertTrue(reached.get());
263 assertTrue(out.isThresholdExceeded());
264 assertInstanceOf(NullOutputStream.class, out.getOutputStream());
265 assertTrue(out.isThresholdExceeded());
266 }
267 }
268
269
270
271
272
273 @Test
274 void testThresholdZeroWrite() throws IOException {
275 final AtomicBoolean reached = new AtomicBoolean();
276 final int threshold = 7;
277 try (ThresholdingOutputStream out = new ThresholdingOutputStream(threshold) {
278 @Override
279 protected void thresholdReached() throws IOException {
280 super.thresholdReached();
281 reached.set(true);
282 }
283 }) {
284 assertThresholdingInitialState(out, threshold, 0);
285 assertFalse(reached.get());
286 out.write(new byte[0]);
287 assertFalse(out.isThresholdExceeded());
288 assertFalse(reached.get());
289 assertInstanceOf(NullOutputStream.class, out.getOutputStream());
290 assertFalse(out.isThresholdExceeded());
291 }
292 }
293 }