/*
 * 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.geode.internal.cache.ha;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.cache.EventID;
import org.apache.geode.internal.serialization.DeserializationContext;
import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.serialization.VersionedDataInputStream;
import org.apache.geode.internal.serialization.VersionedDataOutputStream;
import org.apache.geode.test.junit.categories.ClientServerTest;

/**
 * This test verifies that eventId, while being sent across the network ( client to server, server
 * to client and peer to peer) , goes as optimized byte-array. For client to server messages, the
 * membership id part of event-id is not need to be sent with each event. Also, the threadId and
 * sequenceId need not be sent as long if their value is small. This is a junit test for testing the
 * methods written in <code>EventID</code> class for the above optimization. For distributed testing
 * for the same , please refer {@link EventIdOptimizationDUnitTest}.
 */
@Category({ClientServerTest.class})
public class EventIdOptimizationJUnitTest {

  /** The long id (threadId or sequenceId) having value equivalent to byte */
  private static final long ID_VALUE_BYTE = Byte.MAX_VALUE;

  /** The long id (threadId or sequenceId) having value equivalent to short */
  private static final long ID_VALUE_SHORT = Short.MAX_VALUE;

  /** The long id (threadId or sequenceId) having value equivalent to int */
  private static final long ID_VALUE_INT = Integer.MAX_VALUE;

  /** The long id (threadId or sequenceId) having value equivalent to long */
  private static final long ID_VALUE_LONG = Long.MAX_VALUE;

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for byte-byte combination for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForByteByte() {
    int expectedLength = 2 + 1 + 1;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_BYTE, ID_VALUE_BYTE, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for short-short combination for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForShortShort() {
    int expectedLength = 2 + 2 + 2;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_SHORT, ID_VALUE_SHORT, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for int-int combination for threadId
   * and sequenceId values.
   */
  @Test
  public void testOptimizationForIntInt() {
    int expectedLength = 2 + 4 + 4;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_INT, ID_VALUE_INT, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for long-long combination for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForLongLong() {
    int expectedLength = 2 + 8 + 8;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_LONG, ID_VALUE_LONG, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for byte-short combinations for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForByteShort() {
    int expectedLength = 2 + 1 + 2;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_BYTE, ID_VALUE_SHORT, expectedLength);
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_SHORT, ID_VALUE_BYTE, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for byte-int combinations for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForByteInt() {
    int expectedLength = 2 + 1 + 4;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_BYTE, ID_VALUE_INT, expectedLength);
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_INT, ID_VALUE_BYTE, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for byte-long combinations for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForByteLong() {
    int expectedLength = 2 + 1 + 8;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_BYTE, ID_VALUE_LONG, expectedLength);
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_LONG, ID_VALUE_BYTE, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for short-int combinations for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForShortInt() {
    int expectedLength = 2 + 2 + 4;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_SHORT, ID_VALUE_INT, expectedLength);
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_INT, ID_VALUE_SHORT, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for short-long combinations for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForShortLong() {
    int expectedLength = 2 + 2 + 8;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_SHORT, ID_VALUE_LONG, expectedLength);
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_LONG, ID_VALUE_SHORT, expectedLength);
  }

  /**
   * Tests the eventId optimization APIs <code>EventID#getOptimizedByteArrayForEventID</code> and
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> for int-long combinations for
   * threadId and sequenceId values.
   */
  @Test
  public void testOptimizationForIntLong() {
    int expectedLength = 2 + 4 + 8;
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_INT, ID_VALUE_LONG, expectedLength);
    writeReadAndVerifyOptimizedByteArray(ID_VALUE_LONG, ID_VALUE_INT, expectedLength);
  }

  @Test
  public void testEventIDForGEODE100Member() throws IOException, ClassNotFoundException {
    InternalDistributedMember distributedMember = new InternalDistributedMember("localhost", 10999);
    HeapDataOutputStream hdos = new HeapDataOutputStream(256, Version.CURRENT);
    distributedMember.writeEssentialData(hdos);
    byte[] memberBytes = hdos.toByteArray();
    EventID eventID = new EventID(memberBytes, 1, 1);


    HeapDataOutputStream hdos90 = new HeapDataOutputStream(256, Version.GFE_90);
    VersionedDataOutputStream dop = new VersionedDataOutputStream(hdos90, Version.GFE_90);

    eventID.toData(dop, InternalDataSerializer.createSerializationContext(dop));

    ByteArrayInputStream bais = new ByteArrayInputStream(hdos90.toByteArray());


    VersionedDataInputStream dataInputStream =
        new VersionedDataInputStream(bais, Version.GFE_90);

    EventID eventID2 = new EventID();
    eventID2.fromData(dataInputStream, mock(DeserializationContext.class));

    assertEquals(distributedMember, eventID2.getDistributedMember(Version.GFE_90));

    assertEquals(memberBytes.length + 17, eventID2.getMembershipID().length);
  }

  /**
   * Creates the optimized byte array using <code>EventID#getOptimizedByteArrayForEventID</code> api
   * with the given threadId and sequenceId and verifies that the length of that byte-array is as
   * expected, then reads the values for eventId and sequenceId from this byte-array using
   * <code>EventID#readEventIdPartsFromOptmizedByteArray</code> api and verifies that they are
   * decoded properly.
   *
   * @param threadId the long value of threadId
   * @param sequenceId the long value of sequenceId
   * @param expectedArrayLength expected length of the optimized byte-array
   */
  private void writeReadAndVerifyOptimizedByteArray(long threadId, long sequenceId,
      int expectedArrayLength) {
    byte[] array = EventID.getOptimizedByteArrayForEventID(threadId, sequenceId);
    assertEquals("optimized byte-array length not as expected", expectedArrayLength, array.length);
    ByteBuffer buffer = ByteBuffer.wrap(array);
    long threadIdReadFromOptArray = EventID.readEventIdPartsFromOptmizedByteArray(buffer);
    long sequenceIdReadFromOptArray = EventID.readEventIdPartsFromOptmizedByteArray(buffer);
    assertEquals("threadId value read is not same as that written to the byte-buffer", threadId,
        threadIdReadFromOptArray);
    assertEquals("sequenceId value read is not same as that written to the byte-buffer", sequenceId,
        sequenceIdReadFromOptArray);
  }

}
