public ByteBuffer fetchOnePacket() throws IOException {
        int readLen;
        ByteBuffer result = defaultBuffer;
        result.clear();

        while (true) {
            headerByteBuffer.clear();
            readLen = readAll(headerByteBuffer);
            if (readLen != PACKET_HEADER_LEN) {
                // remote has close this channel
                LOG.info("Receive packet header failed, " +
                        "remote {} may close the channel.", remoteHostPortString);
                return null;
            }
            if (packetId() != sequenceId) {
                LOG.warn("receive packet sequence id[" + packetId() + "] want to get[" + sequenceId + "]");
                throw new IOException("Bad packet sequence.");
            }
            int packetLen = packetLen();
            if ((result.capacity() - result.position()) < packetLen) {
                // byte buffer is not enough, new one packet
                ByteBuffer tmp;
                if (packetLen < MAX_PHYSICAL_PACKET_LENGTH) {
                    // last packet, enough to this packet is OK.
                    tmp = ByteBuffer.allocate(packetLen + result.position());
                } else {
                    // already have packet, to allocate two packet.
                    tmp = ByteBuffer.allocate(2 * packetLen + result.position());
                }
                tmp.put(result.array(), 0, result.position());
                result = tmp;
            }

            // read one physical packet
            // before read, set limit to make read only one packet
            result.limit(result.position() + packetLen);
            readLen = readAll(result);
            if (readLen != packetLen) {
                LOG.warn("Length of received packet content(" + readLen
                        + ") is not equal with length in head.(" + packetLen + ")");
                return null;
            }
            accSequenceId();
            if (packetLen != MAX_PHYSICAL_PACKET_LENGTH) {
                result.flip();
                break;
            }
        }
        return result;
    }
@Test(expected = IOException.class)
    public void testBadSeq() throws IOException {
        // mock
        new Expectations() {
            {
                channel.read((ByteBuffer) any);
                minTimes = 0;
                result = new Delegate() {
                    int fakeRead(ByteBuffer buffer) {
                        int maxLen = MysqlChannel.MAX_PHYSICAL_PACKET_LENGTH;
                        MysqlSerializer serializer = MysqlSerializer.newInstance();
                        if (readIdx == 0) {
                            // packet
                            readIdx++;
                            serializer.writeInt3(maxLen);
                            serializer.writeInt1(packetId++);

                            buffer.put(serializer.toArray());
                            return 4;
                        } else if (readIdx == 1) {
                            readIdx++;
                            int readLen = buffer.remaining();
                            byte[] buf = new byte[readLen];
                            for (int i = 0; i < readLen; ++i) {
                                buf[i] = (byte) ('a' + (i % 26));

                            }
                            buffer.put(buf);
                            return readLen;
                        } else if (readIdx == 2) {
                            // packet
                            readIdx++;
                            serializer.writeInt3(10);
                            // NOTE: Bad packet seq
                            serializer.writeInt1(0);

                            buffer.put(serializer.toArray());
                            return 4;
                        } else if (readIdx == 3) {
                            readIdx++;
                            byte[] buf = new byte[buffer.remaining()];
                            for (int i = 0; i < buffer.remaining(); ++i) {
                                buf[i] = (byte) ('a' + (i % 26));

                            }
                            buffer.put(buf);
                            return buffer.remaining();
                        }
                        return 0;
                    }
                };
            }
        };

        MysqlChannel channel1 = new MysqlChannel(channel);

        ByteBuffer buf = channel1.fetchOnePacket();
    }