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 testIO887() throws IOException {
63 final StringWriter stringWriter1 = new StringWriter();
64 final Charset charset = StandardCharsets.UTF_8;
65 try (WriterOutputStream writerOutputStream = new WriterOutputStream(stringWriter1, charset)) {
66 writerOutputStream.write("¿Cómo estás".getBytes("Cp850"));
67 }
68 final String expected = "?C?mo est?s";
69 assertEquals(expected, stringWriter1.toString());
70 final StringWriter stringWriter2 = new StringWriter();
71 try (WriterOutputStream writerOutputStream = WriterOutputStream.builder().setWriter(stringWriter2).setCharset(charset).get()) {
72 writerOutputStream.write("¿Cómo estás".getBytes("Cp850"));
73 }
74 assertEquals(expected, stringWriter2.toString());
75 }
76
77 @Test
78 void testLargeUTF8CharsetWithBufferedWrite() throws IOException {
79 testWithBufferedWrite(LARGE_TEST_STRING, UTF_8);
80 }
81
82 @Test
83 void testLargeUTF8CharsetWithSingleByteWrite() throws IOException {
84 testWithSingleByteWrite(LARGE_TEST_STRING, StandardCharsets.UTF_8);
85 }
86
87 @Test
88 void testLargeUTF8WithBufferedWrite() throws IOException {
89 testWithBufferedWrite(LARGE_TEST_STRING, UTF_8);
90 }
91
92 @Test
93 void testLargeUTF8WithSingleByteWrite() throws IOException {
94 testWithSingleByteWrite(LARGE_TEST_STRING, UTF_8);
95 }
96
97 @Test
98 void testNullCharsetDecoderWithSingleByteWrite() throws IOException {
99 testWithSingleByteWrite(TEST_STRING, (CharsetDecoder) null);
100 }
101
102 @Test
103 void testNullCharsetNameWithSingleByteWrite() throws IOException {
104 testWithSingleByteWrite(TEST_STRING, (String) null);
105 }
106
107 @Test
108 void testNullCharsetWithSingleByteWrite() throws IOException {
109 testWithSingleByteWrite(TEST_STRING, (Charset) null);
110 }
111
112 @Test
113 void testUTF16BEWithBufferedWrite() throws IOException {
114 testWithBufferedWrite(TEST_STRING, UTF_16BE);
115 }
116
117 @Test
118 void testUTF16BEWithSingleByteWrite() throws IOException {
119 testWithSingleByteWrite(TEST_STRING, UTF_16BE);
120 }
121
122 @Test
123 void testUTF16LEWithBufferedWrite() throws IOException {
124 testWithBufferedWrite(TEST_STRING, UTF_16LE);
125 }
126
127 @Test
128 void testUTF16LEWithSingleByteWrite() throws IOException {
129 testWithSingleByteWrite(TEST_STRING, UTF_16LE);
130 }
131
132 @Test
133 void testUTF16WithBufferedWrite() throws IOException {
134 try {
135 testWithBufferedWrite(TEST_STRING, UTF_16);
136 } catch (final UnsupportedOperationException e) {
137 if (!SystemProperties.getJavaVendor().contains("IBM")) {
138 fail("This test should only throw UOE on IBM JDKs with broken UTF-16");
139 }
140 }
141 }
142
143 @Test
144 void testUTF16WithSingleByteWrite() throws IOException {
145 try {
146 testWithSingleByteWrite(TEST_STRING, UTF_16);
147 } catch (final UnsupportedOperationException e) {
148 if (!SystemProperties.getJavaVendor().contains("IBM")) {
149 fail("This test should only throw UOE on IBM JDKs with broken UTF-16");
150 }
151 }
152 }
153
154 @Test
155 void testUTF8WithBufferedWrite() throws IOException {
156 testWithBufferedWrite(TEST_STRING, UTF_8);
157 }
158
159 @Test
160 void testUTF8WithSingleByteWrite() throws IOException {
161 testWithSingleByteWrite(TEST_STRING, UTF_8);
162 }
163
164 private void testWithBufferedWrite(final String testString, final String charsetName) throws IOException {
165 final byte[] expected = testString.getBytes(charsetName);
166 final StringWriter writer = new StringWriter();
167 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charsetName).get()) {
168 int offset = 0;
169 while (offset < expected.length) {
170 final int length = Math.min(random.nextInt(128), expected.length - offset);
171 out.write(expected, offset, length);
172 offset += length;
173 }
174 }
175 assertEquals(testString, writer.toString());
176 }
177
178 private void testWithSingleByteWrite(final String testString, final Charset charset) throws IOException {
179 final byte[] bytes = testString.getBytes(Charsets.toCharset(charset));
180 StringWriter writer = new StringWriter();
181 try (WriterOutputStream out = new WriterOutputStream(writer, charset)) {
182 writeOneAtATime(bytes, out);
183 }
184 assertEquals(testString, writer.toString());
185
186 writer = new StringWriter();
187 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charset).get()) {
188 writeOneAtATime(bytes, out);
189 }
190 assertEquals(testString, writer.toString());
191 }
192
193 private void testWithSingleByteWrite(final String testString, final CharsetDecoder charsetDecoder) throws IOException {
194 final byte[] bytes = testString.getBytes(CharsetDecoders.toCharsetDecoder(charsetDecoder).charset());
195 StringWriter writer = new StringWriter();
196 try (WriterOutputStream out = new WriterOutputStream(writer, charsetDecoder)) {
197 writeOneAtATime(bytes, out);
198 }
199 assertEquals(testString, writer.toString());
200
201 writer = new StringWriter();
202 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharsetDecoder(charsetDecoder).get()) {
203 writeOneAtATime(bytes, out);
204 }
205 assertEquals(testString, writer.toString());
206 }
207
208 private void testWithSingleByteWrite(final String testString, final String charsetName) throws IOException {
209 final byte[] bytes = testString.getBytes(Charsets.toCharset(charsetName));
210 StringWriter writer = new StringWriter();
211 try (WriterOutputStream out = new WriterOutputStream(writer, charsetName)) {
212 writeOneAtATime(bytes, out);
213 }
214 assertEquals(testString, writer.toString());
215
216 writer = new StringWriter();
217 try (WriterOutputStream out = WriterOutputStream.builder().setWriter(writer).setCharset(charsetName).get()) {
218 writeOneAtATime(bytes, out);
219 }
220 assertEquals(testString, writer.toString());
221 }
222
223 @Test
224 void testWriteImmediately() throws IOException {
225 final StringWriter writer = new StringWriter();
226 try (WriterOutputStream out = new WriterOutputStream(writer, "us-ascii", 1024, true)) {
227 out.write("abc".getBytes(StandardCharsets.US_ASCII));
228 assertEquals("abc", writer.toString());
229 }
230
231 try (WriterOutputStream out = WriterOutputStream.builder()
232 .setWriter(writer)
233 .setCharset("us-ascii")
234 .setBufferSize(1024)
235 .setWriteImmediately(true)
236 .setOpenOptions(StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)
237 .get()) {
238
239 out.write("abc".getBytes(StandardCharsets.US_ASCII));
240 assertEquals("abcabc", writer.toString());
241 }
242 }
243
244 private void writeOneAtATime(final byte[] bytes, final WriterOutputStream out) throws IOException {
245 for (final byte b : bytes) {
246 out.write(b);
247 }
248 }
249 }