main

square/leakcanary

Last updated at: 29/12/2023 09:38

SortedBytesMapTest.kt

TLDR

This file contains the test cases for the UnsortedByteEntries class in the shark package. The test cases verify the functionality of various methods and properties of the UnsortedByteEntries class.

Methods

writeAndReadLongValue

This method tests the functionality of writing and reading a long value to the UnsortedByteEntries object. It checks if the values are written and read correctly.

writeAndReadTruncatedLongValue

This method tests the functionality of writing and reading a truncated long value to the UnsortedByteEntries object. It checks if the values are written and read correctly.

fourEntriesWithLongKey1ByteValueSorted

This method tests the functionality of the UnsortedByteEntries object with four entries, where the key is a long and the value is a one-byte array. It checks if the entries are sorted correctly.

fourEntriesWithLongKey3ByteValueSorted

This method tests the functionality of the UnsortedByteEntries object with four entries, where the key is a long and the value is a three-byte array. It checks if the entries are sorted correctly.

largeRandomArrayIntKey3ByteValueSorted

This method tests the functionality of the UnsortedByteEntries object with a large random array, where the key is an integer and the value is a three-byte array. It checks if the entries are sorted correctly.

largeRandomArrayLongKey3ByteValueSorted

This method tests the functionality of the UnsortedByteEntries object with a large random array, where the key is a long and the value is a three-byte array. It checks if the entries are sorted correctly.

largeRandomArrayLongKey7ByteValueSorted

This method tests the functionality of the UnsortedByteEntries object with a large random array, where the key is a long and the value is a seven-byte array. It checks if the entries are sorted correctly.

sortAndCompare

This private method is used by other test methods to sort and compare the entries in the UnsortedByteEntries object with the source entry array. It takes the number of bytes per value, the flag indicating whether the identifiers are long, and the source entry array as parameters.

Classes

SortedBytesMapTest

This class contains the test cases for the UnsortedByteEntries class. It includes methods to test different functionalities of the UnsortedByteEntries class.

Entry

This inner class represents an entry in the UnsortedByteEntries object. It has properties for the key and the value of the entry. It also implements the Comparable interface for comparing entries based on their keys. It overrides the equals and toString methods.

package shark

import kotlin.random.Random
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import shark.internal.UnsortedByteEntries

class SortedBytesMapTest {

  @Test fun writeAndReadLongValue() {
    val unsortedEntries = UnsortedByteEntries(bytesPerValue = 8, longIdentifiers = false)
    unsortedEntries.append(1)
      .apply {
        writeLong(Long.MIN_VALUE)
      }

    val array = unsortedEntries.moveToSortedMap()[1]!!
    assertThat(array.readLong()).isEqualTo(Long.MIN_VALUE)
  }

  @Test fun writeAndReadTruncatedLongValue() {
    val maxUnsigned3Bytes = 0x00000FFFL
    val unsortedMap = UnsortedByteEntries(bytesPerValue = 3, longIdentifiers = false)
    unsortedMap.append(1)
      .apply {
        writeTruncatedLong(maxUnsigned3Bytes, 3)
      }

    val array = unsortedMap.moveToSortedMap()[1]!!
    assertThat(array.readTruncatedLong(3)).isEqualTo(maxUnsigned3Bytes)
  }

  @Test fun fourEntriesWithLongKey1ByteValueSorted() {
    val unsortedEntries = UnsortedByteEntries(bytesPerValue = 1, longIdentifiers = true)
    unsortedEntries.append(42)
      .apply {
        writeByte(4)
      }
    unsortedEntries.append(0)
      .apply {
        writeByte(3)
      }
    unsortedEntries.append(3)
      .apply {
        writeByte(20)
      }
    unsortedEntries.append(Long.MAX_VALUE)
      .apply {
        writeByte(127)
      }
    val sortedEntries = unsortedEntries.moveToSortedMap()
      .entrySequence()
      .toList()

    assertThat(sortedEntries.map { it.first }).containsExactly(0, 3, 42, Long.MAX_VALUE)
    assertThat(
      sortedEntries.map {
        byteArrayOf(
          it.second.readByte()
        )
      }).containsExactly(
      byteArrayOf(3), byteArrayOf(20), byteArrayOf(4),
      byteArrayOf(127)
    )
  }

  @Test fun fourEntriesWithLongKey3ByteValueSorted() {
    val unsortedMap = UnsortedByteEntries(bytesPerValue = 3, longIdentifiers = true)
    unsortedMap.append(42)
      .apply {
        writeByte(4)
        writeByte(2)
        writeByte(0)
      }
    unsortedMap.append(0)
      .apply {
        writeByte(3)
        writeByte(2)
        writeByte(1)
      }
    unsortedMap.append(3)
      .apply {
        writeByte(20)
        writeByte(52)
        writeByte(-17)
      }
    unsortedMap.append(Long.MAX_VALUE)
      .apply {
        writeByte(127)
        writeByte(0)
        writeByte(-128)
      }
    val sortedEntries = unsortedMap.moveToSortedMap()
      .entrySequence()
      .toList()

    assertThat(sortedEntries.map { it.first }).containsExactly(0, 3, 42, Long.MAX_VALUE)
    assertThat(
      sortedEntries.map {
        byteArrayOf(
          it.second.readByte(), it.second.readByte(), it.second.readByte()
        )
      }).containsExactly(
      byteArrayOf(3, 2, 1), byteArrayOf(20, 52, -17), byteArrayOf(4, 2, 0),
      byteArrayOf(127, 0, -128)
    )
  }

  class Entry(
    val key: Long,
    val value: ByteArray
  ) : Comparable<Entry> {
    override fun compareTo(other: Entry): Int = key.compareTo(other.key)
    override fun equals(other: Any?): Boolean {
      if (this === other) return true
      if (javaClass != other?.javaClass) return false

      other as Entry

      if (key != other.key) return false
      if (!value.contentEquals(other.value)) return false

      return true
    }

    override fun toString(): String {
      return "Entry(key=$key, value=${value.contentToString()})"
    }
  }

  @Test fun largeRandomArrayIntKey3ByteValueSorted() {
    val random = Random(Long.MAX_VALUE)

    val bytesPerValue = 3
    val longIdentifiers = false

    val sourceEntryArray = Array(10000) {
      Entry(random.nextInt().toLong(), random.nextBytes(bytesPerValue))
    }

    sortAndCompare(bytesPerValue, longIdentifiers, sourceEntryArray)
  }

  @Test fun largeRandomArrayLongKey3ByteValueSorted() {
    val random = Random(42)

    val bytesPerValue = 3
    val longIdentifiers = true

    val sourceEntryArray = Array(10000) {
      Entry(random.nextLong(), random.nextBytes(bytesPerValue))
    }

    sortAndCompare(bytesPerValue, longIdentifiers, sourceEntryArray)
  }

  @Test fun largeRandomArrayLongKey7ByteValueSorted() {
    val random = Random(Long.MIN_VALUE)

    val bytesPerValue = 7
    val longIdentifiers = true

    val sourceEntryArray = Array(10000) {
      Entry(random.nextLong(), random.nextBytes(bytesPerValue))
    }

    sortAndCompare(bytesPerValue, longIdentifiers, sourceEntryArray)
  }

  private fun sortAndCompare(
    bytesPerValue: Int,
    longIdentifiers: Boolean,
    sourceEntryArray: Array<Entry>
  ) {
    val unsortedEntries =
      UnsortedByteEntries(bytesPerValue = bytesPerValue, longIdentifiers = longIdentifiers)

    sourceEntryArray.forEach { entry ->
      val subArray = unsortedEntries.append(entry.key)
      entry.value.forEach { subArray.writeByte(it) }
    }

    val sortedMap = unsortedEntries.moveToSortedMap()
    sourceEntryArray.sort()

    val sortedEntryArray = sortedMap.entrySequence()
      .map {
        val key = it.first
        val value = it.second

        val bytes = mutableListOf<Byte>()
        for (i in 0 until bytesPerValue) {
          bytes += value.readByte()
        }
        Entry(key, bytes.toByteArray())
      }
      .toList()
      .toTypedArray()

    assertThat(sortedEntryArray).isEqualTo(sourceEntryArray)
  }
}