You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2018/10/30 09:42:11 UTC

[incubator-plc4x] branch master updated: - Removed obsolete classes (S7TypeDecoder and S7TypeEncoder) - Added tests for S7RequestSizeCalculator and S7RequestSizeCalculator

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git


The following commit(s) were added to refs/heads/master by this push:
     new a37d40c  - Removed obsolete classes (S7TypeDecoder and S7TypeEncoder) - Added tests for S7RequestSizeCalculator and S7RequestSizeCalculator
a37d40c is described below

commit a37d40c21e042cd8fa29afa884f472d55353d610
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Oct 30 10:42:08 2018 +0100

    - Removed obsolete classes (S7TypeDecoder and S7TypeEncoder)
    - Added tests for S7RequestSizeCalculator and S7RequestSizeCalculator
---
 plc4j/protocols/s7/pom.xml                         |   5 +
 .../s7/netty/util/S7RequestSizeCalculator.java     |  12 --
 .../s7/netty/util/S7ResponseSizeEstimator.java     |  14 +-
 .../plc4x/java/s7/netty/util/S7TypeDecoder.java    |  96 -------------
 .../plc4x/java/s7/netty/util/S7TypeEncoder.java    | 153 ---------------------
 .../s7/netty/util/S7RequestSizeCalculatorTest.java | 141 +++++++++++++++++++
 .../s7/netty/util/S7ResponseSizeEstimatorTest.java | 122 ++++++++++++++++
 7 files changed, 271 insertions(+), 272 deletions(-)

diff --git a/plc4j/protocols/s7/pom.xml b/plc4j/protocols/s7/pom.xml
index 198f92a..ce0b9bf 100644
--- a/plc4j/protocols/s7/pom.xml
+++ b/plc4j/protocols/s7/pom.xml
@@ -91,6 +91,11 @@
       <artifactId>commons-io</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.plc4x</groupId>
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7RequestSizeCalculator.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7RequestSizeCalculator.java
index bfebfd6..b8fe22c 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7RequestSizeCalculator.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7RequestSizeCalculator.java
@@ -84,10 +84,6 @@ public class S7RequestSizeCalculator {
     }
 
     private static short getRequestParameterSize(S7Parameter parameter) {
-        if (parameter == null) {
-            return 0;
-        }
-
         switch (parameter.getType()) {
             case READ_VAR:
             case WRITE_VAR:
@@ -130,10 +126,6 @@ public class S7RequestSizeCalculator {
     }
 
     private static short getRequestPayloadSize(S7Payload payload) {
-        if (payload == null) {
-            return 0;
-        }
-
         switch (payload.getType()) {
             case WRITE_VAR:
                 return getRequestWriteVarPayloadSize((VarPayload) payload);
@@ -152,10 +144,6 @@ public class S7RequestSizeCalculator {
     }
 
     private static short getRequestWriteVarPayloadItemSize(VarPayloadItem varPayloadItem) {
-        if(varPayloadItem == null) {
-            return 0;
-        }
-
         // A var payload item always has a minimum size of 4 bytes (return code, transport size, size (two bytes))
         short length = 4;
         length += varPayloadItem.getData().length;
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7ResponseSizeEstimator.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7ResponseSizeEstimator.java
index a0e66b8..121ea0b 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7ResponseSizeEstimator.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7ResponseSizeEstimator.java
@@ -94,10 +94,6 @@ public class S7ResponseSizeEstimator {
     }
 
     private static short getEstimatedResponseParameterSize(S7Parameter parameter) {
-        if (parameter == null) {
-            return 0;
-        }
-
         switch (parameter.getType()) {
             case READ_VAR:
             case WRITE_VAR:
@@ -125,19 +121,15 @@ public class S7ResponseSizeEstimator {
     }
 
     private static short getEstimatedResponsePayloadSize(S7Parameter parameter) {
-        if (parameter == null) {
-            return 0;
-        }
-
         switch (parameter.getType()) {
             case READ_VAR:
                 return getEstimatedResponseReadVarPayloadSize((VarParameter) parameter);
             case WRITE_VAR:
                 return getEstimatedResponseWriteVarPayloadSize((VarParameter) parameter);
-            case SETUP_COMMUNICATION:
+            // As we already handled all cases in the parameter size section, SETUP_COMMUNICATION
+            // is the last possible option.
+            default :
                 return 0;
-            default:
-                throw new NotImplementedException("Not implemented");
         }
     }
 
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java
deleted file mode 100644
index cb60ee7..0000000
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.plc4x.java.s7.netty.util;
-
-import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
-
-import java.nio.charset.StandardCharsets;
-import java.util.LinkedList;
-import java.util.List;
-
-public class S7TypeDecoder {
-
-    private S7TypeDecoder() {
-        // Utility class
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> List<T> decodeData(Class<T> datatype, byte[] s7Data) {
-
-        List<Object> result = new LinkedList<>();
-        int i = 0;
-        final int length = s7Data.length;
-        while (i < length) {
-            if (datatype == Boolean.class) {
-                result.add((s7Data[i] & 0x01) == 0x01);
-                i += 1;
-            } else if (datatype == Byte.class) {
-                result.add(s7Data[i]);
-                i += 1;
-            } else if (datatype == Short.class) {
-                result.add((short) (((s7Data[i] & 0xff) << 8) | (s7Data[i + 1] & 0xff)));
-                i += 2;
-            } else if (datatype == Integer.class) {
-                result.add(((s7Data[i] & 0xff) << 24) | ((s7Data[i + 1] & 0xff) << 16) |
-                    ((s7Data[i + 2] & 0xff) << 8) | (s7Data[i + 3] & 0xff));
-                i += 4;
-            } else if (datatype == Float.class) {
-                // Description of the Real number format:
-                // https://www.sps-lehrgang.de/zahlenformate-step7/#c144
-                // https://de.wikipedia.org/wiki/IEEE_754
-                int intValue = ((s7Data[i] & 0xff) << 24)
-                    | ((s7Data[i + 1] & 0xff) << 16)
-                    | ((s7Data[i + 2] & 0xff) << 8)
-                    | (s7Data[i + 3] & 0xff);
-                result.add(Float.intBitsToFloat(intValue));
-                i += 4;
-            } else if (datatype == Double.class) {
-                // Description of the Real number format:
-                // https://www.sps-lehrgang.de/zahlenformate-step7/#c144
-                // https://de.wikipedia.org/wiki/IEEE_754
-                long longValue = (((long) (s7Data[i] & 0xff)) << 56)
-                    | (((long) (s7Data[i] & 0xff)) << 48)
-                    | (((long) (s7Data[i + 1] & 0xff)) << 40)
-                    | (((long) (s7Data[i + 2] & 0xff)) << 32)
-
-                    | (((long) (s7Data[i + 3] & 0xff)) << 24)
-                    | (((long) (s7Data[i + 4] & 0xff)) << 16)
-                    | (((long) (s7Data[i + 5] & 0xff)) << 8)
-                    | ((long) s7Data[i + 6] & 0xff);
-                result.add(Double.longBitsToDouble(longValue));
-                i += 8;
-            } else if (datatype == String.class) {
-                // Every string value had a prefix of two bytes for which I have no idea, what the meaning is.
-                // This code assumes the string values doesn't contain UTF-8 values with a code of 0x00 as it
-                // uses this as termination char.
-                int j = 0;
-                for (; j < s7Data.length; j++) {
-                    if (s7Data[j] == 0) {
-                        break;
-                    }
-                }
-                result.add(new String(s7Data, 2, j - 2, StandardCharsets.UTF_8));
-                i += s7Data.length;
-            } else {
-                throw new PlcUnsupportedDataTypeException(datatype);
-            }
-        }
-        return (List<T>) result;
-    }
-}
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java
deleted file mode 100644
index bcadbde..0000000
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.plc4x.java.s7.netty.util;
-
-import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException;
-import org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException;
-
-import java.util.Calendar;
-
-public class S7TypeEncoder {
-
-    private S7TypeEncoder() {
-        // Utility class
-    }
-
-    public static byte[] encodeData(Object[] values) {
-        final int length = values.length;
-        if (length == 0) {
-            return new byte[]{};
-        }
-        final byte[] result;
-        Class valueType = values[0].getClass();
-        if (valueType == Boolean.class) {
-            result = encodeBoolean(values, length);
-        } else if (valueType == Byte.class) {
-            result = encodeByte(values, length);
-        } else if (valueType == Short.class) {
-            result = encodeShort(values, length);
-        } else if (valueType == Integer.class) {
-            result = encodeInteger(values, length);
-        } else if (valueType == Calendar.class) {
-            // TODO: Decide what to do here ...
-            throw new PlcNotImplementedException("calender not yet implemented in s7");
-        } else if (valueType == Float.class) {
-            result = encodeFloat(values, length);
-        } else if (valueType == Double.class) {
-            result = encodeDouble(values, length);
-        } else if (valueType == String.class) {
-            result = encodeString(values, length);
-        } else {
-            throw new PlcUnsupportedDataTypeException(valueType);
-        }
-        return result;
-    }
-
-    public static byte[] encodeString(Object[] values, int length) {
-        byte[] result;
-        int size = 0;
-        for (Object value : values) {
-            size = size + ((String) value).length();
-        }
-        result = new byte[size + length];
-        int j = 0;
-        for (Object value : values) {
-            String str = (String) value;
-            for (int i = 0; i < str.length(); i++) {
-                result[j++] = (byte) str.charAt(i);
-            }
-            result[j++] = (byte) 0x0;
-        }
-        return result;
-    }
-
-    public static byte[] encodeFloat(Object[] values, int length) {
-        byte[] result;
-        result = new byte[length * 4];
-        for (int i = 0; i < length; i++) {
-            float floatValue = (float) values[i];
-            int intValue = Float.floatToIntBits(floatValue);
-            result[i * 4] = (byte) ((intValue & 0xff000000) >> 24);
-            result[(i * 4) + 1] = (byte) ((intValue & 0x00ff0000) >> 16);
-            result[(i * 4) + 2] = (byte) ((intValue & 0x0000ff00) >> 8);
-            result[(i * 4) + 3] = (byte) (intValue & 0xff);
-        }
-        return result;
-    }
-
-    public static byte[] encodeDouble(Object[] values, int length) {
-        byte[] result;
-        result = new byte[length * 8];
-        for (int i = 0; i < length; i++) {
-            double doubleValue = (double) values[i];
-            long longValue = Double.doubleToLongBits(doubleValue);
-            result[i * 8] = (byte) ((longValue & 0xFF000000_00000000L) >> 56);
-            result[(i * 8) + 1] = (byte) ((longValue & 0x00FF0000_00000000L) >> 48);
-            result[(i * 8) + 2] = (byte) ((longValue & 0x0000FF00_00000000L) >> 40);
-            result[(i * 8) + 3] = (byte) ((longValue & 0x000000FF_00000000L) >> 32);
-            result[(i * 8) + 4] = (byte) ((longValue & 0x00000000_FF000000L) >> 24);
-            result[(i * 8) + 5] = (byte) ((longValue & 0x00000000_00FF0000L) >> 16);
-            result[(i * 8) + 6] = (byte) ((longValue & 0x00000000_0000FF00L) >> 8);
-            result[(i * 8) + 7] = (byte) (longValue & 0x00000000_000000FFL);
-        }
-        return result;
-    }
-
-    public static byte[] encodeInteger(Object[] values, int length) {
-        byte[] result;
-        result = new byte[length * 4];
-        for (int i = 0; i < length; i++) {
-            int intValue = (int) values[i];
-            result[i * 4] = (byte) ((intValue & 0xff000000) >> 24);
-            result[(i * 4) + 1] = (byte) ((intValue & 0x00ff0000) >> 16);
-            result[(i * 4) + 2] = (byte) ((intValue & 0x0000ff00) >> 8);
-            result[(i * 4) + 3] = (byte) (intValue & 0xff);
-        }
-        return result;
-    }
-
-    public static byte[] encodeShort(Object[] values, int length) {
-        byte[] result;
-        result = new byte[length * 2];
-        for (int i = 0; i < length; i++) {
-            short intValue = (short) values[i];
-            result[i * 2] = (byte) ((intValue & 0xff00) >> 8);
-            result[(i * 2) + 1] = (byte) (intValue & 0xff);
-        }
-        return result;
-    }
-
-    public static byte[] encodeByte(Object[] values, int length) {
-        byte[] result;
-        result = new byte[length];
-        for (int i = 0; i < length; i++) {
-            result[i] = (byte) values[i];
-        }
-        return result;
-    }
-
-    public static byte[] encodeBoolean(Object[] values, int length) {
-        byte[] result;// TODO: Check if this is true and the result is not Math.ceil(values.lenght / 8)
-        result = new byte[length];
-        for (int i = 0; i < length; i++) {
-            result[i] = (byte) (((Boolean) values[i]) ? 0x01 : 0x00);
-        }
-        return result;
-    }
-}
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/util/S7RequestSizeCalculatorTest.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/util/S7RequestSizeCalculatorTest.java
new file mode 100644
index 0000000..a7ab173
--- /dev/null
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/util/S7RequestSizeCalculatorTest.java
@@ -0,0 +1,141 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.java.s7.netty.util;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.plc4x.java.s7.netty.model.messages.S7RequestMessage;
+import org.apache.plc4x.java.s7.netty.model.params.S7Parameter;
+import org.apache.plc4x.java.s7.netty.model.params.SetupCommunicationParameter;
+import org.apache.plc4x.java.s7.netty.model.params.VarParameter;
+import org.apache.plc4x.java.s7.netty.model.params.items.S7AnyVarParameterItem;
+import org.apache.plc4x.java.s7.netty.model.params.items.VarParameterItem;
+import org.apache.plc4x.java.s7.netty.model.payloads.S7Payload;
+import org.apache.plc4x.java.s7.netty.model.payloads.VarPayload;
+import org.apache.plc4x.java.s7.netty.model.payloads.items.VarPayloadItem;
+import org.apache.plc4x.java.s7.netty.model.types.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class S7RequestSizeCalculatorTest {
+
+    @Test
+    void getReadVarRequestMessageSize() {
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new VarParameter(ParameterType.READ_VAR, Collections.singletonList(
+                    new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS, TransportSize.BYTE, 1, (short) 1, (short) 0, (byte) 0)))),
+            Collections.emptyList(),
+            null);
+        short size = S7RequestSizeCalculator.getRequestMessageSize(readVarRequest);
+        assertEquals(24, size);
+    }
+
+    @Test
+    void getWriteVarRequestMessageSize() {
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new VarParameter(ParameterType.WRITE_VAR, Collections.singletonList(
+                    new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS, TransportSize.BYTE, 1, (short) 1, (short) 0, (byte) 0)))),
+            Collections.singletonList(
+                new VarPayload(ParameterType.WRITE_VAR, Collections.singletonList(
+                    new VarPayloadItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, new byte[] {(byte) 0x01})))),
+            null);
+        short size = S7RequestSizeCalculator.getRequestMessageSize(readVarRequest);
+        assertEquals(30, size);
+    }
+
+    @Test
+    void getSetupCommunicationRequestMessageSize() {
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new SetupCommunicationParameter((short) 1, (short) 2, (short) 250)),
+            Collections.emptyList(),
+            null);
+        short size = S7RequestSizeCalculator.getRequestMessageSize(readVarRequest);
+        assertEquals(18, size);
+    }
+
+    @Test
+    void getUnimplementedParameterItemTypeMessageSize() {
+        S7Parameter mockParameter = mock(S7Parameter.class);
+        when(mockParameter.getType()).thenReturn(ParameterType.UPLOAD);
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(mockParameter),
+            Collections.emptyList(),
+            null);
+        Assertions.assertThrows(NotImplementedException.class,
+            () -> S7RequestSizeCalculator.getRequestMessageSize(readVarRequest));
+    }
+
+    @Test
+    void getUnimplementedVarAddressingModeMessageSize() {
+        VarParameterItem mockParameterItem = mock(VarParameterItem.class);
+        when(mockParameterItem.getAddressingMode()).thenReturn(VariableAddressingMode.ALARM_QUERYREQ);
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new VarParameter(ParameterType.WRITE_VAR, Collections.singletonList(mockParameterItem))),
+            Collections.emptyList(),
+            null);
+        Assertions.assertThrows(NotImplementedException.class,
+            () -> S7RequestSizeCalculator.getRequestMessageSize(readVarRequest));
+    }
+
+    @Test
+    void getUnimplementedPayloadTypeMessageSize() {
+        S7Payload mockPayload = mock(S7Payload.class);
+        when(mockPayload.getType()).thenReturn(ParameterType.UPLOAD);
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new VarParameter(ParameterType.WRITE_VAR, Collections.singletonList(
+                    new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS, TransportSize.BYTE, 1, (short) 1, (short) 0, (byte) 0)))),
+            Collections.singletonList(mockPayload),
+            null);
+        Assertions.assertThrows(NotImplementedException.class,
+            () -> S7RequestSizeCalculator.getRequestMessageSize(readVarRequest));
+    }
+
+    @Test
+    void getRequestItemTotalSize() {
+        short size = S7RequestSizeCalculator.getRequestItemTotalSize(
+            new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS, TransportSize.BYTE, 1, (short) 1, (short) 0, (byte) 0),
+            new VarPayloadItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, new byte[] {(byte) 0x01})
+        );
+        assertEquals(18, size);
+    }
+
+}
\ No newline at end of file
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/util/S7ResponseSizeEstimatorTest.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/util/S7ResponseSizeEstimatorTest.java
new file mode 100644
index 0000000..6116643
--- /dev/null
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/util/S7ResponseSizeEstimatorTest.java
@@ -0,0 +1,122 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+package org.apache.plc4x.java.s7.netty.util;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.plc4x.java.s7.netty.model.messages.S7RequestMessage;
+import org.apache.plc4x.java.s7.netty.model.params.S7Parameter;
+import org.apache.plc4x.java.s7.netty.model.params.SetupCommunicationParameter;
+import org.apache.plc4x.java.s7.netty.model.params.VarParameter;
+import org.apache.plc4x.java.s7.netty.model.params.items.S7AnyVarParameterItem;
+import org.apache.plc4x.java.s7.netty.model.payloads.VarPayload;
+import org.apache.plc4x.java.s7.netty.model.payloads.items.VarPayloadItem;
+import org.apache.plc4x.java.s7.netty.model.types.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class S7ResponseSizeEstimatorTest {
+
+    @Test
+    void getEstimatedReadVarResponseSize() {
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new VarParameter(ParameterType.READ_VAR, Collections.singletonList(
+                    new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS,
+                        TransportSize.BOOL, 1, (short) 1, (short) 0, (byte) 0)))),
+            Collections.emptyList(),
+            null);
+        short size = S7ResponseSizeEstimator.getEstimatedResponseMessageSize(readVarRequest);
+        assertEquals(20, size);
+    }
+
+    @Test
+    void getEstimatedWriteVarResponseSize() {
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new VarParameter(ParameterType.WRITE_VAR, Collections.singletonList(
+                    new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS,
+                        TransportSize.BYTE, 1, (short) 1, (short) 0, (byte) 0)))),
+            Collections.singletonList(
+                new VarPayload(ParameterType.WRITE_VAR, Collections.singletonList(
+                    new VarPayloadItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD,
+                        new byte[] {(byte) 0x01})))),
+            null);
+        short size = S7ResponseSizeEstimator.getEstimatedResponseMessageSize(readVarRequest);
+        assertEquals(15, size);
+    }
+
+    @Test
+    void getEstimatedSetupCommunicationResponseSize() {
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(
+                new SetupCommunicationParameter((short) 1, (short) 2, (short) 250)),
+            Collections.emptyList(),
+            null);
+        short size = S7ResponseSizeEstimator.getEstimatedResponseMessageSize(readVarRequest);
+        assertEquals(20, size);
+    }
+
+    @Test
+    void getEstimatedUnimplementedParameterItemTypeResponseSize() {
+        S7Parameter mockParameter = mock(S7Parameter.class);
+        when(mockParameter.getType()).thenReturn(ParameterType.UPLOAD);
+        S7RequestMessage readVarRequest = new S7RequestMessage(
+            MessageType.JOB,
+            (short) 1,
+            Collections.singletonList(mockParameter),
+            Collections.emptyList(),
+            null);
+        Assertions.assertThrows(NotImplementedException.class,
+            () -> S7ResponseSizeEstimator.getEstimatedResponseMessageSize(readVarRequest));
+    }
+
+    @Test
+    void getEstimatedResponseReadItemTotalSize() {
+        short size = S7ResponseSizeEstimator.getEstimatedResponseReadItemTotalSize(
+            new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS,
+                TransportSize.BYTE, 1, (short) 1, (short) 0, (byte) 0),
+            null
+        );
+        assertEquals(5, size);
+    }
+
+    @Test
+    void getEstimatedResponseWriteItemTotalSize() {
+        short size = S7ResponseSizeEstimator.getEstimatedResponseReadItemTotalSize(
+            new S7AnyVarParameterItem(SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS,
+                TransportSize.BYTE, 1, (short) 1, (short) 0, (byte) 0),
+            new VarPayloadItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, new byte[] {(byte) 0x01})
+        );
+        assertEquals(1, size);
+    }
+
+}
\ No newline at end of file