14031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman/*
24031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  Licensed to the Apache Software Foundation (ASF) under one or more
34031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  contributor license agreements.  See the NOTICE file distributed with
44031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  this work for additional information regarding copyright ownership.
54031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  The ASF licenses this file to You under the Apache License, Version 2.0
64031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  (the "License"); you may not use this file except in compliance with
74031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  the License.  You may obtain a copy of the License at
84031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *
94031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *     http://www.apache.org/licenses/LICENSE-2.0
104031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *
114031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  Unless required by applicable law or agreed to in writing, software
124031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  distributed under the License is distributed on an "AS IS" BASIS,
134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  See the License for the specific language governing permissions and
154031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *  limitations under the License.
164031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman */
174031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
184031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanpackage org.apache.harmony.testframework;
194031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
204031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport junit.framework.Assert;
214031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport junit.framework.TestCase;
224031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport junit.framework.TestSuite;
234031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
244031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.io.IOException;
254031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.io.Writer;
264031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.util.Arrays;
274031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.util.Random;
284031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
294031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman/**
304031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * Tests behaviour common to all implementations of {@link Writer}. This adapts
314031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * writers that collects untransformed chars so that they may be tested.
324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman */
334031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanpublic abstract class CharSinkTester {
344031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
354031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private boolean throwsExceptions = true;
364031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
374031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
384031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Creates a new writer ready to receive an arbitrary number of chars. Each
394031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * time this method is invoked, any previously returned writers may be
40f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * discarded.
41f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     */
424031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    public abstract Writer create() throws Exception;
434031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
44f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    /**
454031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Returns the current set of chars written to the writer last returned by
464031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * {@link #create}, and releases any resources held by that writer.
47f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     */
48f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    public abstract char[] getChars() throws Exception;
49f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
504031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
514031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Configures whether the writer is expected to throw exceptions when an
52f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * error is encountered. Classes like {@code PrintWriter} report errors via
53f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * an API method instead.
54f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     */
55f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    public CharSinkTester setThrowsExceptions(boolean throwsExceptions) {
56f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        this.throwsExceptions = throwsExceptions;
574031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        return this;
584031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
59f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
609cf37e8b48732fccd4c301ed51aafed7074bd84eJakob Stoklund Olesen    public final TestSuite createTests() {
614031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        TestSuite result = new TestSuite();
624031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        result.addTest(new SinkTestCase("sinkTestNoWriting"));
634031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        result.addTest(new SinkTestCase("sinkTestWriteZeroChars"));
644031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        result.addTest(new SinkTestCase("sinkTestWriteCharByChar"));
65f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        result.addTest(new SinkTestCase("sinkTestWriteArray"));
664031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        result.addTest(new SinkTestCase("sinkTestWriteOffset"));
674031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        result.addTest(new SinkTestCase("sinkTestWriteLargeArray"));
68f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
69f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (throwsExceptions) {
70f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            result.addTest(new SinkTestCase("sinkTestWriteAfterClose"));
71f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        } else {
72f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            result.addTest(new SinkTestCase("sinkTestWriteAfterCloseSuppressed"));
734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
75dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return result;
76dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
77dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
78dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    @Override
79dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    public String toString() {
80f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        return getClass().getName();
81f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
82f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
834031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private static void assertArrayEquals(char[] expected, char[] actual) {
844031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        Assert.assertEquals(Arrays.toString(expected), Arrays.toString(actual));
85f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
86f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
87f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    public class SinkTestCase extends TestCase {
88f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
894031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        private SinkTestCase(String name) {
904031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            super(name);
91f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
92f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
93f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        public void sinkTestNoWriting() throws Exception {
94f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            char[] expected = new char[] { };
9523ff7cff52702a8bff904d8ab4c9ca67cc19d6caJim Grosbach
965eb195153950bc7ebfc30649494a78b2096b5ef8Jim Grosbach            Writer out = create();
97f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.close();
98f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            assertArrayEquals(expected, getChars());
99f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
100f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1015eb195153950bc7ebfc30649494a78b2096b5ef8Jim Grosbach        public void sinkTestWriteZeroChars() throws Exception {
1025eb195153950bc7ebfc30649494a78b2096b5ef8Jim Grosbach            char[] expected = new char[] { };
103f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
104f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Writer out = create();
105f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            char[] a = new char[1024];
106f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.write(a, 1000, 0);
107f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.write(a, 0, 0);
1084031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            out.write(new char[] { });
1094031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1104031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            out.close();
111f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            assertArrayEquals(expected, getChars());
112f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
113f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public void sinkTestWriteCharByChar() throws Exception {
1154031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            char[] expected = "EFGCDECBA".toCharArray();
1164031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1174031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Writer out = create();
1184031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            for (char c : expected) {
1194031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                out.write(c);
1204031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
1214031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
12274500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen            out.close();
12374500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen            assertArrayEquals(expected, getChars());
12474500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen        }
12574500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen
12674500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen        public void sinkTestWriteArray() throws Exception {
1274031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            char[] expected = "EFGCDECBA".toCharArray();
1284031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1294031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Writer out = create();
1304031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1312bff8abbf2c02065556332d50c4e4cf86a09034dJim Grosbach            out.write("EF".toCharArray());
1324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            out.write("GCDE".toCharArray());
1334031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            out.write("CBA".toCharArray());
1344031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1354031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            out.close();
1364031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            assertArrayEquals(expected, getChars());
1374031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
1384031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1394031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public void sinkTestWriteOffset() throws Exception {
1404031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            char[] expected = "EFGCDECBA".toCharArray();
1414031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Writer out = create();
1424031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1434031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            char[] a = new char[1024];
1444031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            a[1000] = 'E';
1454031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            a[1001] = 'F';
1464031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            out.write(a, 1000, 2);
1474031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1484031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            char[] b = new char[1024];
149f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            b[1020] = 'G';
150f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            b[1021] = 'C';
1514031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            b[1022] = 'D';
1524031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            b[1023] = 'E';
153f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.write(b, 1020, 4);
154f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
155f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            char[] c = new char[1024];
1564031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            c[0] = 'C';
1574031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            c[1] = 'B';
158f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            c[2] = 'A';
1594031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            out.write(c, 0, 3);
1604031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
161f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.close();
162f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            assertArrayEquals(expected, getChars());
163f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
164f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1654031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public void sinkTestWriteLargeArray() throws Exception {
1664031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Random dice = new Random();
167f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            char[] expected = new char[(1024 * 1024) + 1]; // 2 MB + 1 char
168f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            for (int c = 0; c < expected.length; c++) {
169f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                expected[c] = (char) ('A' + dice.nextInt(26));
170f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
1714031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1724031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Writer out = create();
173f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.write(expected);
174f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.close();
175f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
176f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            assertArrayEquals(expected, getChars());
177f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
1784031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1794031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public void sinkTestWriteAfterClose() throws Exception {
180f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            char[] expectedChars = "EF".toCharArray();
1814031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Writer out = create();
1824031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
183f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.write(expectedChars);
184f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.close();
185f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1864031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            try {
1874031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                out.write("GCDE".toCharArray());
188f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                fail("expected already closed exception");
189f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            } catch (IOException expected) {
1904031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
1914031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
192f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            assertArrayEquals(expectedChars, getChars());
193f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
1944031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1954031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public void sinkTestWriteAfterCloseSuppressed() throws Exception {
196f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Writer out = create();
197f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.write("EF".toCharArray());
198f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.close();
199f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            out.write("GCDE".toCharArray()); // no exception expected!
2004031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
2014031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
202f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        // adding a new test? Don't forget to update createTests().
203f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
204f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        @Override
205f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        public String getName() {
206f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            return CharSinkTester.this.toString() + ":" + super.getName();
207f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
208f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
2094031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman}
2104031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman