package org.corfudb.runtime.view.replication;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.corfudb.protocols.wireprotocol.DataType;
import org.corfudb.protocols.wireprotocol.ILogData;
import org.corfudb.protocols.wireprotocol.LogData;
import org.corfudb.runtime.CorfuRuntime;
import org.corfudb.runtime.exceptions.OverwriteException;
import org.corfudb.runtime.view.AbstractViewTest;
import org.corfudb.runtime.view.Layout;
import org.corfudb.util.serializer.Serializers;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/** This test tests basic properties of the contract
* which all replication protocols must meet.
*
* Created by mwei on 4/13/17.
*/
public abstract class AbstractReplicationProtocolTest extends AbstractViewTest {
/** Return the replication protocol under test. */
abstract IReplicationProtocol getProtocol();
/** Setup the replication protocol nodes under test. */
abstract void setupNodes();
LogData getLogData(long globalAddress, byte[] payload)
{
ByteBuf b = Unpooled.buffer();
Serializers.CORFU.serialize(payload, b);
LogData d = new LogData(DataType.DATA, b);
d.setGlobalAddress(globalAddress);
return d;
}
/** Check if we can write and then read the value
* that was written.
*/
@Test
@SuppressWarnings("unchecked")
public void canWriteRead()
throws Exception {
setupNodes();
//begin tests
final CorfuRuntime r = getDefaultRuntime();
final IReplicationProtocol rp = getProtocol();
final Layout layout = r.getLayoutView().getLayout();
LogData data = getLogData(0, "hello world".getBytes());
rp.write(layout, data);
ILogData read = rp.read(layout, 0);
assertThat(read.getType())
.isEqualTo(DataType.DATA);
assertThat(read.getGlobalAddress())
.isEqualTo(0);
assertThat(read.getPayload(r))
.isEqualTo("hello world".getBytes());
}
/** Check to make sure reads never return empty in
* the case of an unwritten address.
*/
@Test
@SuppressWarnings("unchecked")
public void readOnlyCommitted()
throws Exception {
setupNodes();
//begin tests
final CorfuRuntime r = getDefaultRuntime();
final IReplicationProtocol rp = getProtocol();
final Layout layout = r.getLayoutView().getLayout();
ILogData read = rp.read(layout, 0);
assertThat(read.getType())
.isNotEqualTo(DataType.EMPTY);
read = rp.read(layout, 1);
assertThat(read.getType())
.isNotEqualTo(DataType.EMPTY);
}
/** Check to make sure that overwriting a previously
* written entry results in an OverwriteException.
*/
@Test
@SuppressWarnings("unchecked")
public void overwriteThrowsException()
throws Exception {
setupNodes();
//begin tests
final CorfuRuntime r = getDefaultRuntime();
final IReplicationProtocol rp = getProtocol();
final Layout layout = r.getLayoutView().getLayout();
LogData d1 = getLogData(0, "1".getBytes());
LogData d2 = getLogData(0, "2".getBytes());
rp.write(layout, d1);
assertThatThrownBy(() -> rp.write(layout, d2))
.isInstanceOf(OverwriteException.class);
}
}