package org.jgroups.tests;
import org.jgroups.Address;
import org.jgroups.Global;
import org.jgroups.Header;
import org.jgroups.Message;
import org.jgroups.protocols.PingHeader;
import org.jgroups.protocols.TpHeader;
import org.jgroups.protocols.pbcast.NakAckHeader2;
import org.jgroups.util.ByteArrayDataInputStream;
import org.jgroups.util.Range;
import org.jgroups.util.UUID;
import org.jgroups.util.Util;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.DataInput;
import java.io.DataOutput;
import java.util.Map;
import java.util.function.Supplier;
/**
* @author Bela Ban
*/
@Test(groups=Global.FUNCTIONAL)
public class MessageTest {
static final short UDP_ID=101;
static final short PING_ID=102;
static final short NAKACK_ID=103;
public static void testFlags() {
Message m1=new Message();
assert !m1.isFlagSet(Message.Flag.OOB);
assert m1.getFlags() == 0;
m1.setFlag((Message.Flag[])null);
assert !m1.isFlagSet(Message.Flag.OOB);
assert !m1.isFlagSet(null);
}
public void testSettingMultipleFlags() {
Message msg=new Message();
msg.setFlag((Message.Flag[])null);
assert msg.getFlags() == 0;
msg.setFlag(Message.Flag.OOB,Message.Flag.NO_FC, null, Message.Flag.DONT_BUNDLE);
assert msg.isFlagSet(Message.Flag.OOB);
assert msg.isFlagSet(Message.Flag.NO_FC);
assert msg.isFlagSet(Message.Flag.DONT_BUNDLE);
}
public static void testFlags2() {
Message m1=new Message();
m1.setFlag(Message.Flag.OOB);
assert m1.isFlagSet(Message.Flag.OOB);
assert Message.isFlagSet(m1.getFlags(), Message.Flag.OOB);
assert !(m1.isFlagSet(Message.Flag.DONT_BUNDLE));
assert !Message.isFlagSet(m1.getFlags(), Message.Flag.DONT_BUNDLE);
}
public static void testFlags3() {
Message msg=new Message();
assert !msg.isFlagSet(Message.Flag.OOB);
msg.setFlag(Message.Flag.OOB);
assert msg.isFlagSet(Message.Flag.OOB);
msg.setFlag(Message.Flag.OOB);
assert msg.isFlagSet(Message.Flag.OOB);
}
public static void testClearFlags() {
Message msg=new Message();
msg.setFlag(Message.Flag.OOB);
assert msg.isFlagSet(Message.Flag.OOB);
msg.clearFlag(Message.Flag.OOB);
assert !msg.isFlagSet(Message.Flag.OOB);
msg.clearFlag(Message.Flag.OOB);
assert !msg.isFlagSet(Message.Flag.OOB);
msg.setFlag(Message.Flag.OOB);
assert msg.isFlagSet(Message.Flag.OOB);
}
public static void testClearFlags2() {
Message msg=new Message();
msg.setFlag(Message.Flag.OOB);
msg.setFlag(Message.Flag.NO_FC);
assert !msg.isFlagSet(Message.Flag.DONT_BUNDLE);
assert msg.isFlagSet(Message.Flag.OOB);
assert msg.isFlagSet(Message.Flag.NO_FC);
msg.clearFlag(Message.Flag.OOB);
assert !msg.isFlagSet(Message.Flag.OOB);
msg.setFlag(Message.Flag.DONT_BUNDLE);
assert msg.isFlagSet(Message.Flag.DONT_BUNDLE);
assert msg.isFlagSet(Message.Flag.NO_FC);
msg.clearFlag(Message.Flag.NO_FC);
assert !msg.isFlagSet(Message.Flag.NO_FC);
msg.clearFlag(Message.Flag.NO_FC);
assert !msg.isFlagSet(Message.Flag.NO_FC);
msg.clearFlag(Message.Flag.DONT_BUNDLE);
msg.clearFlag(Message.Flag.OOB);
assert msg.getFlags() == 0;
assert !msg.isFlagSet(Message.Flag.OOB);
assert !msg.isFlagSet(Message.Flag.DONT_BUNDLE);
assert !msg.isFlagSet(Message.Flag.NO_FC);
msg.setFlag(Message.Flag.DONT_BUNDLE);
assert msg.isFlagSet(Message.Flag.DONT_BUNDLE);
msg.setFlag(Message.Flag.DONT_BUNDLE);
assert msg.isFlagSet(Message.Flag.DONT_BUNDLE);
}
public void testDontLoopback() {
final Address DEST=Util.createRandomAddress("A");
Message msg=new Message(null).setTransientFlag(Message.TransientFlag.DONT_LOOPBACK);
msg.dest(null); // OK
msg.setDest(null);
msg.dest(DEST);
msg.clearTransientFlag(Message.TransientFlag.DONT_LOOPBACK);
msg.dest(DEST); // OK
msg.setTransientFlag(Message.TransientFlag.DONT_LOOPBACK);
msg.setTransientFlagIfAbsent(Message.TransientFlag.DONT_LOOPBACK);
short flags=(short)(Message.TransientFlag.DONT_LOOPBACK.value() + Message.TransientFlag.OOB_DELIVERED.value());
msg.setTransientFlag(flags);
}
public static void testBufferSize() throws Exception {
Message m1=new Message(null, "bela");
assert m1.getRawBuffer() != null;
assert m1.getBuffer() != null;
Assert.assertEquals(m1.getBuffer().length, m1.getLength());
byte[] new_buf={'m', 'i', 'c', 'h', 'e', 'l', 'l', 'e'};
m1.setBuffer(new_buf);
assert m1.getRawBuffer() != null;
assert m1.getBuffer() != null;
Assert.assertEquals(new_buf.length, m1.getLength());
Assert.assertEquals(m1.getBuffer().length, m1.getLength());
}
public static void testBufferOffset() throws Exception {
byte[] buf={'b', 'e', 'l', 'a', 'b', 'a', 'n'};
Message m1=new Message(null, buf, 0, 4);
Message m2=new Message(null, buf, 4, 3);
byte[] b1, b2;
b1=new byte[m1.getLength()];
System.arraycopy(m1.getRawBuffer(), m1.getOffset(), b1, 0, m1.getLength());
b2=new byte[m2.getLength()];
System.arraycopy(m2.getRawBuffer(), m2.getOffset(), b2, 0, m2.getLength());
Assert.assertEquals(4, b1.length);
Assert.assertEquals(3, b2.length);
}
public static void testSetBufferWithNullBuffer() {
byte[] buf={'b', 'e', 'l', 'a'};
Message m1=new Message();
m1.setBuffer(buf, 1, 2); // dummy data with non 0 oiffset and length
Assert.assertEquals(1, m1.getOffset());
Assert.assertEquals(2, m1.getLength());
m1.setBuffer(null, 1, 2); // dummy offset and length, is ignored
Assert.assertEquals(0, m1.getOffset());
Assert.assertEquals(0, m1.getLength());
}
@Test(groups=Global.FUNCTIONAL, expectedExceptions=ArrayIndexOutOfBoundsException.class)
public static void testInvalidOffset() {
byte[] buf={'b', 'e', 'l', 'a', 'b', 'a', 'n'};
Message m1=new Message(null, buf, -1, 4);
System.out.println("message is " + m1);
}
@Test(groups=Global.FUNCTIONAL, expectedExceptions=ArrayIndexOutOfBoundsException.class)
public static void testInvalidLength() {
byte[] buf={'b', 'e', 'l', 'a', 'b', 'a', 'n'};
Message m1=new Message(null, buf, 3, 6);
System.out.println("we should not get here with " + m1);
}
public static void testGetRawBuffer() {
byte[] buf={'b', 'e', 'l', 'a', 'b', 'a', 'n'};
Message m1=new Message(null, buf, 0, 4);
Message m2=new Message(null, buf, 4, 3);
Assert.assertEquals(buf.length, m1.getRawBuffer().length);
Assert.assertEquals(4, m1.getBuffer().length);
Assert.assertEquals(4, m1.getLength());
Assert.assertEquals(buf.length, m2.getRawBuffer().length);
Assert.assertEquals(3, m2.getBuffer().length);
Assert.assertEquals(3, m2.getLength());
}
public static void testSetObject() {
String s1="Bela Ban";
Message m1=new Message(null, s1);
Assert.assertEquals(0, m1.getOffset());
Assert.assertEquals(m1.getBuffer().length, m1.getLength());
String s2=m1.getObject();
Assert.assertEquals(s2, s1);
}
public static void testCopy() {
Message m1=new Message(null, "Bela Ban");
m1.setFlag(Message.Flag.OOB);
m1.setTransientFlag(Message.TransientFlag.OOB_DELIVERED);
Message m2=m1.copy();
Assert.assertEquals(m1.getOffset(), m2.getOffset());
Assert.assertEquals(m1.getLength(), m2.getLength());
assert m2.isFlagSet(Message.Flag.OOB);
assert m2.isTransientFlagSet(Message.TransientFlag.OOB_DELIVERED);
}
public static void testCopyWithOffset() {
byte[] buf={'b', 'e', 'l', 'a', 'b', 'a', 'n'};
Message m1=new Message(null, buf, 0, 4);
Message m2=new Message(null, buf, 4, 3);
Message m3, m4;
m3=m1.copy();
m4=m2.copy();
Assert.assertEquals(0, m3.getOffset());
Assert.assertEquals(4, m3.getLength());
Assert.assertEquals(4, m3.getBuffer().length);
Assert.assertEquals(4, m4.getOffset());
Assert.assertEquals(3, m4.getLength());
Assert.assertEquals(3, m4.getBuffer().length);
}
public static void testCopyHeaders() {
Message m1=new Message(null, "hello");
for(short id: new short[]{1, 2, 10, Global.BLOCKS_START_ID, Global.BLOCKS_START_ID +10}) {
m1.putHeader(id, new DummyHeader(id));
}
System.out.println("Headers for m1: " + m1.printHeaders());
Message m2=m1.copy(true, Global.BLOCKS_START_ID);
System.out.println("Headers for m2: " + m2.printHeaders());
Map<Short,Header> hdrs=m2.getHeaders();
assert hdrs.size() == 2;
assert hdrs.containsKey(Global.BLOCKS_START_ID);
short tmp=Global.BLOCKS_START_ID +10;
assert hdrs.containsKey(tmp);
}
public void testComputeFragOffsets() {
byte[] buf={0,1,2,3,4,5,6,7,8,9};
java.util.List<Range> retval=Util.computeFragOffsets(buf, 4);
System.out.println("list is " + retval);
Assert.assertEquals(3, retval.size());
Range r=retval.get(0);
Assert.assertEquals(0, r.low);
Assert.assertEquals(4, r.high);
r=retval.get(1);
Assert.assertEquals(4, r.low);
Assert.assertEquals(4, r.high);
r=retval.get(2);
Assert.assertEquals(8, r.low);
Assert.assertEquals(2, r.high);
}
public void testComputeFragOffsetsWithOffsets() {
Range r;
// byte[] buf={'p', 'a', 'd', 0,1,2,3,4,5,6,7,8,9, 'p', 'a', 'd', 'd', 'i', 'e'};
java.util.List<Range> retval=Util.computeFragOffsets(3, 10, 4);
System.out.println("list is " + retval);
Assert.assertEquals(3, retval.size());
r=retval.get(0);
Assert.assertEquals(3, r.low);
Assert.assertEquals(4, r.high);
r=retval.get(1);
Assert.assertEquals(7, r.low);
Assert.assertEquals(4, r.high);
r=retval.get(2);
Assert.assertEquals(11, r.low);
Assert.assertEquals(2, r.high);
}
public void testComputeFragOffsets2() {
byte[] buf={0,1,2,3,4,5,6,7,8,9};
java.util.List<Range> retval=Util.computeFragOffsets(buf, 10);
System.out.println("list is " + retval);
Assert.assertEquals(1, retval.size());
Range r=retval.get(0);
Assert.assertEquals(0, r.low);
Assert.assertEquals(10, r.high);
}
public void testComputeFragOffsets3() {
byte[] buf={0,1,2,3,4,5,6,7,8,9};
java.util.List<Range> retval=Util.computeFragOffsets(buf, 100);
System.out.println("list is " + retval);
Assert.assertEquals(1, retval.size());
Range r=retval.get(0);
Assert.assertEquals(0, r.low);
Assert.assertEquals(10, r.high);
}
public void testComputeFragOffsets4() {
byte[] buf={0,1,2,3,4,5,6,7,8,9};
java.util.List<Range> retval=Util.computeFragOffsets(buf, 5);
System.out.println("list is " + retval);
Assert.assertEquals(2, retval.size());
Range r=retval.get(0);
Assert.assertEquals(0, r.low);
Assert.assertEquals(5, r.high);
r=retval.get(1);
Assert.assertEquals(5, r.low);
Assert.assertEquals(5, r.high);
}
public static void testSizeNullMessage() throws Exception {
Message msg=new Message();
_testSize(msg);
}
public static void testSizeMessageWithDest() throws Exception {
Message msg=new Message(UUID.randomUUID());
_testSize(msg);
}
public static void testSizeMessageWithSrc() throws Exception {
Message msg=new Message(null).src(UUID.randomUUID());
_testSize(msg);
}
public static void testSizeMessageWithDestAndSrc() throws Exception {
Message msg=new Message(UUID.randomUUID()).src(UUID.randomUUID());
_testSize(msg);
}
public static void testSizeMessageWithDestAndSrcAndFlags() throws Exception {
Message msg=new Message(UUID.randomUUID()).src(UUID.randomUUID());
msg.setFlag(Message.Flag.OOB);
msg.setFlag(Message.Flag.DONT_BUNDLE);
_testSize(msg);
}
public static void testSizeMessageWithBuffer() throws Exception {
Message msg=new Message(null, "bela".getBytes());
_testSize(msg);
}
public static void testSizeMessageWithBuffer2() throws Exception {
Message msg=new Message(null, new byte[]{'b', 'e', 'l', 'a'});
_testSize(msg);
}
public static void testSizeMessageWithBuffer3() throws Exception {
Message msg=new Message(null, "bela");
_testSize(msg);
}
public void testSizeMessageWithDestAndSrcAndHeaders() throws Exception {
Message msg=new Message(UUID.randomUUID(), "bela".getBytes()).src(UUID.randomUUID());
addHeaders(msg);
_testSize(msg);
}
public void testReadFromSkipPayload() throws Exception {
Message msg=new Message(Util.createRandomAddress("A"), "bela".getBytes()).src(Util.createRandomAddress("B"));
addHeaders(msg);
byte[] buf=Util.streamableToByteBuffer(msg);
// ExposedByteArrayInputStream input=new ExposedByteArrayInputStream(buf);
// DataInput in=new DataInputStream(input);
ByteArrayDataInputStream in=new ByteArrayDataInputStream(buf);
Message msg2=new Message(false);
int payload_position=msg2.readFromSkipPayload(in);
msg2.setBuffer(buf, payload_position, buf.length - payload_position);
assert msg2.getOffset() == payload_position;
assert msg2.getLength() == msg.getLength();
assert msg2.size() == msg.size();
Message copy=msg2.copy();
assert copy.getOffset() == payload_position;
assert copy.getLength() == msg.getLength();
assert copy.size() == msg2.size();
}
public static void testReadFromSkipPayloadNullPayload() throws Exception {
Message msg=new Message(Util.createRandomAddress("A")).src(Util.createRandomAddress("B"));
addHeaders(msg);
byte[] buf=Util.streamableToByteBuffer(msg);
// ExposedByteArrayInputStream input=new ExposedByteArrayInputStream(buf);
// DataInput in=new DataInputStream(input);
ByteArrayDataInputStream in=new ByteArrayDataInputStream(buf);
Message msg2=new Message(false);
int payload_position=msg2.readFromSkipPayload(in);
if(payload_position >= 0)
msg2.setBuffer(buf, payload_position, buf.length - payload_position);
assert msg2.getOffset() == 0;
assert msg2.getLength() == msg.getLength();
assert msg.getRawBuffer() == null;
assert msg2.getRawBuffer() == null;
assert msg.getBuffer() == null;
assert msg2.getBuffer() == null;
assert msg2.size() == msg.size();
Message copy=msg2.copy();
assert copy.getOffset() == 0;
assert copy.getLength() == msg.getLength();
assert copy.getRawBuffer() == null;
assert copy.getBuffer() == null;
assert copy.size() == msg2.size();
}
protected static void addHeaders(Message msg) {
TpHeader tp_hdr=new TpHeader("DemoChannel2");
msg.putHeader(UDP_ID, tp_hdr);
PingHeader ping_hdr=new PingHeader(PingHeader.GET_MBRS_REQ).clusterName("demo-cluster");
msg.putHeader(PING_ID, ping_hdr);
NakAckHeader2 nak_hdr=NakAckHeader2.createXmitRequestHeader(Util.createRandomAddress("S"));
msg.putHeader(NAKACK_ID, nak_hdr);
}
private static void _testSize(Message msg) throws Exception {
long size=msg.size();
byte[] serialized_form=Util.streamableToByteBuffer(msg);
System.out.println("size=" + size + ", serialized size=" + serialized_form.length);
Assert.assertEquals(size, serialized_form.length);
}
protected static class DummyHeader extends Header {
protected short num;
public DummyHeader() {
}
public DummyHeader(short num) {
this.num=num;
}
public short getMagicId() {return 1600;}
public Supplier<? extends Header> create() {
return DummyHeader::new;
}
public short getNum() {
return num;
}
public int serializedSize() {
return 0;
}
public void writeTo(DataOutput out) throws Exception {
}
public void readFrom(DataInput in) throws Exception {
}
public String toString() {
return "DummyHeader(" + num + ")";
}
}
}