Add Unit Tests for Feed Runtime Input Handler

Change-Id: I7088f489a7d53dee8cf6cdbf5baa7cd8d3884f55
Reviewed-on: https://asterix-gerrit.ics.uci.edu/866
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Michael Blow <michael.blow@couchbase.com>
diff --git a/hyracks-fullstack/hyracks/hyracks-api/pom.xml b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
index 3961921..9336921 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
@@ -39,7 +39,23 @@
   <properties>
     <root.dir>${basedir}/../..</root.dir>
   </properties>
-
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.4</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-jar</goal>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
   <dependencies>
     <dependency>
       <groupId>org.json</groupId>
@@ -77,5 +93,22 @@
       <artifactId>hyracks-util</artifactId>
       <version>0.2.18-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <version>2.0.2-beta</version>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>1.6.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>1.6.2</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAndThrowError.java b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAndThrowError.java
new file mode 100644
index 0000000..19998a7
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAndThrowError.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.api.test;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.mockito.invocation.InvocationOnMock;
+
+public class CountAndThrowError extends CountAnswer {
+    private String errorMessage;
+
+    public CountAndThrowError(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
+    @Override
+    public Object call() throws HyracksDataException {
+        count++;
+        throw new UnknownError(errorMessage);
+    }
+
+    @Override
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        count++;
+        throw new UnknownError(errorMessage);
+    }
+}
\ No newline at end of file
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAndThrowException.java b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAndThrowException.java
new file mode 100644
index 0000000..5a5ad59
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAndThrowException.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.api.test;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.mockito.invocation.InvocationOnMock;
+
+public class CountAndThrowException extends CountAnswer {
+    private String errorMessage;
+
+    public CountAndThrowException(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+
+    @Override
+    public Object call() throws HyracksDataException {
+        count++;
+        throw new HyracksDataException(errorMessage);
+    }
+
+    @Override
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        count++;
+        throw new HyracksDataException(errorMessage);
+    }
+}
\ No newline at end of file
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAnswer.java b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAnswer.java
new file mode 100644
index 0000000..e8a6654
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/CountAnswer.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.api.test;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class CountAnswer implements Answer<Object> {
+    protected int count = 0;
+
+    @Override
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        count++;
+        return null;
+    }
+
+    public Object call() throws HyracksDataException {
+        count++;
+        return null;
+    }
+
+    public int getCallCount() {
+        return count;
+    }
+
+    public void reset() {
+        count = 0;
+    }
+}
\ No newline at end of file
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/FrameWriterTestUtils.java b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/FrameWriterTestUtils.java
new file mode 100644
index 0000000..4bddfa9
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/FrameWriterTestUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.api.test;
+
+import java.util.Collection;
+
+public class FrameWriterTestUtils {
+    public static final String EXCEPTION_MESSAGE = "IFrameWriter Exception in the call to the method ";
+    public static final String ERROR_MESSAGE = "IFrameWriter Error in the call to the method ";
+
+    public enum FrameWriterOperation {
+        Open,
+        NextFrame,
+        Fail,
+        Flush,
+        Close
+    }
+
+    public static TestFrameWriter create(Collection<FrameWriterOperation> exceptionThrowingOperations,
+            Collection<FrameWriterOperation> errorThrowingOperations) {
+        CountAnswer openAnswer =
+                createAnswer(FrameWriterOperation.Open, exceptionThrowingOperations, errorThrowingOperations);
+        CountAnswer nextAnswer =
+                createAnswer(FrameWriterOperation.NextFrame, exceptionThrowingOperations, errorThrowingOperations);
+        CountAnswer flushAnswer =
+                createAnswer(FrameWriterOperation.Flush, exceptionThrowingOperations, errorThrowingOperations);
+        CountAnswer failAnswer =
+                createAnswer(FrameWriterOperation.Fail, exceptionThrowingOperations, errorThrowingOperations);
+        CountAnswer closeAnswer =
+                createAnswer(FrameWriterOperation.Close, exceptionThrowingOperations, errorThrowingOperations);
+        return new TestFrameWriter(openAnswer, nextAnswer, flushAnswer, failAnswer, closeAnswer);
+    }
+
+    public static CountAnswer createAnswer(FrameWriterOperation operation,
+            Collection<FrameWriterOperation> exceptionThrowingOperations,
+            Collection<FrameWriterOperation> errorThrowingOperations) {
+        if (exceptionThrowingOperations.contains(operation)) {
+            return new CountAndThrowException(EXCEPTION_MESSAGE + operation.toString());
+        } else if (exceptionThrowingOperations.contains(operation)) {
+            return new CountAndThrowError(ERROR_MESSAGE + operation.toString());
+        } else {
+            return new CountAnswer();
+        }
+    }
+
+    public static TestControlledFrameWriter create(int initialFrameSize) {
+        return new TestControlledFrameWriter(initialFrameSize);
+    }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/TestControlledFrameWriter.java b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/TestControlledFrameWriter.java
new file mode 100644
index 0000000..2a3f70d
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/TestControlledFrameWriter.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.api.test;
+
+import java.nio.ByteBuffer;
+
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class TestControlledFrameWriter extends TestFrameWriter {
+    private boolean frozen = false;
+    private boolean timed = false;
+    private long duration = Long.MAX_VALUE;
+    private final int initialFrameSize;
+    private volatile int currentMultiplier = 0;
+    private volatile int kicks = 0;
+
+    public TestControlledFrameWriter(int initialFrameSize) {
+        super(new CountAnswer(), new CountAnswer(), new CountAnswer(), new CountAnswer(), new CountAnswer());
+        this.initialFrameSize = initialFrameSize;
+    }
+
+    public int getCurrentMultiplier() {
+        return currentMultiplier;
+    }
+
+    public synchronized void freeze() {
+        frozen = true;
+    }
+
+    public synchronized void time(long ms) {
+        frozen = true;
+        timed = true;
+        duration = ms;
+    }
+
+    public synchronized void unfreeze() {
+        frozen = false;
+        notify();
+    }
+
+    public synchronized void kick() {
+        kicks++;
+        notify();
+    }
+
+    @Override
+    public synchronized void nextFrame(ByteBuffer buffer) throws HyracksDataException {
+        super.nextFrame(buffer);
+        currentMultiplier = buffer.capacity() / initialFrameSize;
+        if (frozen) {
+            try {
+                if (timed) {
+                    wait(duration);
+                } else {
+                    while (frozen && kicks == 0) {
+                        wait();
+                    }
+                    kicks--;
+                }
+            } catch (InterruptedException e) {
+                throw new HyracksDataException(e);
+            }
+        }
+        currentMultiplier = 0;
+    }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/TestFrameWriter.java b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/TestFrameWriter.java
new file mode 100644
index 0000000..b3492fe
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/test/java/org/apache/hyracks/api/test/TestFrameWriter.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.api.test;
+
+import java.nio.ByteBuffer;
+
+import org.apache.hyracks.api.comm.IFrameWriter;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class TestFrameWriter implements IFrameWriter {
+    private final CountAnswer openAnswer;
+    private final CountAnswer nextAnswer;
+    private final CountAnswer flushAnswer;
+    private final CountAnswer failAnswer;
+    private final CountAnswer closeAnswer;
+    private long openDuration = 0L;
+    private long nextDuration = 0L;
+    private long flushDuration = 0L;
+    private long failDuration = 0L;
+    private long closeDuration = 0L;
+
+    public TestFrameWriter(CountAnswer openAnswer, CountAnswer nextAnswer, CountAnswer flushAnswer,
+            CountAnswer failAnswer, CountAnswer closeAnswer) {
+        this.openAnswer = openAnswer;
+        this.nextAnswer = nextAnswer;
+        this.closeAnswer = closeAnswer;
+        this.flushAnswer = flushAnswer;
+        this.failAnswer = failAnswer;
+    }
+
+    @Override
+    public void open() throws HyracksDataException {
+        delay(openDuration);
+        openAnswer.call();
+    }
+
+    public int openCount() {
+        return openAnswer.getCallCount();
+    }
+
+    @Override
+    public void nextFrame(ByteBuffer buffer) throws HyracksDataException {
+        delay(nextDuration);
+        nextAnswer.call();
+    }
+
+    public int nextFrameCount() {
+        return nextAnswer.getCallCount();
+    }
+
+    @Override
+    public void flush() throws HyracksDataException {
+        delay(flushDuration);
+        flushAnswer.call();
+    }
+
+    public int flushCount() {
+        return flushAnswer.getCallCount();
+    }
+
+    @Override
+    public void fail() throws HyracksDataException {
+        delay(failDuration);
+        failAnswer.call();
+    }
+
+    public int failCount() {
+        return failAnswer.getCallCount();
+    }
+
+    @Override
+    public void close() throws HyracksDataException {
+        delay(closeDuration);
+        closeAnswer.call();
+    }
+
+    public int closeCount() {
+        return closeAnswer.getCallCount();
+    }
+
+    public synchronized boolean validate(boolean finished) {
+        if (failAnswer.getCallCount() > 1 || closeAnswer.getCallCount() > 1 || openAnswer.getCallCount() > 1) {
+            return false;
+        }
+        if (openAnswer.getCallCount() == 0
+                && (nextAnswer.getCallCount() > 0 || failAnswer.getCallCount() > 0 || closeAnswer.getCallCount() > 0)) {
+            return false;
+        }
+        if (finished) {
+            if (closeAnswer.getCallCount() == 0 && (nextAnswer.getCallCount() > 0 || failAnswer.getCallCount() > 0
+                    || openAnswer.getCallCount() > 0)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public void reset() {
+        openAnswer.reset();
+        nextAnswer.reset();
+        flushAnswer.reset();
+        failAnswer.reset();
+        closeAnswer.reset();
+    }
+
+    public long getOpenDuration() {
+        return openDuration;
+    }
+
+    public void setOpenDuration(long openDuration) {
+        this.openDuration = openDuration;
+    }
+
+    public long getNextDuration() {
+        return nextDuration;
+    }
+
+    public void setNextDuration(long nextDuration) {
+        this.nextDuration = nextDuration;
+    }
+
+    public long getFlushDuration() {
+        return flushDuration;
+    }
+
+    public void setFlushDuration(long flushDuration) {
+        this.flushDuration = flushDuration;
+    }
+
+    public long getFailDuration() {
+        return failDuration;
+    }
+
+    public void setFailDuration(long failDuration) {
+        this.failDuration = failDuration;
+    }
+
+    public long getCloseDuration() {
+        return closeDuration;
+    }
+
+    public void setCloseDuration(long closeDuration) {
+        this.closeDuration = closeDuration;
+    }
+
+    private void delay(long duration) throws HyracksDataException {
+        if (duration > 0) {
+            try {
+                synchronized (this) {
+                    wait(duration);
+                }
+            } catch (InterruptedException e) {
+                throw new HyracksDataException(e);
+            }
+        }
+    }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/pom.xml b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/pom.xml
index 581fde4..d07d633 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/pom.xml
@@ -39,6 +39,13 @@
   <dependencies>
     <dependency>
       <groupId>org.apache.hyracks</groupId>
+      <artifactId>hyracks-api</artifactId>
+      <version>0.2.18-SNAPSHOT</version>
+      <type>test-jar</type>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hyracks</groupId>
       <artifactId>hyracks-storage-common</artifactId>
       <version>0.2.18-SNAPSHOT</version>
       <type>jar</type>
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/test/java/org/apache/hyracks/storage/am/btree/test/FramewriterTest.java b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/test/java/org/apache/hyracks/storage/am/btree/test/FramewriterTest.java
index df3a211..d3e7a3a 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/test/java/org/apache/hyracks/storage/am/btree/test/FramewriterTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-storage-am-btree/src/test/java/org/apache/hyracks/storage/am/btree/test/FramewriterTest.java
@@ -30,6 +30,9 @@
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.dataflow.value.RecordDescriptor;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.test.CountAndThrowError;
+import org.apache.hyracks.api.test.CountAndThrowException;
+import org.apache.hyracks.api.test.CountAnswer;
 import org.apache.hyracks.dataflow.common.comm.io.ArrayTupleBuilder;
 import org.apache.hyracks.dataflow.common.comm.io.FrameTupleAccessor;
 import org.apache.hyracks.dataflow.common.comm.io.FrameTupleAppender;
@@ -92,8 +95,8 @@
     public boolean validate(boolean finished) {
         // get number of open calls
         int openCount = openException.getCallCount() + openNormal.getCallCount() + openError.getCallCount();
-        int nextFrameCount = nextFrameException.getCallCount() + nextFrameNormal.getCallCount()
-                + nextFrameError.getCallCount();
+        int nextFrameCount =
+                nextFrameException.getCallCount() + nextFrameNormal.getCallCount() + nextFrameError.getCallCount();
         int failCount = failException.getCallCount() + failNormal.getCallCount() + failError.getCallCount();
         int closeCount = closeException.getCallCount() + closeNormal.getCallCount() + closeError.getCallCount();
 
@@ -422,8 +425,9 @@
     public AbstractTreeIndexOperatorDescriptor[] mockIndexOpDesc() throws HyracksDataException, IndexException {
         IIndexDataflowHelperFactory[] indexDataflowHelperFactories = mockIndexHelperFactories();
         ISearchOperationCallbackFactory[] searchOpCallbackFactories = mockSearchOpCallbackFactories();
-        AbstractTreeIndexOperatorDescriptor[] opDescs = new AbstractTreeIndexOperatorDescriptor[indexDataflowHelperFactories.length
-                * searchOpCallbackFactories.length];
+        AbstractTreeIndexOperatorDescriptor[] opDescs =
+                new AbstractTreeIndexOperatorDescriptor[indexDataflowHelperFactories.length
+                        * searchOpCallbackFactories.length];
         int k = 0;
         for (int i = 0; i < indexDataflowHelperFactories.length; i++) {
             for (int j = 0; j < searchOpCallbackFactories.length; j++) {
@@ -452,52 +456,6 @@
         return opCallback;
     }
 
-    public class CountAnswer implements Answer<Object> {
-        protected int count = 0;
-
-        @Override
-        public Object answer(InvocationOnMock invocation) throws Throwable {
-            count++;
-            return null;
-        }
-
-        public int getCallCount() {
-            return count;
-        }
-
-        public void reset() {
-            count = 0;
-        }
-    }
-
-    public class CountAndThrowException extends CountAnswer {
-        private String errorMessage;
-
-        public CountAndThrowException(String errorMessage) {
-            this.errorMessage = errorMessage;
-        }
-
-        @Override
-        public Object answer(InvocationOnMock invocation) throws Throwable {
-            count++;
-            throw new HyracksDataException(errorMessage);
-        }
-    }
-
-    public class CountAndThrowError extends CountAnswer {
-        private String errorMessage;
-
-        public CountAndThrowError(String errorMessage) {
-            this.errorMessage = errorMessage;
-        }
-
-        @Override
-        public Object answer(InvocationOnMock invocation) throws Throwable {
-            count++;
-            throw new UnknownError(errorMessage);
-        }
-    }
-
     public IFrameWriter[] createOutputWriters() throws Exception {
         CountAnswer[] opens = new CountAnswer[] { openNormal, openException, openError };
         CountAnswer[] nextFrames = new CountAnswer[] { nextFrameNormal, nextFrameException, nextFrameError };