private void assertMsg(Message msg) {
   assertNotNull(msg);
   assertEquals(9999L, msg.getId());
   assertEquals("test", msg.getTopic());
   assertFalse(msg.hasAttribute());
   assertEquals(0, MessageAccessor.getFlag(msg));
   assertEquals("hello", new String(msg.getData()));
 }
 /**
  * 从binary数据中解出消息
  *
  * @param topic
  * @param data
  * @param offset
  * @return
  * @throws InvalidMessageException
  */
 public static final DecodedMessage decodeMessage(
     final String topic, final byte[] data, final int offset) throws InvalidMessageException {
   final ByteBuffer buf = ByteBuffer.wrap(data, offset, HEADER_LEN);
   final int msgLen = buf.getInt();
   final int checksum = buf.getInt();
   vailidateMessage(offset + HEADER_LEN, msgLen, checksum, data);
   final long id = buf.getLong();
   // 取flag
   final int flag = buf.getInt();
   String attribute = null;
   int payLoadOffset = offset + HEADER_LEN;
   int payLoadLen = msgLen;
   if (payLoadLen > MAX_READ_BUFFER_SIZE) {
     throw new InvalidMessageException("Too much long payload length:" + payLoadLen);
   }
   // 如果有属性,需要解析属性
   if (MessageFlagUtils.hasAttribute(flag)) {
     // 取4个字节的属性长度
     final int attrLen = getInt(offset + HEADER_LEN, data);
     // 取消息属性
     final byte[] attrData = new byte[attrLen];
     System.arraycopy(data, offset + HEADER_LEN + 4, attrData, 0, attrLen);
     attribute = ByteUtils.getString(attrData);
     // 递增payloadOffset,加上4个字节的消息长度和消息长度本身
     payLoadOffset = offset + HEADER_LEN + 4 + attrLen;
     // payload长度递减,减去4个字节的消息长度和消息长度本身
     payLoadLen = msgLen - 4 - attrLen;
   }
   // 获取payload
   final byte[] payload = new byte[payLoadLen];
   System.arraycopy(data, payLoadOffset, payload, 0, payLoadLen);
   final Message msg = new Message(topic, payload);
   MessageAccessor.setFlag(msg, flag);
   msg.setAttribute(attribute);
   MessageAccessor.setId(msg, id);
   return new DecodedMessage(
       payLoadOffset + payLoadLen,
       msg,
       ByteBuffer.wrap(data, offset, payLoadOffset + payLoadLen - offset));
 }