1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io.output;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.fail;
21
22 import java.io.IOException;
23 import java.io.StringWriter;
24 import java.nio.charset.Charset;
25 import java.nio.charset.CharsetDecoder;
26 import java.nio.charset.StandardCharsets;
27 import java.nio.file.StandardOpenOption;
28 import java.util.Random;
29
30 import org.apache.commons.io.Charsets;
31 import org.apache.commons.io.charset.CharsetDecoders;
32 import org.apache.commons.lang3.StringUtils;
33 import org.apache.commons.lang3.SystemProperties;
34 import org.junit.jupiter.api.Test;
35
36
37
38
39 class WriterOutputStreamTest {
40
41 private static final String UTF_16LE = StandardCharsets.UTF_16LE.name();
42 private static final String UTF_16BE = StandardCharsets.UTF_16BE.name();
43 private static final String UTF_16 = StandardCharsets.UTF_16.name();
44 private static final String UTF_8 = StandardCharsets.UTF_8.name();
45 private static final String TEST_STRING = "\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre";
46 private static final String LARGE_TEST_STRING = StringUtils.repeat(TEST_STRING, 100);
47
48 private final Random random = new Random();
49
50 @Test
51 void testFlush() throws IOException {
52 final StringWriter writer = new StringWriter();
53 try (WriterOutputStream out = new WriterOutputStream(writer, "us-ascii", 1024, false)) {
54 out.write("abc".getBytes(StandardCharsets.US_ASCII));
55 assertEquals(0, writer.getBuffer().length());
56 out.flush();
57 assertEquals("abc", writer.toString());
58 }
59 }
60
61 @Test
62 void testLargeUTF8CharsetWithBufferedWrite() throws IOException {
63 testWithBufferedWrite(LARGE_TEST_STRING, UTF_8);
64 }
65
66 @Test
67 void testLargeUTF8CharsetWithSingleByteWrite() throws IOException {
68 testWithSingleByteWrite(LARGE_TEST_STRING, StandardCharsets.UTF_8);
69 }
70
71 @Test
72 void testLargeUTF8WithBufferedWrite() throws IOException {
73 testWithBufferedWrite(LARGE_TEST_STRING, UTF_8);
74 }
75
76 @Test
77 void testLargeUTF8WithSingleByteWrite() throws IOException {
78 testWithSingleByteWrite(LARGE_TEST_STRING, UTF_8);
79 }
80
81 @Test
82 void testNullCharsetDecoderWithSingleByteWrite() throws IOException {
83 testWithSingleByteWrite(TEST_STRING, (CharsetDecoder) null);
84 }
85
86 @Test
87 void testNullCharsetNameWithSingleByteWrite() throws IOException {
88 testWithSingleByteWrite(TEST_STRING, (String) null);
89 }
90
91 @Test
92 void testNullCharsetWithSingleByteWrite() throws IOException {
93 testWithSingleByteWrite(TEST_STRING, (Charset) null);
94 }
95
96 @Test
97 void testUTF16BEWithBufferedWrite() throws IOException {
98 testWithBufferedWrite(TEST_STRING, UTF_16BE);
99 }
100
101 @Test
102 void testUTF16BEWithSingleByteWrite() throws IOException {
103 testWithSingleByteWrite(TEST_STRING, UTF_16BE);
104 }
105
106 @Test
107 void testUTF16LEWithBufferedWrite() throws IOException {
108 testWithBufferedWrite(TEST_STRING, UTF_16LE);
109 }
110
111 @Test
112 void testUTF16LEWithSingleByteWrite() throws IOException {
113 testWithSingleByteWrite(TEST_STRING, UTF_16LE);
114 }
115
116 @Test
117 void testUTF16WithBufferedWrite() throws IOException {
118 try {
119 testWithBufferedWrite(TEST_STRING, UTF_16);
120 } catch (final UnsupportedOperationException e) {
121 if (!SystemProperties.getJavaVendor().contains("IBM")) {
122 fail("This test should only throw UOE on IBM JDKs with broken UTF-16");
123 }
124 }
125 }
126
127 @Test
128 void testUTF16WithSingleByteWrite() throws IOException {
129 try {
130 testWithSingleByteWrite(TEST_STRING, UTF_16);
131 } catch (final UnsupportedOperationException e) {
132 if (!SystemProperties.getJavaVendor().contains("IBM")) {
133 fail("This test should only throw UOE on IBM JDKs with broken UTF-16");
134 }
135 }
136 }
137
138 @Test
139 void testUTF8WithBufferedWrite() throws IOException {
140 testWithBufferedWrite(TEST_STRING, UTF_8);
141 }
142
143 @Test
144 void testUTF8WithSingleByteWrite() throws IOException {
145 testWithSingleByteWrite(TEST_STRING, UTF_8);
146 }
147
148 private void testWithBufferedWrite(final String testString, final String charsetName) throws IOException {
149 final byte[] expected = testString.getBytes(charsetName);
150 final StringWriter writer = new StringWriter();
151 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charsetName).get()) {
152 int offset = 0;
153 while (offset < expected.length) {
154 final int length = Math.min(random.nextInt(128), expected.length - offset);
155 out.write(expected, offset, length);
156 offset += length;
157 }
158 }
159 assertEquals(testString, writer.toString());
160 }
161
162 private void testWithSingleByteWrite(final String testString, final Charset charset) throws IOException {
163 final byte[] bytes = testString.getBytes(Charsets.toCharset(charset));
164 StringWriter writer = new StringWriter();
165 try (WriterOutputStream out = new WriterOutputStream(writer, charset)) {
166 writeOneAtATime(bytes, out);
167 }
168 assertEquals(testString, writer.toString());
169
170 writer = new StringWriter();
171 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charset).get()) {
172 writeOneAtATime(bytes, out);
173 }
174 assertEquals(testString, writer.toString());
175 }
176
177 private void testWithSingleByteWrite(final String testString, final CharsetDecoder charsetDecoder) throws IOException {
178 final byte[] bytes = testString.getBytes(CharsetDecoders.toCharsetDecoder(charsetDecoder).charset());
179 StringWriter writer = new StringWriter();
180 try (WriterOutputStream out = new WriterOutputStream(writer, charsetDecoder)) {
181 writeOneAtATime(bytes, out);
182 }
183 assertEquals(testString, writer.toString());
184
185 writer = new StringWriter();
186 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharsetDecoder(charsetDecoder).get()) {
187 writeOneAtATime(bytes, out);
188 }
189 assertEquals(testString, writer.toString());
190 }
191
192 private void testWithSingleByteWrite(final String testString, final String charsetName) throws IOException {
193 final byte[] bytes = testString.getBytes(Charsets.toCharset(charsetName));
194 StringWriter writer = new StringWriter();
195 try (WriterOutputStream out = new WriterOutputStream(writer, charsetName)) {
196 writeOneAtATime(bytes, out);
197 }
198 assertEquals(testString, writer.toString());
199
200 writer = new StringWriter();
201 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charsetName).get()) {
202 writeOneAtATime(bytes, out);
203 }
204 assertEquals(testString, writer.toString());
205 }
206
207 @Test
208 void testWriteImmediately() throws IOException {
209 final StringWriter writer = new StringWriter();
210 try (WriterOutputStream out = new WriterOutputStream(writer, "us-ascii", 1024, true)) {
211 out.write("abc".getBytes(StandardCharsets.US_ASCII));
212 assertEquals("abc", writer.toString());
213 }
214
215 try (WriterOutputStream out = WriterOutputStream.builder()
216 .setWriter(writer)
217 .setCharset("us-ascii")
218 .setBufferSize(1024)
219 .setWriteImmediately(true)
220 .setOpenOptions(StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)
221 .get()) {
222
223 out.write("abc".getBytes(StandardCharsets.US_ASCII));
224 assertEquals("abcabc", writer.toString());
225 }
226 }
227
228 private void writeOneAtATime(final byte[] bytes, final WriterOutputStream out) throws IOException {
229 for (final byte b : bytes) {
230 out.write(b);
231 }
232 }
233 }