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 18 package org.apache.harmony.testframework; 19 20 import junit.framework.Assert; 21 import junit.framework.TestCase; 22 import junit.framework.TestSuite; 23 24 import java.io.IOException; 25 import java.io.Writer; 26 import java.util.Arrays; 27 import java.util.Random; 28 29 /** 30 * Tests behaviour common to all implementations of {@link Writer}. This adapts 31 * writers that collects untransformed chars so that they may be tested. 32 */ 33 public abstract class CharSinkTester { 34 35 private boolean throwsExceptions = true; 36 37 /** 38 * Creates a new writer ready to receive an arbitrary number of chars. Each 39 * time this method is invoked, any previously returned writers may be 40 * discarded. 41 */ create()42 public abstract Writer create() throws Exception; 43 44 /** 45 * Returns the current set of chars written to the writer last returned by 46 * {@link #create}, and releases any resources held by that writer. 47 */ getChars()48 public abstract char[] getChars() throws Exception; 49 50 /** 51 * Configures whether the writer is expected to throw exceptions when an 52 * error is encountered. Classes like {@code PrintWriter} report errors via 53 * an API method instead. 54 */ setThrowsExceptions(boolean throwsExceptions)55 public CharSinkTester setThrowsExceptions(boolean throwsExceptions) { 56 this.throwsExceptions = throwsExceptions; 57 return this; 58 } 59 createTests()60 public final TestSuite createTests() { 61 TestSuite result = new TestSuite(); 62 result.addTest(new SinkTestCase("sinkTestNoWriting")); 63 result.addTest(new SinkTestCase("sinkTestWriteZeroChars")); 64 result.addTest(new SinkTestCase("sinkTestWriteCharByChar")); 65 result.addTest(new SinkTestCase("sinkTestWriteArray")); 66 result.addTest(new SinkTestCase("sinkTestWriteOffset")); 67 result.addTest(new SinkTestCase("sinkTestWriteLargeArray")); 68 69 if (throwsExceptions) { 70 result.addTest(new SinkTestCase("sinkTestWriteAfterClose")); 71 } else { 72 result.addTest(new SinkTestCase("sinkTestWriteAfterCloseSuppressed")); 73 } 74 75 return result; 76 } 77 78 @Override toString()79 public String toString() { 80 return getClass().getName(); 81 } 82 assertArrayEquals(char[] expected, char[] actual)83 private static void assertArrayEquals(char[] expected, char[] actual) { 84 Assert.assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 85 } 86 87 public class SinkTestCase extends TestCase { 88 SinkTestCase(String name)89 private SinkTestCase(String name) { 90 super(name); 91 } 92 sinkTestNoWriting()93 public void sinkTestNoWriting() throws Exception { 94 char[] expected = new char[] { }; 95 96 Writer out = create(); 97 out.close(); 98 assertArrayEquals(expected, getChars()); 99 } 100 sinkTestWriteZeroChars()101 public void sinkTestWriteZeroChars() throws Exception { 102 char[] expected = new char[] { }; 103 104 Writer out = create(); 105 char[] a = new char[1024]; 106 out.write(a, 1000, 0); 107 out.write(a, 0, 0); 108 out.write(new char[] { }); 109 110 out.close(); 111 assertArrayEquals(expected, getChars()); 112 } 113 sinkTestWriteCharByChar()114 public void sinkTestWriteCharByChar() throws Exception { 115 char[] expected = "EFGCDECBA".toCharArray(); 116 117 Writer out = create(); 118 for (char c : expected) { 119 out.write(c); 120 } 121 122 out.close(); 123 assertArrayEquals(expected, getChars()); 124 } 125 sinkTestWriteArray()126 public void sinkTestWriteArray() throws Exception { 127 char[] expected = "EFGCDECBA".toCharArray(); 128 129 Writer out = create(); 130 131 out.write("EF".toCharArray()); 132 out.write("GCDE".toCharArray()); 133 out.write("CBA".toCharArray()); 134 135 out.close(); 136 assertArrayEquals(expected, getChars()); 137 } 138 sinkTestWriteOffset()139 public void sinkTestWriteOffset() throws Exception { 140 char[] expected = "EFGCDECBA".toCharArray(); 141 Writer out = create(); 142 143 char[] a = new char[1024]; 144 a[1000] = 'E'; 145 a[1001] = 'F'; 146 out.write(a, 1000, 2); 147 148 char[] b = new char[1024]; 149 b[1020] = 'G'; 150 b[1021] = 'C'; 151 b[1022] = 'D'; 152 b[1023] = 'E'; 153 out.write(b, 1020, 4); 154 155 char[] c = new char[1024]; 156 c[0] = 'C'; 157 c[1] = 'B'; 158 c[2] = 'A'; 159 out.write(c, 0, 3); 160 161 out.close(); 162 assertArrayEquals(expected, getChars()); 163 } 164 sinkTestWriteLargeArray()165 public void sinkTestWriteLargeArray() throws Exception { 166 Random dice = new Random(); 167 char[] expected = new char[(1024 * 1024) + 1]; // 2 MB + 1 char 168 for (int c = 0; c < expected.length; c++) { 169 expected[c] = (char) ('A' + dice.nextInt(26)); 170 } 171 172 Writer out = create(); 173 out.write(expected); 174 out.close(); 175 176 assertArrayEquals(expected, getChars()); 177 } 178 sinkTestWriteAfterClose()179 public void sinkTestWriteAfterClose() throws Exception { 180 char[] expectedChars = "EF".toCharArray(); 181 Writer out = create(); 182 183 out.write(expectedChars); 184 out.close(); 185 186 try { 187 out.write("GCDE".toCharArray()); 188 fail("expected already closed exception"); 189 } catch (IOException expected) { 190 } 191 192 assertArrayEquals(expectedChars, getChars()); 193 } 194 sinkTestWriteAfterCloseSuppressed()195 public void sinkTestWriteAfterCloseSuppressed() throws Exception { 196 Writer out = create(); 197 out.write("EF".toCharArray()); 198 out.close(); 199 out.write("GCDE".toCharArray()); // no exception expected! 200 } 201 202 // adding a new test? Don't forget to update createTests(). 203 204 @Override getName()205 public String getName() { 206 return CharSinkTester.this.toString() + ":" + super.getName(); 207 } 208 } 209 } 210