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.juneau.commons.io;
18  
19  import static org.junit.jupiter.api.Assertions.*;
20  
21  import org.apache.juneau.*;
22  import org.junit.jupiter.api.*;
23  
24  class StringBuilderWriter_Test extends TestBase {
25  
26  	//====================================================================================================
27  	// Constructor tests
28  	//====================================================================================================
29  	@Test void a01_defaultConstructor() {
30  		var sbw = new StringBuilderWriter();
31  		assertEquals("", sbw.toString());
32  		sbw.write("test");
33  		assertEquals("test", sbw.toString());
34  	}
35  
36  	@Test void a02_constructorWithInitialSize() {
37  		var sbw = new StringBuilderWriter(100);
38  		assertEquals("", sbw.toString());
39  		sbw.write("test");
40  		assertEquals("test", sbw.toString());
41  	}
42  
43  	@Test void a03_constructorWithInitialSize_negative() {
44  		assertThrows(IllegalArgumentException.class, () -> {
45  			new StringBuilderWriter(-1);
46  		});
47  	}
48  
49  	@Test void a04_constructorWithStringBuilder() {
50  		var sb = new StringBuilder("initial");
51  		var sbw = new StringBuilderWriter(sb);
52  		assertEquals("initial", sbw.toString());
53  		sbw.write("test");
54  		assertEquals("initialtest", sbw.toString());
55  		// Verify the original StringBuilder is modified
56  		assertEquals("initialtest", sb.toString());
57  	}
58  
59  	@Test void a05_constructorWithStringBuilder_null() {
60  		assertThrows(IllegalArgumentException.class, () -> {
61  			new StringBuilderWriter((StringBuilder)null);
62  		});
63  	}
64  
65  	//====================================================================================================
66  	// write(String) tests
67  	//====================================================================================================
68  	@Test void b01_writeString() {
69  		var sbw = new StringBuilderWriter();
70  		sbw.write("abc");
71  		assertEquals("abc", sbw.toString());
72  		sbw.write("def");
73  		assertEquals("abcdef", sbw.toString());
74  	}
75  
76  	@Test void b02_writeString_null() {
77  		var sbw = new StringBuilderWriter();
78  		assertThrows(IllegalArgumentException.class, () -> {
79  			sbw.write((String)null);
80  		});
81  	}
82  
83  	@Test void b03_writeString_empty() {
84  		var sbw = new StringBuilderWriter();
85  		sbw.write("");
86  		assertEquals("", sbw.toString());
87  		sbw.write("test");
88  		assertEquals("test", sbw.toString());
89  	}
90  
91  	//====================================================================================================
92  	// write(String, int, int) tests
93  	//====================================================================================================
94  	@Test void b04_writeStringWithOffset() {
95  		var sbw = new StringBuilderWriter();
96  		sbw.write("abc", 0, 3);
97  		assertEquals("abc", sbw.toString());
98  		sbw.write("def", 1, 2);
99  		assertEquals("abcef", sbw.toString());
100 	}
101 
102 	@Test void b05_writeStringWithOffset_null() {
103 		var sbw = new StringBuilderWriter();
104 		assertThrows(IllegalArgumentException.class, () -> {
105 			sbw.write((String)null, 0, 4);
106 		});
107 	}
108 
109 	@Test void b06_writeStringWithOffset_empty() {
110 		var sbw = new StringBuilderWriter();
111 		sbw.write("abc", 0, 0);
112 		assertEquals("", sbw.toString());
113 		sbw.write("abc", 1, 1);
114 		assertEquals("b", sbw.toString());
115 	}
116 
117 	@Test void b07_writeStringWithOffset_fullLength() {
118 		var sbw = new StringBuilderWriter();
119 		sbw.write("hello", 0, 5);
120 		assertEquals("hello", sbw.toString());
121 	}
122 
123 	//====================================================================================================
124 	// write(int) tests
125 	//====================================================================================================
126 	@Test void c01_writeInt() {
127 		var sbw = new StringBuilderWriter();
128 		sbw.write('a');
129 		assertEquals("a", sbw.toString());
130 		sbw.write(98); // 'b'
131 		assertEquals("ab", sbw.toString());
132 		sbw.write(0); // null character
133 		assertEquals("ab\u0000", sbw.toString());
134 	}
135 
136 	@Test void c02_writeInt_unicode() {
137 		var sbw = new StringBuilderWriter();
138 		sbw.write(0x1F600); // 😀 emoji
139 		assertEquals("\uD83D\uDE00", sbw.toString());
140 	}
141 
142 	//====================================================================================================
143 	// write(char[], int, int) tests
144 	//====================================================================================================
145 	@Test void d01_writeCharArray() {
146 		var sbw = new StringBuilderWriter();
147 		var buff = "abc".toCharArray();
148 		sbw.write(buff, 0, buff.length);
149 		assertEquals("abc", sbw.toString());
150 	}
151 
152 	@Test void d02_writeCharArray_partial() {
153 		var sbw = new StringBuilderWriter();
154 		var buff = "abcdef".toCharArray();
155 		sbw.write(buff, 1, 3);
156 		assertEquals("bcd", sbw.toString());
157 	}
158 
159 	@Test void d03_writeCharArray_empty() {
160 		var sbw = new StringBuilderWriter();
161 		var buff = "abc".toCharArray();
162 		sbw.write(buff, 0, 0);
163 		assertEquals("", sbw.toString());
164 	}
165 
166 	@Test void d04_writeCharArray_null() {
167 		var sbw = new StringBuilderWriter();
168 		assertThrows(IllegalArgumentException.class, () -> {
169 			sbw.write((char[])null, 0, 0);
170 		});
171 	}
172 
173 	@Test void d05_writeCharArray_indexOutOfBounds_negativeStart() {
174 		var sbw = new StringBuilderWriter();
175 		var buff = "abc".toCharArray();
176 		assertThrows(IndexOutOfBoundsException.class, () -> {
177 			sbw.write(buff, -1, buff.length);
178 		});
179 	}
180 
181 	@Test void d06_writeCharArray_indexOutOfBounds_startTooLarge() {
182 		var sbw = new StringBuilderWriter();
183 		var buff = "abc".toCharArray();
184 		assertThrows(IndexOutOfBoundsException.class, () -> {
185 			sbw.write(buff, buff.length + 1, 0);
186 		});
187 	}
188 
189 	@Test void d07_writeCharArray_indexOutOfBounds_lengthTooLarge() {
190 		var sbw = new StringBuilderWriter();
191 		var buff = "abc".toCharArray();
192 		assertThrows(IndexOutOfBoundsException.class, () -> {
193 			sbw.write(buff, 0, buff.length + 1);
194 		});
195 	}
196 
197 	@Test void d08_writeCharArray_indexOutOfBounds_negativeLength() {
198 		var sbw = new StringBuilderWriter();
199 		var buff = "abc".toCharArray();
200 		assertThrows(IndexOutOfBoundsException.class, () -> {
201 			sbw.write(buff, 0, -1);
202 		});
203 	}
204 
205 	@Test void d09_writeCharArray_indexOutOfBounds_startPlusLengthTooLarge() {
206 		var sbw = new StringBuilderWriter();
207 		var buff = "abc".toCharArray();
208 		assertThrows(IndexOutOfBoundsException.class, () -> {
209 			sbw.write(buff, buff.length - 1, 2);
210 		});
211 	}
212 
213 	//====================================================================================================
214 	// append(char) tests
215 	//====================================================================================================
216 	@Test void e01_appendChar() {
217 		var sbw = new StringBuilderWriter();
218 		var result = sbw.append('a');
219 		assertSame(sbw, result); // Should return this
220 		assertEquals("a", sbw.toString());
221 		sbw.append('b');
222 		assertEquals("ab", sbw.toString());
223 	}
224 
225 	@Test void e02_appendChar_unicode() {
226 		var sbw = new StringBuilderWriter();
227 		sbw.append('\u00E9'); // é
228 		assertEquals("é", sbw.toString());
229 	}
230 
231 	//====================================================================================================
232 	// append(CharSequence) tests
233 	//====================================================================================================
234 	@Test void f01_appendCharSequence() {
235 		var sbw = new StringBuilderWriter();
236 		var result = sbw.append("abc");
237 		assertSame(sbw, result); // Should return this
238 		assertEquals("abc", sbw.toString());
239 		sbw.append("def");
240 		assertEquals("abcdef", sbw.toString());
241 	}
242 
243 	@Test void f02_appendCharSequence_null() {
244 		var sbw = new StringBuilderWriter();
245 		sbw.append((CharSequence)null);
246 		assertEquals("null", sbw.toString());
247 	}
248 
249 	@Test void f03_appendCharSequence_StringBuilder() {
250 		var sbw = new StringBuilderWriter();
251 		var cs = new StringBuilder("test");
252 		sbw.append(cs);
253 		assertEquals("test", sbw.toString());
254 	}
255 
256 	@Test void f04_appendCharSequence_StringBuffer() {
257 		var sbw = new StringBuilderWriter();
258 		var cs = new StringBuffer("test");
259 		sbw.append(cs);
260 		assertEquals("test", sbw.toString());
261 	}
262 
263 	//====================================================================================================
264 	// append(CharSequence, int, int) tests
265 	//====================================================================================================
266 	@Test void g01_appendCharSequenceWithRange() {
267 		var sbw = new StringBuilderWriter();
268 		var result = sbw.append("abc", 0, 3);
269 		assertSame(sbw, result); // Should return this
270 		assertEquals("abc", sbw.toString());
271 		sbw.append("def", 1, 3);
272 		assertEquals("abcef", sbw.toString());
273 	}
274 
275 	@Test void g02_appendCharSequenceWithRange_null() {
276 		var sbw = new StringBuilderWriter();
277 		sbw.append((CharSequence)null, 0, 4);
278 		assertEquals("null", sbw.toString());
279 	}
280 
281 	@Test void g03_appendCharSequenceWithRange_empty() {
282 		var sbw = new StringBuilderWriter();
283 		sbw.append("abc", 0, 0);
284 		assertEquals("", sbw.toString());
285 		sbw.append("abc", 1, 1);
286 		assertEquals("", sbw.toString());
287 	}
288 
289 	@Test void g04_appendCharSequenceWithRange_fullLength() {
290 		var sbw = new StringBuilderWriter();
291 		sbw.append("hello", 0, 5);
292 		assertEquals("hello", sbw.toString());
293 	}
294 
295 	@Test void g05_appendCharSequenceWithRange_StringBuilder() {
296 		var sbw = new StringBuilderWriter();
297 		var cs = new StringBuilder("test");
298 		sbw.append(cs, 1, 3);
299 		assertEquals("es", sbw.toString());
300 	}
301 
302 	//====================================================================================================
303 	// flush() and close() tests
304 	//====================================================================================================
305 	@Test void h01_flush() throws Exception {
306 		var sbw = new StringBuilderWriter();
307 		sbw.write("test");
308 		sbw.flush(); // Should not throw
309 		assertEquals("test", sbw.toString());
310 		// Should be able to write after flush
311 		sbw.write("more");
312 		assertEquals("testmore", sbw.toString());
313 	}
314 
315 	@Test void h02_close() throws Exception {
316 		var sbw = new StringBuilderWriter();
317 		sbw.write("test");
318 		sbw.close(); // Should not throw
319 		assertEquals("test", sbw.toString());
320 		// Should be able to write after close
321 		sbw.write("more");
322 		assertEquals("testmore", sbw.toString());
323 	}
324 
325 	@Test void h03_flushAndClose() throws Exception {
326 		var sbw = new StringBuilderWriter();
327 		sbw.write("test");
328 		sbw.flush();
329 		sbw.close();
330 		sbw.flush(); // Should be safe to call multiple times
331 		sbw.close(); // Should be safe to call multiple times
332 		assertEquals("test", sbw.toString());
333 	}
334 
335 	//====================================================================================================
336 	// toString() tests
337 	//====================================================================================================
338 	@Test void i01_toString() {
339 		var sbw = new StringBuilderWriter();
340 		assertEquals("", sbw.toString());
341 		sbw.write("test");
342 		assertEquals("test", sbw.toString());
343 		sbw.write("more");
344 		assertEquals("testmore", sbw.toString());
345 	}
346 
347 	@Test void i02_toString_afterOperations() {
348 		var sbw = new StringBuilderWriter();
349 		sbw.write("a");
350 		sbw.append('b');
351 		sbw.append("c");
352 		sbw.append("def", 0, 2);  // Appends "de" (indices 0-1)
353 		sbw.write(new char[]{'g', 'h', 'i'}, 0, 2);  // Writes "gh" (2 chars from offset 0)
354 		assertEquals("abcdegh", sbw.toString());
355 	}
356 
357 	//====================================================================================================
358 	// Integration tests
359 	//====================================================================================================
360 	@Test void j01_combinedOperations() {
361 		var sbw = new StringBuilderWriter();
362 		sbw.write("Hello");
363 		sbw.append(' ');
364 		sbw.append("World");
365 		sbw.write("!", 0, 1);
366 		assertEquals("Hello World!", sbw.toString());
367 	}
368 
369 	@Test void j02_chaining() {
370 		var sbw = new StringBuilderWriter();
371 		sbw.append('a').append("bc").append("def", 0, 2);
372 		assertEquals("abcde", sbw.toString());
373 	}
374 
375 	@Test void j03_largeContent() {
376 		var sbw = new StringBuilderWriter(1000);
377 		for (int i = 0; i < 100; i++) {
378 			sbw.write("test");
379 		}
380 		assertEquals(400, sbw.toString().length());
381 		assertTrue(sbw.toString().startsWith("test"));
382 		assertTrue(sbw.toString().endsWith("test"));
383 	}
384 }
385