package io.craft.atom.protocol.rpc; import io.craft.atom.protocol.ProtocolDecoder; import io.craft.atom.protocol.ProtocolEncoder; import io.craft.atom.protocol.ProtocolException; import io.craft.atom.protocol.rpc.KryoSerialization; import io.craft.atom.protocol.rpc.api.RpcCodecFactory; import io.craft.atom.protocol.rpc.model.RpcBody; import io.craft.atom.protocol.rpc.model.RpcHeader; import io.craft.atom.protocol.rpc.model.RpcMessage; import io.craft.atom.protocol.rpc.model.RpcMethod; import io.craft.atom.test.CaseCounter; import io.craft.atom.util.ByteArrayBuffer; import io.craft.atom.util.ByteUtil; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Tests for {@code RpcEncoder} and {@code RpcDecoder} * * @author mindwind * @version 1.0, Jul 22, 2014 */ public class TestRpcCodec { private static final Logger LOG = LoggerFactory.getLogger(TestRpcCodec.class); private static final byte STATUS_CODE = 40 ; private static final byte ID = 11 ; private RpcMessage rm = new RpcMessage() ; private RpcHeader rh = new RpcHeader() ; private ProtocolEncoder<RpcMessage> encoder = RpcCodecFactory.newRpcEncoder(); private ProtocolDecoder<RpcMessage> decoder = RpcCodecFactory.newRpcDecoder(); // ~ ------------------------------------------------------------------------------------------------------------- @Before public void before() { rh.setSt(KryoSerialization.getInstance().type()); rh.setHb(); rh.setOw(); rh.setRp(); rh.setId(ID); rh.setStatusCode(STATUS_CODE); RpcBody rb = new RpcBody(); rb.setRpcInterface(RpcService.class); RpcMethod method = new RpcMethod(); method.setName("rpc"); method.setParameterTypes(String.class, Integer.class); method.setParameters("hello", 1); rb.setRpcMethod(method); rm.setHeader(rh); rm.setBody(rb); } @Test public void testEncode() { byte[] b = encoder.encode(rm); Assert.assertArrayEquals(ByteUtil.short2bytes(RpcHeader.MAGIC), ByteUtil.split(b, 0, 2)); Assert.assertArrayEquals(ByteUtil.short2bytes(RpcHeader.HEADER_SIZE), ByteUtil.split(b, 2, 4)); Assert.assertEquals(RpcHeader.VERSION, b[4]); Assert.assertEquals(KryoSerialization.getInstance().type(), rh.getSt()); Assert.assertEquals(rh.getSt() | rh.getHb() | rh.getOw() | rh.getRp(), b[5]); Assert.assertEquals(STATUS_CODE, b[6]); Assert.assertEquals(0, b[7]); Assert.assertEquals(ID, ByteUtil.bytes2long(b, 8)); Assert.assertTrue(ByteUtil.bytes2int(b, 16) > 0); System.out.format("[CRAFT-ATOM-PROTOCOL-RPC] (^_^) <%s> Case -> test encode.\n", CaseCounter.incr(9)); } @Test public void testDecode() { byte[] b = encoder.encode(rm); List<RpcMessage> l = decoder.decode(b); Assert.assertEquals(1, l.size()); RpcMessage drm = l.get(0); Assert.assertEquals(rm, drm); LOG.debug("[CRAFT-ATOM-PROTOCOL-RPC] |expected ={}|", rm); LOG.debug("[CRAFT-ATOM-PROTOCOL-RPC] |actual ={}|", drm); System.out.format("[CRAFT-ATOM-PROTOCOL-RPC] (^_^) <%s> Case -> test decode.\n", CaseCounter.incr(2)); } @Test public void testStreamingDecode() { byte[] bytes = encoder.encode(rm); testInRandomLoop(rm, bytes, 1, true); testInRandomLoop(rm, bytes, 100, false); System.out.format("[CRAFT-ATOM-PROTOCOL-RPC] (^_^) <%s> Case -> test streaming decode.\n", CaseCounter.incr(2)); } @Test public void testPipelineDecode() { byte[] bytes = encoder.encode(rm); ByteArrayBuffer buf = new ByteArrayBuffer(); buf.append(bytes).append(bytes).append(bytes, 0, 100); byte[] b = buf.array(); List<RpcMessage> l = decoder.decode(b); Assert.assertEquals(2, l.size()); Assert.assertEquals(rm, l.get(0)); Assert.assertEquals(rm, l.get(1)); l = decoder.decode(ByteUtil.split(bytes, 100, bytes.length)); Assert.assertEquals(1, l.size()); Assert.assertEquals(rm, l.get(0)); System.out.format("[CRAFT-ATOM-PROTOCOL-RPC] (^_^) <%s> Case -> test pipeline decode.\n", CaseCounter.incr(5)); } @Test public void testInvalidDecode() { byte[] bytes = encoder.encode(rm); bytes[0] = (byte) (bytes[0] + 1); try { decoder.decode(bytes); Assert.fail(); } catch (ProtocolException e) { Assert.assertTrue(true); } bytes = encoder.encode(rm); bytes[50] = (byte) (bytes[50] + 1); try { decoder.reset(); decoder.decode(bytes); Assert.fail(); } catch (ProtocolException e) { Assert.assertTrue(true); } System.out.format("[CRAFT-ATOM-PROTOCOL-RPC] (^_^) <%s> Case -> test invalid decode.\n", CaseCounter.incr(2)); } private void testInRandomLoop(RpcMessage expected, byte[] bytes, int loop, boolean onebyte) { for (int i = 0; i < loop; i++) { List<byte[]> barr = new ArrayList<byte[]>(); if (onebyte) { for (int j = 0; j < bytes.length; j++) { barr.add(new byte[] { bytes[j] }); } } else { int rand = 1; for (int j = 0; j < bytes.length; j +=rand) { rand = new Random().nextInt(32); if (j + rand > bytes.length) { rand = bytes.length - j; } barr.add(ByteUtil.split(bytes, j, j + rand)); } } List<RpcMessage> rms = null; for (byte[] b : barr) { rms = decoder.decode(b); } Assert.assertEquals(1, rms.size()); RpcMessage actual = rms.get(0); Assert.assertEquals(expected, actual); } } }