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
29import java.io.BufferedReader;
30import java.io.BufferedWriter;
31import java.io.ByteArrayOutputStream;
32import java.io.CharArrayWriter;
33import java.io.File;
34import java.io.FileReader;
35import java.io.FileWriter;
36import java.io.IOException;
37import java.io.OutputStreamWriter;
38import java.io.PrintStream;
39import java.io.PrintWriter;
40import java.io.StringWriter;
41import java.io.Writer;
42import java.nio.ByteBuffer;
43import java.nio.CharBuffer;
44
45interface BasicRunnable extends Runnable {
46    void init(Appendable a, String csq, String exp);
47    Appendable reset(Appendable csq);
48}
49
50public 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
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
73    static void pass() {
74        pass++;
75    }
76
77    static void fail(Throwable ex) {
78        if (first == null)
79            first = ex;
80        System.err.println("FAILED: unexpected exception");
81        fail++;
82    }
83
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
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
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
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
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