1 /*
2  * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /* @test
25  * @bug 5067405
26  * @summary Basic test for classes which implement Appendable.
27  */
28 
29 import java.io.BufferedReader;
30 import java.io.BufferedWriter;
31 import java.io.ByteArrayOutputStream;
32 import java.io.CharArrayWriter;
33 import java.io.File;
34 import java.io.FileReader;
35 import java.io.FileWriter;
36 import java.io.IOException;
37 import java.io.OutputStreamWriter;
38 import java.io.PrintStream;
39 import java.io.PrintWriter;
40 import java.io.StringWriter;
41 import java.io.Writer;
42 import java.nio.ByteBuffer;
43 import java.nio.CharBuffer;
44 
45 interface BasicRunnable extends Runnable {
init(Appendable a, String csq, String exp)46     void init(Appendable a, String csq, String exp);
reset(Appendable csq)47     Appendable reset(Appendable csq);
48 }
49 
50 public class Basic {
51 
52     private static final String s = "Beware the Jabberwock, my son!";
53     private static CharArrayWriter gw = new CharArrayWriter();
54     private static ByteArrayOutputStream gos = new ByteArrayOutputStream();
55 
newFile()56     private static File newFile() {
57         File f = null;
58         try {
59             f = File.createTempFile("append", ".txt");
60             f.deleteOnExit();
61         } catch (IOException x) {
62             fail(x);
63         }
64         return f;
65     }
66     private static File gf = newFile();
67 
68     private static int fail = 0;
69     private static int pass = 0;
70 
71     private static Throwable first;
72 
pass()73     static void pass() {
74         pass++;
75     }
76 
fail(Throwable ex)77     static void fail(Throwable ex) {
78         if (first == null)
79             first = ex;
80         System.err.println("FAILED: unexpected exception");
81         fail++;
82     }
83 
fail(String fs, Throwable ex)84     static void fail(String fs, Throwable ex) {
85         String s = "'" + fs + "': " + ex.getClass().getName() + " not thrown";
86         if (first == null)
87             first = ex;
88         System.err.println("FAILED: " + s);
89         fail++;
90     }
91 
fail(String fs, String exp, String got)92     static void fail(String fs, String exp, String got) {
93         String s = "'" + fs + "': Expected '" + exp + "', got '" + got + "'";
94         if (first == null)
95             first = new RuntimeException(s);
96         System.err.println("FAILED: " + s);
97         fail++;
98     }
99 
ck(String s, String exp, String got)100     static void ck(String s, String exp, String got) {
101         if (!exp.equals(got))
102             fail(s, exp, got);
103         else
104             pass();
105     }
106 
107     private static BasicRunnable testBufferedWriter =
108         new BasicRunnable() {
109             private String csn, exp;
110             public void init(Appendable bw, String csn, String exp) {
111                 try {
112                     ((BufferedWriter)bw).flush();
113                 } catch (IOException x) {
114                     fail(x);
115                 }
116                 this.csn = csn;
117                 this.exp = exp;
118             }
119             public void run() {
120                 ck("BufferedWriter.append(" + csn + ")", exp, gw.toString());
121             }
122             public Appendable reset(Appendable bw) {
123                 gw.reset();
124                 return bw;
125             }};
126 
127     private static BasicRunnable testCharArrayWriter =
128         new BasicRunnable() {
129             private String csn, exp;
130             private CharArrayWriter cw;
131             public void init(Appendable cw, String csn, String exp) {
132                 this.cw = (CharArrayWriter)cw;
133                 this.csn = csn;
134                 this.exp = exp;
135             }
136             public void run() {
137                 ck("CharArrayWriter.append(" + csn + ")", exp, cw.toString());
138             }
139             public Appendable reset(Appendable cw) {
140                 ((CharArrayWriter)cw).reset();
141                 return cw;
142             }};
143 
144     private static BasicRunnable testFileWriter =
145         new BasicRunnable() {
146             private String csn, exp;
147             public void init(Appendable fw, String csn, String exp) {
148                 try {
149                     ((FileWriter)fw).flush();
150                 } catch (IOException x) {
151                     fail(x);
152                 }
153                 this.csn = csn;
154                 this.exp = exp;
155             }
156             public void run() {
157                 StringBuilder sb = new StringBuilder();
158                 try {
159                     BufferedReader in = new BufferedReader(new FileReader(gf));
160                     String line;
161                     while (true) {
162                         if ((line = in.readLine()) == null)
163                             break;
164                         sb.append(line);
165                     }
166                 } catch (IOException x) {
167                     fail(x);
168                 }
169                 ck("FileWriter.append(" + csn + ")", exp, sb.toString());
170             }
171             public Appendable reset(Appendable fw) {
172                 try {
173                     fw = new FileWriter(gf);
174                 } catch (IOException x) {
175                     fail(x);
176                 }
177                 return fw;
178             }};
179 
180     private static BasicRunnable testOutputStreamWriter =
181         new BasicRunnable() {
182             private String csn, exp;
183             public void init(Appendable osw, String csn, String exp) {
184                 try {
185                     ((OutputStreamWriter)osw).flush();
186                 } catch (IOException x) {
187                     fail(x);
188                 }
189                 this.csn = csn;
190                 this.exp = exp;
191             }
192             public void run() {
193                 ck("OutputStreamWriter.append(" + csn + ")", exp, gos.toString());
194             }
195             public Appendable reset(Appendable osw) {
196                 gos.reset();
197                 return osw;
198             }};
199 
200     private static BasicRunnable testPrintWriter =
201         new BasicRunnable() {
202             private String csn, exp;
203             public void init(Appendable pw, String csn, String exp) {
204                 ((PrintWriter)pw).flush();
205                 this.csn = csn;
206                 this.exp = exp;
207             }
208             public void run() {
209                 ck("PrintWriter.append(" + csn + ")", exp, gw.toString());
210             }
211             public Appendable reset(Appendable pw) {
212                 gw.reset();
213                 return pw;
214             }};
215 
216     private static BasicRunnable testStringWriter =
217         new BasicRunnable() {
218             private String csn, exp;
219             private StringWriter sw;
220             public void init(Appendable sw, String csn, String exp) {
221                 this.sw = (StringWriter)sw;
222                 this.csn = csn;
223                 this.exp = exp;
224             }
225             public void run() {
226                 ck("StringWriter.append(" + csn + ")", exp, sw.toString());
227             }
228             public Appendable reset(Appendable sw) {
229                 return new StringWriter();
230             }};
231 
232     private static BasicRunnable testPrintStream =
233         new BasicRunnable() {
234             private String csn, exp;
235             public void init(Appendable ps, String csn, String exp) {
236                 ((PrintStream)ps).flush();
237                 this.csn = csn;
238                 this.exp = exp;
239             }
240             public void run() {
241                 ck("PrintStream.append(" + csn + ")", exp, gos.toString());
242             }
243             public Appendable reset(Appendable ps) {
244                 gos.reset();
245                 return ps;
246             }};
247 
248     private static BasicRunnable testCharBuffer =
249         new BasicRunnable() {
250             private String csn, exp;
251             private CharBuffer cb;
252             public void init(Appendable cb, String csn, String exp) {
253                 this.cb = (CharBuffer)cb;
254                 this.csn = csn;
255                 this.exp = exp;
256             }
257             public void run() {
258                 cb.limit(cb.position()).rewind();
259                 ck("CharBuffer.append(" + csn + ")", exp, cb.toString());
260             }
261             public Appendable reset(Appendable cb) {
262                 ((CharBuffer)cb).clear();
263                 return cb;
264             }};
265 
266     private static BasicRunnable testStringBuffer =
267         new BasicRunnable() {
268             private String csn, exp;
269             private StringBuffer sb;
270             public void init(Appendable sb, String csn, String exp) {
271                 this.sb = (StringBuffer)sb;
272                 this.csn = csn;
273                 this.exp = exp;
274             }
275             public void run() {
276                 ck("StringBuffer.append(" + csn + ")", exp, sb.toString());
277             }
278             public Appendable reset(Appendable sb) {
279                 return new StringBuffer();
280             }};
281 
282     private static BasicRunnable testStringBuilder =
283         new BasicRunnable() {
284             private String csn, exp;
285             private StringBuilder sb;
286             public void init(Appendable sb, String csn, String exp) {
287                 this.sb = (StringBuilder)sb;
288                 this.csn = csn;
289                 this.exp = exp;
290             }
291             public void run() {
292                 ck("StringBuilder.append(" + csn + ")", exp, sb.toString());
293             }
294             public Appendable reset(Appendable sb) {
295                 return new StringBuilder();
296             }};
297 
test(Appendable a, CharSequence csq, BasicRunnable thunk)298     private static void test(Appendable a, CharSequence csq, BasicRunnable thunk) {
299         // appends that should always work
300         int [][] sp = { { 0, 0 }, { 11, 11 }, { 11, 21 }, { 0, 7 },
301                         { 0, s.length() }, { s.length(), s.length() },
302         };
303         for (int j = 0; j < sp.length; j++) {
304             int start = sp[j][0];
305             int end = sp[j][1];
306             try {
307                 thunk.init(a.append(csq, start, end),
308                            csq.getClass().getName(),
309                            s.subSequence(start, end).toString());
310                 thunk.run();
311                 a = thunk.reset(a);
312             } catch (IOException x) {
313                 fail(x);
314             }
315         }
316 
317         // appends that should always throw IndexOutOfBoundsException
318         int [][] sf = { { -1, 0 }, { 0, -1 }, { 11, 10 },
319                         { 0, s.length() + 1},
320         };
321         for (int j = 0; j < sf.length; j++) {
322             int start = sf[j][0];
323             int end = sf[j][1];
324             try {
325                 a.append(csq, start, end);
326                 fail("start = " + start + ", end = " + end,
327                      new IndexOutOfBoundsException());
328                 a = thunk.reset(a);
329             } catch (IndexOutOfBoundsException x) {
330                 pass();
331             } catch (IOException x) {
332                 fail(x);
333             }
334         }
335 
336         // appends of null
337         int start = 1;
338         int end = 2;
339         try {
340             thunk.init(a.append(null, start, end), "null",
341                        "null".subSequence(start, end).toString());
342             thunk.run();
343             a = thunk.reset(a);
344         } catch (IOException x) {
345             fail(x);
346         }
347     }
348 
main(String [] args)349     public static void main(String [] args) throws Exception {
350         // CharSequences
351         CharBuffer cb = CharBuffer.allocate(128).put(s);
352         cb.limit(s.length()).rewind();
353         CharBuffer dcb = ByteBuffer.allocateDirect(128).asCharBuffer().put(s);
354         dcb.limit(s.length()).rewind();
355         CharSequence [] ca = { s,
356                                new StringBuffer(s),
357                                new StringBuilder(s),
358                                cb,
359                                dcb,
360         };
361 
362         // Appendables/Writers
363         Object [][] wa = { { new CharArrayWriter(), testCharArrayWriter },
364                            { new BufferedWriter(gw), testBufferedWriter },
365                            // abstract, no implementing classes in jdk
366                            // { new FilterWriter(), testFilterWriter },
367                            { new FileWriter(gf), testFileWriter },
368                            { new OutputStreamWriter(gos), testOutputStreamWriter },
369                            // covered by previous two test cases
370                            // { new PipedWriter(gw), testPipedWriter },
371                            { new PrintWriter(gw), testPrintWriter },
372                            { new StringWriter(), testStringWriter },
373         };
374 
375         for (int i = 0; i < ca.length; i++) {
376             CharSequence a = ca[i];
377             for (int j = 0; j < wa.length; j++)
378                 test((Writer)wa[j][0], a, (BasicRunnable)wa[j][1]);
379 
380             // other Appendables
381             test(new PrintStream(gos), a, testPrintStream);
382             test(CharBuffer.allocate(128), a, testCharBuffer);
383             test(ByteBuffer.allocateDirect(128).asCharBuffer(), a, testCharBuffer);
384             test(new StringBuffer(), a, testStringBuffer);
385             test(new StringBuilder(), a, testStringBuilder);
386         }
387 
388         if (fail != 0)
389             throw new RuntimeException((fail + pass) + " tests: "
390                                        + fail + " failure(s), first", first);
391         else
392             System.out.println("all " + (fail + pass) + " tests passed");
393     }
394 }
395