/**
* Copyright 2009 Google Inc.
*
* Licensed 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.waveprotocol.wave.concurrencycontrol.channel;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import org.waveprotocol.wave.concurrencycontrol.common.ChannelException;
import org.waveprotocol.wave.concurrencycontrol.common.ResponseCode;
import org.waveprotocol.wave.concurrencycontrol.testing.CcTestingUtils;
import org.waveprotocol.wave.model.id.IdFilter;
import org.waveprotocol.wave.model.id.WaveId;
import org.waveprotocol.wave.model.id.WaveletId;
import org.waveprotocol.wave.model.operation.wave.WaveletDelta;
import org.waveprotocol.wave.model.version.HashedVersion;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
/**
* A mock view channel which allows setting of expectations.
*
* @author anorth@google.com (Alex North)
*/
public final class MockViewChannel implements ViewChannel {
/**
* Factory for mock view channels. Provides access to the created channels.
*/
public static class Factory implements ViewChannelFactory {
private final Queue<MockViewChannel> channels = new LinkedList<MockViewChannel>();
/**
* Expects a channel creation.
*
* @return the channel which will be returned at {@link #create(WaveId)}
*/
public MockViewChannel expectCreate() {
MockViewChannel ch = new MockViewChannel();
channels.add(ch);
return ch;
}
@Override
public ViewChannel create(WaveId waveId) {
return channels.remove();
}
}
private enum Method { OPEN, SUBMIT, CLOSE }
private final Queue<Object[]> expectations = new LinkedList<Object[]>();
private final Queue<Listener> listeners = new LinkedList<Listener>();
private final Queue<SubmitCallback> awaitingAck = new LinkedList<SubmitCallback>();
public void expectOpen(IdFilter waveletFilter,
Map<WaveletId, List<HashedVersion>> knownWavelets) {
expectations.add(new Object[] {Method.OPEN, waveletFilter, knownWavelets});
}
public void expectSubmitDelta(WaveletId waveletId, WaveletDelta delta) {
expectations.add(new Object[] {Method.SUBMIT, waveletId, delta});
}
public void expectClose() {
expectations.add(new Object[] {Method.CLOSE});
}
public void checkExpectationsSatisified() {
assertTrue("Unsatisified view channel expectations", expectations.isEmpty());
}
@Override
public void open(Listener viewListener, IdFilter waveletFilter,
Map<WaveletId, List<HashedVersion>> knownWavelets) {
Object[] expected = expectations.remove();
assertEquals(expected[0], Method.OPEN);
assertEquals(expected[1], waveletFilter);
assertEquals(expected[2], knownWavelets);
listeners.add(viewListener);
}
@Override
public void submitDelta(WaveletId waveletId, WaveletDelta delta, SubmitCallback callback) {
Object[] expected = expectations.remove();
assertEquals(expected[0], Method.SUBMIT);
assertEquals(expected[1], waveletId);
assertTrue(CcTestingUtils.deltasAreEqual((WaveletDelta) expected[2], delta));
awaitingAck.add(callback);
}
@Override
public void close() {
Object[] expected = expectations.remove();
assertEquals(expected[0], Method.CLOSE);
// Emulate the real view channel in sending close() synchronously.
for (Listener l : listeners) {
l.onClosed();
}
}
public Listener takeListener() {
return listeners.remove();
}
public void ackSubmit(int opsApplied, long version, byte[] signature) throws ChannelException {
SubmitCallback nextCallback = awaitingAck.remove();
nextCallback.onSuccess(opsApplied, HashedVersion.of(version, signature), ResponseCode.OK, null);
}
public void nackSubmit(String reason, long version, byte[] signature) throws ChannelException {
SubmitCallback nextCallback = awaitingAck.remove();
nextCallback.onSuccess(0, HashedVersion.of(version, signature), ResponseCode.INTERNAL_ERROR,
reason);
}
@Override
public String debugGetProfilingInfo(WaveletId waveletId) {
return null;
}
}