content: /*
   * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
   * (the "License"). You may not use this work except in compliance with the License, which is
   * available at www.apache.org/licenses/LICENSE-2.0
   *
   * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
   * either express or implied, as more fully set forth in the License.
   *
   * See the NOTICE file distributed with this work for information regarding copyright ownership.
   */
  
  package alluxio.worker.page;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertNotEquals;
  import static org.junit.Assert.assertThrows;
  
  import alluxio.client.file.cache.PageId;
  
  import com.google.common.collect.ImmutableList;
  import com.google.common.collect.ImmutableSet;
  import org.apache.curator.shaded.com.google.common.collect.Sets;
  import org.junit.Test;
  
  import java.util.List;
  import java.util.Objects;
  import java.util.Set;
  
  public class BlockPageIdTest {
    private static final long BLOCK_SIZE = 0;
  
    @Test
    public void equality() {
      BlockPageId id1 = new BlockPageId(1, 1, BLOCK_SIZE);
      BlockPageId id2 = new BlockPageId("1", 1, BLOCK_SIZE);
      BlockPageId id3 = new BlockPageId(1, 1, BLOCK_SIZE);
      // reflexive
      assertEquals(id1, id1);
      assertEquals(id2, id2);
      assertEquals(id3, id3);
      // symmetric
      assertEquals(id1, id2);
      assertEquals(id2, id1);
      // transitive
      assertEquals(id1, id2);
      assertEquals(id2, id3);
      assertEquals(id3, id1);
    }
  
    @Test
    public void equalityWithParentClass() {
      BlockPageId id1 = new BlockPageId("1", 1, BLOCK_SIZE);
      PageId id2 = new PageId(BlockPageId.fileIdOf(1, BLOCK_SIZE), 1);
      assertEquals(id1, id2);
      assertEquals(id2, id1);
    }
  
    @Test
    public void usedAsKeyInCollections() {
      Set<PageId> pages = ImmutableSet.of(
          new PageId(BlockPageId.fileIdOf(1, BLOCK_SIZE), 0),
          new BlockPageId(1, 0, BLOCK_SIZE)
      );
      assertEquals(1, pages.size());
    }
  
    @Test
    public void inequalityWithOtherSubclass() {
      PageId id = new BlockPageId("1", 1, BLOCK_SIZE);
      PageId otherSubclassId = new MoreFieldsPageId("1", 1, BLOCK_SIZE);
      assertNotEquals(id, otherSubclassId);
      assertNotEquals(otherSubclassId, id);
    }
  
    @Test
    public void inequality() {
      Set<Object> pageIds = ImmutableSet.of(
          new BlockPageId(1, 1, BLOCK_SIZE),
          new BlockPageId(2, 1, BLOCK_SIZE),
          new BlockPageId(1, 2, BLOCK_SIZE),
          new BlockPageId(2, 2, BLOCK_SIZE),
          new Object());
  
      for (Set<Object> set : Sets.combinations(pageIds, 2)) {
        List<Object> pair = ImmutableList.copyOf(set);
        assertNotEquals(pair.get(0), pair.get(1));
        assertNotEquals(pair.get(1), pair.get(0));
      }
    }
  
    @Test
    public void testHashCode() {
      PageId id1 = new BlockPageId(1, 1, BLOCK_SIZE);
      PageId id2 = new BlockPageId("1", 1, BLOCK_SIZE);
      assertEquals(id1, id2);
      assertEquals(id1.hashCode(), id2.hashCode());
  
      PageId id3 = new PageId(BlockPageId.fileIdOf(1, BLOCK_SIZE), 1);
      assertEquals(id1, id3);
      assertEquals(id1.hashCode(), id3.hashCode());
    }
  
    @Test
    public void getBlockId() {
      long blockId = 2;
      BlockPageId pageId = new BlockPageId(blockId, 0, BLOCK_SIZE);
      assertEquals(blockId, pageId.getBlockId());
    }
  
    @Test
    public void getBlockSize() {
      long blockSize = 42;
      BlockPageId pageId = new BlockPageId(1, 0, blockSize);
      assertEquals(blockSize, pageId.getBlockSize());
    }
  
    @Test
    public void downcastOk() {
      PageId wellFormed = new PageId("paged_block_1234567890abcdef_size_0123cafebabedead", 0);
      BlockPageId downcast = BlockPageId.downcast(wellFormed);
      assertEquals(wellFormed, downcast);
      assertEquals(0x1234_5678_90ab_cdefL, downcast.getBlockId());
      assertEquals(0x0123_cafe_babe_deadL, downcast.getBlockSize());
  
      BlockPageId self = new BlockPageId(1234L, 0, BLOCK_SIZE);
      assertEquals(self, BlockPageId.downcast(self));
  
      PageId negativeBlockId = new PageId("paged_block_ffffffffffffffff_size_0000000000000001", 0);
      downcast = BlockPageId.downcast(negativeBlockId);
      assertEquals(negativeBlockId, downcast);
      assertEquals(-1L, downcast.getBlockId());
      assertEquals(1, downcast.getBlockSize());
    }
  
    @Test
    public void downcastWrong() {
      PageId noPrefix = new PageId("_1234567890abcdef_size_0123cafebabedead", 0);
      assertThrows(IllegalArgumentException.class, () -> BlockPageId.downcast(noPrefix));
      PageId notEnoughDigits = new PageId("paged_block_size_1234_cafe", 0);
      assertThrows(IllegalArgumentException.class, () -> BlockPageId.downcast(notEnoughDigits));
      PageId empty = new PageId("", 0);
      assertThrows(IllegalArgumentException.class, () -> BlockPageId.downcast(empty));
      PageId extraSuffix =
          new PageId("paged_block_1234567890abcdef_size_0123cafebabedead.parquet", 0);
      assertThrows(IllegalArgumentException.class, () -> BlockPageId.downcast(extraSuffix));
      PageId negativeBlockSize = new PageId("paged_block_1234567890abcdef_size_cafebabedead0123", 0);
      assertThrows(IllegalArgumentException.class, () -> BlockPageId.downcast(negativeBlockSize));
    }
  
    private static class MoreFieldsPageId extends PageId {
      private final long mSomeField;
  
      public MoreFieldsPageId(String fileId, long pageIndex, long value) {
        super(fileId, pageIndex);
        mSomeField = value;
      }
  
      @Override
      public int hashCode() {
        return Objects.hash(super.hashCode(), mSomeField);
      }
  
      @Override
      public boolean equals(Object o) {
        if (this == o) {
          return true;
        }
        if (o == null || getClass() != o.getClass()) {
          return false;
        }
        if (!super.equals(o)) {
          return false;
        }
        MoreFieldsPageId that = (MoreFieldsPageId) o;
        return mSomeField == that.mSomeField;
      }
    }
  }
  