Tests rewritten to new version, just the Writer version 2.0 does not yet implement Appendable
1.1 --- a/samples/delegatingwriterfinal/build.xml Sat Jun 14 09:53:06 2008 +0200
1.2 +++ b/samples/delegatingwriterfinal/build.xml Sat Jun 14 09:53:06 2008 +0200
1.3 @@ -13,20 +13,29 @@
1.4 </antcall>
1.5
1.6 <antcall target="-build-one">
1.7 - <param name="version" value="test"/>
1.8 + <param name="version" value="test1.0"/>
1.9 <param name="cp" value="build/api1.0/classes:${junit.jar}"/>
1.10 </antcall>
1.11 +
1.12 + <antcall target="-build-one">
1.13 + <param name="version" value="test2.0"/>
1.14 + <param name="cp" value="build/api2.0/classes:${junit.jar}"/>
1.15 + </antcall>
1.16 </target>
1.17
1.18 <target name="test" depends="build">
1.19 - <echo level="info" message="Running the Implementation against Version 1.0 of the API. This should succeeds."/>
1.20 + <echo level="info" message="Running the Old Implementation against Version 1.0 of the API. This should succeed."/>
1.21 <antcall target="-run-one">
1.22 <param name="version" value="api1.0"/>
1.23 </antcall>
1.24 - <echo level="info" message="Running the Implementation against Version 2.0 of the API. This should fail."/>
1.25 + <echo level="info" message="Running the Old Implementation against Version 2.0 of the API. This should succeed."/>
1.26 <antcall target="-run-one">
1.27 <param name="version" value="api2.0"/>
1.28 </antcall>
1.29 + <echo level="info" message="Running the New Implementation against Version 2.0 of the API. This should succeed."/>
1.30 + <antcall target="-run-two">
1.31 + <param name="version" value="api2.0"/>
1.32 + </antcall>
1.33 </target>
1.34
1.35 <!-- support methods -->
1.36 @@ -40,15 +49,34 @@
1.37 <target name="-run-one">
1.38 <fail message="You need to specify API version number" unless="version"/>
1.39 <mkdir dir="build/testresults"/>
1.40 - <junit dir="build/test/classes" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
1.41 + <junit dir="build/test1.0/classes" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
1.42 <batchtest todir="build/testresults">
1.43 - <fileset dir="build/test/classes">
1.44 + <fileset dir="build/test1.0/classes">
1.45 <filename name="**/*Test.class"/>
1.46 </fileset>
1.47 </batchtest>
1.48 <classpath>
1.49 <path location="build/${version}/classes"/>
1.50 - <path location="build/test/classes"/>
1.51 + <path location="build/test1.0/classes"/>
1.52 + <path location="${junit.jar}"/>
1.53 + </classpath>
1.54 + <formatter type="brief" usefile="false"/>
1.55 + <formatter type="xml"/>
1.56 + </junit>
1.57 + </target>
1.58 +
1.59 + <target name="-run-two">
1.60 + <fail message="You need to specify API version number" unless="version"/>
1.61 + <mkdir dir="build/testresults"/>
1.62 + <junit dir="build/test2.0/classes" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
1.63 + <batchtest todir="build/testresults">
1.64 + <fileset dir="build/test2.0/classes">
1.65 + <filename name="**/*Test.class"/>
1.66 + </fileset>
1.67 + </batchtest>
1.68 + <classpath>
1.69 + <path location="build/${version}/classes"/>
1.70 + <path location="build/test2.0/classes"/>
1.71 <path location="${junit.jar}"/>
1.72 </classpath>
1.73 <formatter type="brief" usefile="false"/>
2.1 --- a/samples/delegatingwriterfinal/nbproject/project.xml Sat Jun 14 09:53:06 2008 +0200
2.2 +++ b/samples/delegatingwriterfinal/nbproject/project.xml Sat Jun 14 09:53:06 2008 +0200
2.3 @@ -25,7 +25,13 @@
2.4 <source-folder>
2.5 <label>test</label>
2.6 <type>java</type>
2.7 - <location>src-test</location>
2.8 + <location>src-test1.0</location>
2.9 + <encoding>UTF-8</encoding>
2.10 + </source-folder>
2.11 + <source-folder>
2.12 + <label>test</label>
2.13 + <type>java</type>
2.14 + <location>src-test2.0</location>
2.15 <encoding>UTF-8</encoding>
2.16 </source-folder>
2.17 </folders>
2.18 @@ -55,8 +61,12 @@
2.19 <location>src-api2.0</location>
2.20 </source-folder>
2.21 <source-folder style="packages">
2.22 - <label>Usage of the API</label>
2.23 - <location>src-test</location>
2.24 + <label>Usage of the API 1.0</label>
2.25 + <location>src-test1.0</location>
2.26 + </source-folder>
2.27 + <source-folder style="packages">
2.28 + <label>Usage of the API 2.0</label>
2.29 + <location>src-test2.0</location>
2.30 </source-folder>
2.31 <source-file>
2.32 <location>build.xml</location>
2.33 @@ -80,10 +90,15 @@
2.34 <source-level>1.5</source-level>
2.35 </compilation-unit>
2.36 <compilation-unit>
2.37 - <package-root>src-test</package-root>
2.38 + <package-root>src-test1.0</package-root>
2.39 <classpath mode="compile">src-api1.0:../libs/dist/junit-4.4.jar</classpath>
2.40 <source-level>1.5</source-level>
2.41 </compilation-unit>
2.42 + <compilation-unit>
2.43 + <package-root>src-test2.0</package-root>
2.44 + <classpath mode="compile">src-api2.0:../libs/dist/junit-4.4.jar</classpath>
2.45 + <source-level>1.5</source-level>
2.46 + </compilation-unit>
2.47 </java-data>
2.48 </configuration>
2.49 </project>
3.1 --- a/samples/delegatingwriterfinal/src-api2.0/api/Writer.java Sat Jun 14 09:53:06 2008 +0200
3.2 +++ b/samples/delegatingwriterfinal/src-api2.0/api/Writer.java Sat Jun 14 09:53:06 2008 +0200
3.3 @@ -1,5 +1,6 @@
3.4 package api;
3.5
3.6 +import java.io.BufferedWriter;
3.7 import java.io.IOException;
3.8
3.9 /** Fixing the problem caused by mixing subclassing and delegation in
3.10 @@ -9,30 +10,124 @@
3.11 */
3.12 public final class Writer {
3.13 private final Impl impl;
3.14 + private final ImplSeq seq;
3.15
3.16 - private Writer(Impl impl) {
3.17 + private Writer(Impl impl, ImplSeq seq) {
3.18 this.impl = impl;
3.19 + this.seq = seq;
3.20 }
3.21 public final void write(int c) throws IOException {
3.22 - impl.write(new CharSeq(c));
3.23 + if (impl != null) {
3.24 + char[] arr = {(char) c};
3.25 + impl.write(arr, 0, 1);
3.26 + } else {
3.27 + seq.write(new CharSeq(c));
3.28 + }
3.29 }
3.30
3.31 public final void write(char cbuf[]) throws IOException {
3.32 - impl.write(new CharSeq(cbuf, 0, cbuf.length));
3.33 + if (impl != null) {
3.34 + impl.write(cbuf, 0, cbuf.length);
3.35 + } else {
3.36 + seq.write(new CharSeq(cbuf, 0, cbuf.length));
3.37 + }
3.38 }
3.39 public final void write(char cbuf[], int off, int len) throws IOException {
3.40 - impl.write(new CharSeq(cbuf, off, len));
3.41 + if (impl != null) {
3.42 + impl.write(cbuf, off, len);
3.43 + } else {
3.44 + seq.write(new CharSeq(cbuf, off, len));
3.45 + }
3.46 }
3.47 public final void write(String str) throws IOException {
3.48 - impl.write(str);
3.49 + if (impl != null) {
3.50 + impl.write(str, 0, str.length());
3.51 + } else {
3.52 + seq.write(str);
3.53 + }
3.54 }
3.55 public final void write(String str, int off, int len) throws IOException {
3.56 - impl.write(str.subSequence(off, off + len));
3.57 + if (impl != null) {
3.58 + impl.write(str, off, len);
3.59 + } else {
3.60 + seq.write(str.subSequence(off, off + len));
3.61 + }
3.62 }
3.63
3.64 + public final void flush() throws IOException {
3.65 + if (impl != null) {
3.66 + impl.flush();
3.67 + } else {
3.68 + seq.flush();
3.69 + }
3.70 + }
3.71 + public final void close() throws IOException {
3.72 + if (impl != null) {
3.73 + impl.close();
3.74 + } else {
3.75 + seq.flush();
3.76 + }
3.77 + }
3.78 +
3.79 + public static Writer create(Impl impl) {
3.80 + return new Writer(impl, null);
3.81 + }
3.82 +
3.83 + public static Writer create(ImplSeq impl) {
3.84 + return new Writer(null, impl);
3.85 + }
3.86 +
3.87 + public static Writer create(final java.io.Writer w) {
3.88 + return new Writer(new Impl() {
3.89 + public void write(String str, int off, int len) throws IOException {
3.90 + w.write(str, off, len);
3.91 + }
3.92 +
3.93 + public void write(char[] arr, int off, int len) throws IOException {
3.94 + w.write(arr, off, len);
3.95 + }
3.96 +
3.97 + public void close() throws IOException {
3.98 + w.close();
3.99 + }
3.100 +
3.101 + public void flush() throws IOException {
3.102 + w.flush();
3.103 + }
3.104 + }, null);
3.105 + }
3.106 +
3.107 + public static Writer createBuffered(final Writer out) {
3.108 + class Delegate extends java.io.Writer {
3.109 + @Override
3.110 + public void write(char[] cbuf, int off, int len) throws IOException {
3.111 + out.write(cbuf, off, len);
3.112 + }
3.113 +
3.114 + @Override
3.115 + public void flush() throws IOException {
3.116 + out.flush();
3.117 + }
3.118 +
3.119 + @Override
3.120 + public void close() throws IOException {
3.121 + out.close();
3.122 + }
3.123 +
3.124 + }
3.125 + return create(new BufferedWriter(new Delegate()));
3.126 + }
3.127
3.128
3.129 public static interface Impl {
3.130 + public void close() throws IOException;
3.131 + public void flush() throws IOException;
3.132 + public void write(String str, int off, int len) throws IOException;
3.133 + public void write(char[] arr, int off, int len) throws IOException;
3.134 + }
3.135 + public static interface ImplSeq {
3.136 + public void close() throws IOException;
3.137 + public void flush() throws IOException;
3.138 public void write(CharSequence seq) throws IOException;
3.139 }
3.140
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/samples/delegatingwriterfinal/src-test1.0/api/usage/BufferedWriterCryptoTest.java Sat Jun 14 09:53:06 2008 +0200
4.3 @@ -0,0 +1,37 @@
4.4 +
4.5 +package api.usage;
4.6 +
4.7 +import api.Writer;
4.8 +import java.io.IOException;
4.9 +import java.io.StringWriter;
4.10 +import java.io.StringWriter;
4.11 +import org.junit.Before;
4.12 +import org.junit.Test;
4.13 +import static org.junit.Assert.*;
4.14 +
4.15 +/** Converting the Crypto example to the APIs that split client and provider
4.16 + * concerns and do not mix delegation and subclassing.
4.17 + *
4.18 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.19 + */
4.20 +public class BufferedWriterCryptoTest {
4.21 + private StringWriter writer;
4.22 +
4.23 +
4.24 + public BufferedWriterCryptoTest() {
4.25 + }
4.26 +
4.27 + @Before
4.28 + public void setUp() {
4.29 + writer = new StringWriter();
4.30 + }
4.31 +
4.32 + @Test
4.33 + public void testBehaviourOfRealBufferInJDKWorksFine() throws IOException {
4.34 + Writer bufferedWriter = CryptoWriter.create(Writer.create(writer));
4.35 + bufferedWriter.write("VMS");
4.36 + bufferedWriter.flush();
4.37 + assertEquals("Converted", "WNT", writer.toString());
4.38 + }
4.39 +
4.40 +}
4.41 \ No newline at end of file
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/samples/delegatingwriterfinal/src-test2.0/api/usage/twodotzero/BufferedWriterOnCDImageTest.java Sat Jun 14 09:53:06 2008 +0200
5.3 @@ -0,0 +1,72 @@
5.4 +
5.5 +package api.usage.twodotzero;
5.6 +
5.7 +import api.Writer;
5.8 +import java.io.IOException;
5.9 +import java.util.concurrent.atomic.AtomicInteger;
5.10 +import org.junit.Test;
5.11 +import static org.junit.Assert.*;
5.12 +
5.13 +/** Emulates what goes wrong when one wants to process really large character
5.14 + * sequence.
5.15 + *
5.16 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.17 + */
5.18 +public class BufferedWriterOnCDImageTest {
5.19 +
5.20 + public BufferedWriterOnCDImageTest() {
5.21 + }
5.22 +
5.23 + @Test
5.24 + public void testBehaviourOfRealBufferInJDKObviouslyThisIsGoingToThrowOutOfMemoryError() throws IOException {
5.25 + AtomicInteger cnt = new AtomicInteger();
5.26 + Writer writer = CountingWriter.create(cnt);
5.27 + CDSequence cdImage = new CDSequence();
5.28 + Writer bufferedWriter = Writer.createBuffered(writer);
5.29 + bufferedWriter.append(cdImage);
5.30 + assertEquals("Correct number of writes delegated", cdImage.length(), cnt.get());
5.31 + }
5.32 +
5.33 +
5.34 + /** A "lazy" sequence of characters, for example one that can represent
5.35 + * content of a CD, read it lazily, do not fit all into memory at once.
5.36 + */
5.37 + private static final class CDSequence implements CharSequence {
5.38 + private final int start;
5.39 + private final int end;
5.40 +
5.41 + public CDSequence() {
5.42 + this(0, 647 * 1024 * 1024);
5.43 + }
5.44 +
5.45 + private CDSequence(int start, int end) {
5.46 + this.start = start;
5.47 + this.end = end;
5.48 + }
5.49 +
5.50 +
5.51 + public int length() {
5.52 + return end - start;
5.53 + }
5.54 +
5.55 + public char charAt(int index) {
5.56 + int ch = index % ('Z' - 'A' + 1);
5.57 + return (char) ('A' + ch);
5.58 + }
5.59 +
5.60 + public CharSequence subSequence(int start, int end) {
5.61 + return new CDSequence(start, end);
5.62 + }
5.63 +
5.64 + @Override
5.65 + public String toString() {
5.66 + char[] arr = new char[length()];
5.67 + for (int i = 0; i < length(); i++) {
5.68 + arr[i] = charAt(i);
5.69 + }
5.70 + return new String(arr);
5.71 + }
5.72 +
5.73 +
5.74 + } // end of CharSequence
5.75 +}
5.76 \ No newline at end of file
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/samples/delegatingwriterfinal/src-test2.0/api/usage/twodotzero/CountingWriter.java Sat Jun 14 09:53:06 2008 +0200
6.3 @@ -0,0 +1,36 @@
6.4 +
6.5 +package api.usage.twodotzero;
6.6 +
6.7 +import api.Writer;
6.8 +import java.io.IOException;
6.9 +import java.util.concurrent.atomic.AtomicInteger;
6.10 +
6.11 +/** Writer that counts the number of written in characters.
6.12 + *
6.13 + * @author Jaroslav Tulach
6.14 + */
6.15 +public class CountingWriter implements Writer.ImplSeq {
6.16 + private final AtomicInteger counter;
6.17 +
6.18 + private CountingWriter(AtomicInteger counter) {
6.19 + this.counter = counter;
6.20 + }
6.21 +
6.22 + public static Writer create(AtomicInteger result) {
6.23 + return Writer.create(new CountingWriter(result));
6.24 + }
6.25 +
6.26 + @Override
6.27 + public void write(CharSequence csq) throws IOException {
6.28 + counter.addAndGet(csq.length());
6.29 + }
6.30 +
6.31 + @Override
6.32 + public void flush() throws IOException {
6.33 + }
6.34 +
6.35 + @Override
6.36 + public void close() throws IOException {
6.37 + }
6.38 +
6.39 +}