changeset 1090:99f8c3835de6

MySqlResponsePacketsDecoder in progress
author Devel 2
date Mon, 11 May 2020 10:59:41 +0200
parents b1c79edc6d5e
children fb3d83dfbd17
files stress-tester/src/main/java/com/passus/st/client/mysql/MySqlResponsePacketsDecoder.java stress-tester/src/test/java/com/passus/st/client/mysql/MySqlResponsePacketsDecoderTest.java stress-tester/src/test/resources/pcap/mysql/mysql_query_1000_records.pcap
diffstat 3 files changed, 154 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/client/mysql/MySqlResponsePacketsDecoder.java	Mon May 11 10:59:41 2020 +0200
@@ -0,0 +1,105 @@
+package com.passus.st.client.mysql;
+
+import com.passus.data.AbstractDataDecoder;
+import com.passus.data.DataUtils;
+import com.passus.net.FixedSizeLengthPduX;
+import com.passus.net.FixedSizeLengthPduXHandler;
+import com.passus.net.PduX;
+import com.passus.net.mysql.MySqlDecoder;
+import com.passus.net.mysql.MySqlDecoderContext;
+import com.passus.net.mysql.MySqlPacket;
+import com.passus.net.mysql.MySqlResponseDecoder;
+import org.apache.commons.lang3.mutable.MutableInt;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MySqlResponsePacketsDecoder extends AbstractDataDecoder<List<MySqlPacket>> {
+
+    private static final Logger LOGGER = LogManager.getLogger(MySqlResponsePacketsDecoder.class);
+
+    private final List<MySqlPacket> packets;
+
+    private final MySqlDecoderContext context;
+
+    private final MySqlPdu pdu;
+
+    public MySqlResponsePacketsDecoder(MySqlDecoderContext context) {
+        this.context = context;
+        this.pdu = new MySqlPdu(context);
+        this.packets = new ArrayList<>();
+    }
+
+    @Override
+    public List<MySqlPacket> getResult() {
+        return packets;
+    }
+
+    @Override
+    public void clear() {
+        pdu.pdu.clear();
+        packets.clear();
+    }
+
+    @Override
+    public void finish() {
+        pdu.decoder.finish();
+    }
+
+    @Override
+    public int decode(byte[] data, int offset, int length) {
+        pdu.handle(data, offset, length);
+        return length;
+    }
+
+    private class MySqlPdu implements FixedSizeLengthPduXHandler {
+
+        private final MySqlResponseDecoder decoder;
+
+        private final PduX pdu;
+
+        public MySqlPdu(MySqlDecoderContext context) {
+            decoder = new MySqlResponseDecoder(context);
+            decoder.context(context);
+
+            pdu = new FixedSizeLengthPduX(this, 3, false);
+        }
+
+        public void handle(byte[] data, int offset, int length) {
+            pdu.handle(data, offset, length);
+        }
+
+        @Override
+        public void decodeBlockLength(byte[] data, int offset, MutableInt value) {
+            value.setValue(DataUtils.getInt3LE(data, offset) + 1);
+        }
+
+        @Override
+        public void onNewPdu(byte[] data, int offset, int length) {
+            try {
+                decoder.decode(data, offset, length);
+                if (decoder.state() == MySqlDecoder.STATE_FINISHED) {
+                    MySqlPacket packet = decoder.getResult();
+                    if (packet != null) {
+                        packets.add(packet);
+                        if (context.stage() == MySqlDecoderContext.STAGE_REQUEST) {
+                            state(STATE_FINISHED);
+                        }
+                    }
+
+                    decoder.clear();
+                } else if (decoder.state() == MySqlDecoder.STATE_ERROR) {
+                    error("Decoder error. " + decoder.getLastError());
+                }
+            } catch (Exception e) {
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug(e.getMessage(), e);
+                }
+
+                decoder.clear();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/test/java/com/passus/st/client/mysql/MySqlResponsePacketsDecoderTest.java	Mon May 11 10:59:41 2020 +0200
@@ -0,0 +1,49 @@
+package com.passus.st.client.mysql;
+
+import com.passus.net.mysql.*;
+import com.passus.net.packet.Tcp;
+import com.passus.net.source.pcap.PcapUtils;
+import org.testng.annotations.Test;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.passus.data.DataDecoder.STATE_DATA_NEEDED;
+import static com.passus.data.DataDecoder.STATE_FINISHED;
+import static org.testng.AssertJUnit.assertEquals;
+
+public class MySqlResponsePacketsDecoderTest {
+    
+    @Test
+    public void testProcess1000Records() {
+        List<Tcp> tcps = PcapUtils.readTcpPackets("pcap/mysql/mysql_query_1000_records.pcap");
+        tcps = tcps.stream().filter(t -> t.hasPayload()).collect(Collectors.toList());
+
+        MySqlDecoderContext context = new MySqlDecoderContext();
+        MySqlRequestDecoder reqDecoder = new MySqlRequestDecoder(context);
+        MySqlResponsePacketsDecoder respDecoder = new MySqlResponsePacketsDecoder(context);
+
+        Iterator<Tcp> it = tcps.iterator();
+        reqDecoder.decode(it.next().getPayload());
+
+        respDecoder.decode(it.next().getPayload());
+        assertEquals(STATE_DATA_NEEDED, respDecoder.state());
+
+        respDecoder.decode(it.next().getPayload());
+        assertEquals(STATE_DATA_NEEDED, respDecoder.state());
+
+        respDecoder.decode(it.next().getPayload());
+        assertEquals(STATE_DATA_NEEDED, respDecoder.state());
+
+        respDecoder.decode(it.next().getPayload());
+        assertEquals(STATE_FINISHED, respDecoder.state());
+
+        List<MySqlPacket> packets = respDecoder.getResult();
+        assertEquals(6, packets.stream().filter(p -> p instanceof MySqlColumnDefinition).count());
+        assertEquals(1000, packets.stream().filter(p -> p instanceof MySqlRowResponse).count());
+
+        reqDecoder.decode(it.next().getPayload());
+
+    }
+}
\ No newline at end of file
Binary file stress-tester/src/test/resources/pcap/mysql/mysql_query_1000_records.pcap has changed