package com.atlassian.bitbucket.mesh.rpc;

import com.atlassian.bitbucket.mesh.rpc.v1.RpcStreamChunk;
import com.google.protobuf.ByteString;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.util.Optional;

import static com.atlassian.bitbucket.mesh.rpc.util.ByteStringUtils.unsafeWrap;
import static org.junit.Assert.*;

public class ZeroCopyUtilsTest {

    @Test
    public void testDeepCopyNull() {
        assertNull(ZeroCopyUtils.deepCopy(null));
    }

    @Test
    public void testDeepCopyOptional() {
        //Prepare some data that contains a ByteString constructed using unsafeWrap
        byte[] data = "this is a test".getBytes(StandardCharsets.UTF_8);
        Optional<ByteString> optional = Optional.of(unsafeWrap(data));

        //Create a deep copy
        Optional<ByteString> deepCopy = ZeroCopyUtils.deepCopy(optional);

        assertNotNull(deepCopy);
        assertEquals(optional, deepCopy);

        //Change the backing byte[]
        data[2] = 'a';
        data[3] = 't';

        //Verify that chunk was updated
        assertEquals("that is a test", optional.map(ByteString::toStringUtf8).orElse(null));
        assertEquals("this is a test", deepCopy.map(ByteString::toStringUtf8).orElse(null));
    }

    @Test
    public void testDeepCopyProducesDeepCopy() {
        //Prepare some data that contains a ByteString constructed using unsafeWrap
        byte[] data = "this is a test".getBytes(StandardCharsets.UTF_8);
        RpcStreamChunk chunk = RpcStreamChunk.newBuilder().setData(unsafeWrap(data)).build();

        //Create a deep copy
        RpcStreamChunk deepCopy = ZeroCopyUtils.deepCopy(chunk);

        assertNotNull(deepCopy);
        assertEquals(chunk, deepCopy);

        //Change the backing byte[]
        data[2] = 'a';
        data[3] = 't';

        //Verify that chunk was updated
        assertEquals("that is a test", chunk.getData().toStringUtf8());
        assertEquals("this is a test", deepCopy.getData().toStringUtf8());
    }
}