/*
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.edgent;

import com.google.gson.JsonObject;
import org.apache.edgent.function.Consumer;
import org.apache.edgent.function.Function;
import org.apache.edgent.function.Supplier;
import org.apache.plc4x.edgent.mock.MockAddress;
import org.apache.plc4x.edgent.mock.MockConnection;
import org.apache.plc4x.java.PlcDriverManager;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.messages.PlcReadResponse;
import org.apache.plc4x.java.api.messages.PlcWriteRequest;
import org.apache.plc4x.java.api.messages.PlcWriteResponse;
import org.apache.plc4x.java.api.messages.items.ReadRequestItem;
import org.apache.plc4x.java.api.messages.items.WriteRequestItem;
import org.apache.plc4x.java.api.model.Address;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Array;
import java.util.Calendar;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class PlcConnectionAdapterTest {

    // TODO figure out how to get these run via Eclipse (org.junit.jupiter.api?) and remove this
    // Ah... Junit 5... needs newer Eclipse (newer than neon 1.a)
    public static void main(String[] args) throws Exception {
        PlcConnectionAdapterTest t = new PlcConnectionAdapterTest();
        t.testCtor1();
        t.testCtor2();
        t.testCheckDatatype();
        t.testNewPlcReadRequest();
        t.testNewPlcWriteRequest();
        t.testNewSupplier();
        t.testNewSupplierNeg();
        t.testNewConsumer1();
        t.testNewConsumer1Neg();
        t.testNewConsumer2();
        t.testNewConsumer2Neg();
        System.out.println("SUCCESS");
    }

    protected MockConnection getMockConnection() throws PlcConnectionException {
        return (MockConnection) new PlcDriverManager().getConnection("mock://some-cool-url");
    }

    /*
     * Test the PlcConnectionAdapter(PlcConnection) ctor, getConnection() and close()
     */
    @Test
    @Tag("fast")
    public void testCtor1() throws Exception {
        MockConnection mockConnection = getMockConnection();
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(mockConnection);
        Assertions.assertSame(mockConnection, adapter.getConnection());
        // and again... multiple adapter.getConnection() returns the same
        Assertions.assertSame(mockConnection, adapter.getConnection());
        adapter.close();
    }

    /*
     * Test the PlcConnectionAdapter(url) ctor, getConnection() and close()
     */
    @Test
    @Tag("fast")
    public void testCtor2() throws Exception {
        MockConnection mockConnection = getMockConnection();
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(mockConnection.getUrl());
        MockConnection mockConnection2 = (MockConnection) adapter.getConnection();
        Assertions.assertNotSame(mockConnection, mockConnection2);
        Assertions.assertSame(mockConnection.getUrl(), mockConnection2.getUrl());
        // and again... multiple adapter.getConnection() returns the same
        Assertions.assertSame(mockConnection2, adapter.getConnection());
        adapter.close();
    }

    @Test
    @Tag("fast")
    public void testCheckDatatype() throws Exception {
        PlcConnectionAdapter.checkDatatype(Boolean.class);
        PlcConnectionAdapter.checkDatatype(Byte.class);
        PlcConnectionAdapter.checkDatatype(Short.class);
        PlcConnectionAdapter.checkDatatype(Integer.class);
        PlcConnectionAdapter.checkDatatype(Float.class);
        PlcConnectionAdapter.checkDatatype(String.class);
        PlcConnectionAdapter.checkDatatype(Calendar.class);
        Assertions.assertThrows(IllegalArgumentException.class,
            () -> PlcConnectionAdapter.checkDatatype(Long.class));
        Assertions.assertThrows(IllegalArgumentException.class,
            () -> PlcConnectionAdapter.checkDatatype(Double.class));
    }

    private <T> void checkRead(MockConnection connection, PlcReadRequest<T> request, T value) throws InterruptedException, ExecutionException {
        // this is really a tests of our mock tooling but knowing it's behaving as expected
        // will help identify problems in the adapter/supplier/consumer
        connection.setDataValue(request.getReadRequestItems().get(0).getAddress(), value);

        CompletableFuture<PlcReadResponse<T>> cf = connection.read(request);

        Assertions.assertTrue(cf.isDone());
        PlcReadResponse<T> response = cf.get();
        Assertions.assertEquals(value, response.getResponseItems().get(0).getValues().get(0));
    }

    @SuppressWarnings("unchecked")
    private <T> void checkWrite(MockConnection connection, PlcWriteRequest<T> request, T value) throws InterruptedException, ExecutionException {
        // this is really a tests of our mock tooling but knowing it's behaving as expected
        // will help identify problems in the adapter/supplier/consumer
        connection.setDataValue(request.getRequestItems().get(0).getAddress(), value);

        CompletableFuture<PlcWriteResponse<T>> cf = connection.write(request);

        Assertions.assertTrue(cf.isDone());
        PlcWriteResponse response = cf.get();
        Assertions.assertNotNull(response);
        T writtenData = (T) connection.getDataValue(request.getRequestItems().get(0).getAddress());
        if (writtenData.getClass().isArray()) {
            writtenData = (T) Array.get(writtenData, 0);
        }
        Assertions.assertEquals(value, writtenData);
    }

    /*
     * Verify the adapter yields the appropriate PlcReadRequest for each type and that it works.
     */
    @SuppressWarnings("unchecked")
    @Test
    @Tag("fast")
    public void testNewPlcReadRequest() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        {
            PlcReadRequest<Boolean> request = PlcConnectionAdapter.newPlcReadRequest(Boolean.class, address);
            ReadRequestItem<Boolean> requestItem = request.getReadRequestItems().get(0);
            Class<Boolean> dataType = requestItem.getDatatype();
            Assertions.assertTrue(dataType == Boolean.class, "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkRead(connection, request, true);
            checkRead(connection, request, false);
        }
        {
            PlcReadRequest<Byte> request = PlcConnectionAdapter.newPlcReadRequest(Byte.class, address);
            ReadRequestItem<Byte> requestItem = request.getReadRequestItems().get(0);
            Class<Byte> dataType = requestItem.getDatatype();
            Assertions.assertTrue(dataType == Byte.class, "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkRead(connection, request, (byte) 0x13);
            checkRead(connection, request, (byte) 0x23);
        }
        {
            PlcReadRequest<Short> request = PlcConnectionAdapter.newPlcReadRequest(Short.class, address);
            ReadRequestItem<Short> requestItem = request.getReadRequestItems().get(0);
            Class<Short> dataType = requestItem.getDatatype();
            Assertions.assertTrue(dataType == Short.class, "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkRead(connection, request, (short) 13);
            checkRead(connection, request, (short) 23);
        }
        {
            PlcReadRequest<Integer> request = PlcConnectionAdapter.newPlcReadRequest(Integer.class, address);
            ReadRequestItem<Integer> requestItem = request.getReadRequestItems().get(0);
            Class<Integer> dataType = requestItem.getDatatype();
            Assertions.assertTrue(dataType == Integer.class, "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkRead(connection, request, 33);
            checkRead(connection, request, -133);
        }
        {
            PlcReadRequest<Float> request = PlcConnectionAdapter.newPlcReadRequest(Float.class, address);
            ReadRequestItem<Float> requestItem = request.getReadRequestItems().get(0);
            Class<Float> dataType = requestItem.getDatatype();
            Assertions.assertTrue(dataType == Float.class, "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkRead(connection, request, 43.5f);
            checkRead(connection, request, -143.5f);
        }
        {
            PlcReadRequest<String> request = PlcConnectionAdapter.newPlcReadRequest(String.class, address);
            ReadRequestItem<String> requestItem = request.getReadRequestItems().get(0);
            Class<String> dataType = requestItem.getDatatype();
            Assertions.assertTrue(dataType == String.class, "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkRead(connection, request, "ReadySetGo");
            checkRead(connection, request, "OneMoreTime");
        }
        {
            PlcReadRequest<Calendar> request = PlcConnectionAdapter.newPlcReadRequest(Calendar.class, address);
            ReadRequestItem<Calendar> requestItem = request.getReadRequestItems().get(0);
            Class<Calendar> dataType = requestItem.getDatatype();
            Assertions.assertTrue(dataType == Calendar.class, "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkRead(connection, request, Calendar.getInstance());
        }
        adapter.close();
    }


    /*
     * Verify the adapter yields the appropriate PlcWriteRequest for each type and that it works.
     */
    @SuppressWarnings("unchecked")
    @Test
    @Tag("fast")
    public void testNewPlcWriteRequest() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        {
            PlcWriteRequest<Boolean> request = PlcConnectionAdapter.newPlcWriteRequest(address, true);
            WriteRequestItem<Boolean> requestItem = request.getRequestItems().get(0);
            Class<Boolean> dataType = requestItem.getDatatype();
            Assertions.assertTrue(Boolean.class.isAssignableFrom(dataType), "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkWrite(connection, request, true);
        }
        {
            PlcWriteRequest<Byte> request = PlcConnectionAdapter.newPlcWriteRequest(address, (byte) 0x113);
            WriteRequestItem<Byte> requestItem = request.getRequestItems().get(0);
            Class<Byte> dataType = requestItem.getDatatype();
            Assertions.assertTrue(Byte.class.isAssignableFrom(dataType), "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkWrite(connection, request, (byte) 0x113);
        }
        {
            PlcWriteRequest<Short> request = PlcConnectionAdapter.newPlcWriteRequest(address, (short) 113);
            WriteRequestItem<Short> requestItem = request.getRequestItems().get(0);
            Class<Short> dataType = requestItem.getDatatype();
            Assertions.assertTrue(Short.class.isAssignableFrom(dataType), "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkWrite(connection, request, (short) 113);
        }
        {
            PlcWriteRequest<Integer> request = PlcConnectionAdapter.newPlcWriteRequest(address, 1033);
            WriteRequestItem<Integer> requestItem = request.getRequestItems().get(0);
            Class<Integer> dataType = requestItem.getDatatype();
            Assertions.assertTrue(Integer.class.isAssignableFrom(dataType), "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkWrite(connection, request, 1033);
        }
        {
            PlcWriteRequest<Float> request = PlcConnectionAdapter.newPlcWriteRequest(address, 1043.5f);
            WriteRequestItem<Float> requestItem = request.getRequestItems().get(0);
            Class<Float> dataType = requestItem.getDatatype();
            Assertions.assertTrue(Float.class.isAssignableFrom(dataType), "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkWrite(connection, request, 1043.5f);
        }
        {
            PlcWriteRequest<String> request = PlcConnectionAdapter.newPlcWriteRequest(address, "A written value");
            WriteRequestItem<String> requestItem = request.getRequestItems().get(0);
            Class<String> dataType = requestItem.getDatatype();
            Assertions.assertTrue(String.class.isAssignableFrom(dataType), "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkWrite(connection, request, "A written value");
        }
        {
            Calendar calValue = Calendar.getInstance();
            PlcWriteRequest<Calendar> request = PlcConnectionAdapter.newPlcWriteRequest(address, calValue);
            WriteRequestItem<Calendar> requestItem = request.getRequestItems().get(0);
            Class<Calendar> dataType = requestItem.getDatatype();
            Assertions.assertTrue(Calendar.class.isAssignableFrom(dataType), "class:" + request.getClass());
            Assertions.assertSame(address, requestItem.getAddress());
            checkWrite(connection, request, calValue);
        }
        adapter.close();
    }

    /*
     * test PlcConnectionAdapter.newSupplier
     */
    @SuppressWarnings("unchecked")
    @Test
    @Tag("fast")
    public void testNewSupplier() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        {
            Supplier<Boolean> supplier = adapter.newSupplier(Boolean.class, addressStr);
            Assertions.assertNotSame(supplier, adapter.newSupplier(Boolean.class, addressStr));
            checkSupplier(connection, address, supplier, true, false);
        }
        {
            Supplier<Byte> supplier = adapter.newSupplier(Byte.class, addressStr);
            checkSupplier(connection, address, supplier, (byte) 0x1, (byte) 0x2, (byte) 0x3);
        }
        {
            Supplier<Short> supplier = adapter.newSupplier(Short.class, addressStr);
            checkSupplier(connection, address, supplier, (short) 1, (short) 2, (short) 3);
        }
        {
            Supplier<Integer> supplier = adapter.newSupplier(Integer.class, addressStr);
            checkSupplier(connection, address, supplier, 1000, 1001, 1002);
        }
        {
            Supplier<Float> supplier = adapter.newSupplier(Float.class, addressStr);
            checkSupplier(connection, address, supplier, 1000.5f, 1001.5f, 1002.5f);
        }
        {
            Supplier<?> supplier = adapter.newSupplier(String.class, addressStr);
            checkSupplier(connection, address, supplier, "one", "two", "three");
        }
        adapter.close();
    }

    /*
     * test PlcConnectionAdapter.newSupplier with read exception
     */
    @SuppressWarnings("unchecked")
    @Test
    @Tag("fast")
    public void testNewSupplierNeg() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        Supplier<String> supplier = adapter.newSupplier(String.class, addressStr);
        checkSupplier(2, connection, address, supplier, "one", "two", "three");

        adapter.close();
    }

    static <T> void checkSupplier(MockConnection connection, Address address, Supplier<T> supplier, Object... values) throws Exception {
        checkSupplier(0, connection, address, supplier, values);
    }

    private static <T> void checkSupplier(int readFailureCountTrigger, MockConnection connection, Address address, Supplier<T> supplier, Object... values) throws Exception {
        // verify that a read failure doesn't kill the consumer
        // it logs (not verified) but returns null (as designed) and keeps working for the subsequent reads
        connection.setReadException(readFailureCountTrigger, "This is a mock read exception");
        int readCount = 0;
        for (Object value : values) {
            connection.setDataValue(address, value);
            T readData = supplier.get();
            // System.out.println("checkSupplier"+(readFailureCountTrigger > 0 ? "NEG" : "")+": value:"+value+" readData:"+readData);
            if (readFailureCountTrigger <= 0)
                Assertions.assertEquals(value, readData);
            else {
                if (++readCount != readFailureCountTrigger)
                    Assertions.assertEquals(value, readData);
                else
                    Assertions.assertNull(readData);
            }
        }
    }

    /*
     * test PlcConnectionAdapter.newConsumer(address)
     */
    @SuppressWarnings("unchecked")
    @Test
    @Tag("fast")
    public void testNewConsumer1() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        Consumer<?> consumer;

        consumer = adapter.newConsumer(Boolean.class, addressStr);
        Assertions.assertNotSame(consumer, adapter.newConsumer(Boolean.class, addressStr));
        checkConsumer(connection, address, consumer, true, false);

        consumer = adapter.newConsumer(Byte.class, addressStr);
        checkConsumer(connection, address, consumer, (byte) 0x1, (byte) 0x2, (byte) 0x3);

        consumer = adapter.newConsumer(Short.class, addressStr);
        checkConsumer(connection, address, consumer, (short) 1, (short) 2, (short) 3);

        consumer = adapter.newConsumer(Integer.class, addressStr);
        checkConsumer(connection, address, consumer, 1000, 1001, 1002);

        consumer = adapter.newConsumer(Float.class, addressStr);
        checkConsumer(connection, address, consumer, 1000.5f, 1001.5f, 1002.5f);

        consumer = adapter.newConsumer(String.class, addressStr);
        checkConsumer(connection, address, consumer, "one", "two", "three");

        adapter.close();
    }

    /*
     * test PlcConnectionAdapter.newConsumer(address) with write exception
     */
    @SuppressWarnings("unchecked")
    @Test
    @Tag("fast")
    public void testNewConsumer1Neg() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        Consumer<?> consumer;

        consumer = adapter.newConsumer(String.class, addressStr);
        checkConsumer(2, connection, address, (Consumer<String>) consumer, "one", "two", "three");

        adapter.close();
    }

    static <T> void checkConsumer(MockConnection connection, Address address, Consumer<T> consumer, Object... values) throws Exception {
        checkConsumer(0, connection, address, consumer, values);
    }

    @SuppressWarnings("unchecked")
    private static <T> void checkConsumer(int writeFailureCountTrigger, MockConnection connection, Address address, Consumer<T> consumer, Object... values) throws Exception {
        // verify that a write failure doesn't kill the consumer
        // it logs (not verified) but keeps working for the subsequent writes
        connection.setWriteException(writeFailureCountTrigger, "This is a mock write exception");
        int writeCount = 0;
        Object previousValue = null;
        for (Object value : values) {
            consumer.accept((T) value);
            T writtenData = (T) connection.getDataValue(address);
            if (writtenData.getClass().isArray()) {
                writtenData = (T) Array.get(writtenData, 0);
            }
            // System.out.println("checkConsumer"+(writeFailureCountTrigger > 0 ? "NEG" : "")+": value:"+value+" writtenData:"+writtenData);
            if (writeFailureCountTrigger <= 0)
                Assertions.assertEquals(value, writtenData);
            else {
                if (++writeCount != writeFailureCountTrigger)
                    Assertions.assertEquals(value, writtenData);
                else
                    Assertions.assertEquals(previousValue, writtenData);
            }
            previousValue = value;
        }
    }

    /*
     * test PlcConnectionAdapter.newConsumer(addressFn, valueFn)
     */
    @Test
    @Tag("fast")
    public void testNewConsumer2() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        Consumer<JsonObject> consumer;

        Function<JsonObject, String> addressFn = t -> t.get("address").getAsString();

        consumer = adapter.newConsumer(Boolean.class, addressFn, t -> t.get("value").getAsBoolean());
        checkConsumerJson(connection, address, consumer, true, false);

        consumer = adapter.newConsumer(Byte.class, addressFn, t -> t.get("value").getAsByte());
        checkConsumerJson(connection, address, consumer, (byte) 0x1, (byte) 0x2, (byte) 0x3);

        consumer = adapter.newConsumer(Short.class, addressFn, t -> t.get("value").getAsShort());
        checkConsumerJson(connection, address, consumer, (short) 1, (short) 2, (short) 3);

        consumer = adapter.newConsumer(Integer.class, addressFn, t -> t.get("value").getAsInt());
        checkConsumerJson(connection, address, consumer, 1000, 1001, 1002);

        consumer = adapter.newConsumer(Float.class, addressFn, t -> t.get("value").getAsFloat());
        checkConsumerJson(connection, address, consumer, 1000.5f, 1001.5f, 1002.5f);

        consumer = adapter.newConsumer(String.class, addressFn, t -> t.get("value").getAsString());
        checkConsumerJson(connection, address, consumer, "one", "two", "three");

        adapter.close();
    }

    /*
     * test PlcConnectionAdapter.newConsumer(addressFn, valueFn) with write failure
     */
    @Test
    @Tag("fast")
    public void testNewConsumer2Neg() throws Exception {
        String addressStr = "MyReadWriteAddress/0";
        MockAddress address = new MockAddress(addressStr);
        PlcConnectionAdapter adapter = new PlcConnectionAdapter(getMockConnection());
        MockConnection connection = (MockConnection) adapter.getConnection();

        Consumer<JsonObject> consumer;

        Function<JsonObject, String> addressFn = t -> t.get("address").getAsString();

        consumer = adapter.newConsumer(String.class, addressFn, t -> t.get("value").getAsString());
        checkConsumerJson(2, connection, address, consumer, "one", "two", "three");

        adapter.close();
    }

    static <T> void checkConsumerJson(MockConnection connection, MockAddress address, Consumer<JsonObject> consumer, Object... values) throws Exception {
        checkConsumerJson(0, connection, address, consumer, values);
    }

    private static <T> void checkConsumerJson(int writeFailureCountTrigger, MockConnection connection, MockAddress address, Consumer<JsonObject> consumer, Object... values) throws Exception {
        if (writeFailureCountTrigger > 0)
            connection.setWriteException(writeFailureCountTrigger, "This is a mock write exception");
        int writeCount = 0;
        Object previousValue = null;
        for (Object value : values) {

            // build the JsonObject to consume
            JsonObject jo = new JsonObject();
            jo.addProperty("address", address.getAddress());
            if (value instanceof Boolean)
                jo.addProperty("value", (Boolean) value);
            else if (value instanceof Number)
                jo.addProperty("value", (Number) value);
            else if (value instanceof String)
                jo.addProperty("value", (String) value);

            consumer.accept(jo);

            @SuppressWarnings("unchecked")
            T writtenData = (T) connection.getDataValue(address);
            if (writtenData.getClass().isArray()) {
                writtenData = (T) Array.get(writtenData, 0);
            }
            // System.out.println("checkConsumerJson"+(writeFailureCountTrigger > 0 ? "NEG" : "")+": value:"+value+" writtenData:"+writtenData);
            if (writeFailureCountTrigger <= 0)
                Assertions.assertEquals(value, writtenData);
            else {
                if (++writeCount != writeFailureCountTrigger)
                    Assertions.assertEquals(value, writtenData);
                else
                    Assertions.assertEquals(previousValue, writtenData);
            }
            previousValue = value;
        }
    }

}
