Open-source multiplayer game server compatible with the RuneScape client https://www.openrs2.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
openrs2/cache/src/test/kotlin/org/openrs2/cache/Js5IndexTest.kt

415 lines
11 KiB

package org.openrs2.cache
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.ByteBufUtil
import io.netty.buffer.Unpooled
import org.openrs2.buffer.use
import org.openrs2.buffer.wrappedBuffer
import org.openrs2.util.krHashCode
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
import kotlin.test.assertNull
import kotlin.test.assertTrue
object Js5IndexTest {
private val emptyIndex = Js5Index(Js5Protocol.ORIGINAL)
private val versionedIndex = Js5Index(Js5Protocol.VERSIONED, version = 0x12345678)
private val noFlagsIndex = Js5Index(Js5Protocol.ORIGINAL).apply {
val group0 = createOrGet(0)
group0.checksum = 0x01234567
group0.version = 0
group0.createOrGet(0)
val group1 = createOrGet(1)
group1.checksum = 0x89ABCDEF.toInt()
group1.version = 10
val group2 = createOrGet(3)
group2.checksum = 0xAAAA5555.toInt()
group2.version = 20
group2.createOrGet(1)
group2.createOrGet(3)
}
private val namedIndex = Js5Index(Js5Protocol.ORIGINAL, hasNames = true).apply {
val group0 = createOrGet("hello")
group0.checksum = 0x01234567
group0.version = 0x89ABCDEF.toInt()
group0.createOrGet("world")
}
private val smartIndex = Js5Index(Js5Protocol.SMART).apply {
val group0 = createOrGet(0)
group0.checksum = 0x01234567
group0.version = 0x89ABCDEF.toInt()
group0.createOrGet(0)
group0.createOrGet(100000)
val group1 = createOrGet(100000)
group1.checksum = 0xAAAA5555.toInt()
group1.version = 0x5555AAAA
}
private val digestIndex = Js5Index(Js5Protocol.ORIGINAL, hasDigests = true).apply {
val group = createOrGet(0)
group.checksum = 0x01234567
group.version = 0x89ABCDEF.toInt()
group.digest = ByteBufUtil.decodeHexDump(
"19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A7" +
"3E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3"
)
}
private val nullDigestIndex = Js5Index(Js5Protocol.ORIGINAL, hasDigests = true).apply {
val group = createOrGet(0)
group.checksum = 0x01234567
group.version = 0x89ABCDEF.toInt()
group.digest = null
}
private val lengthsIndex = Js5Index(Js5Protocol.ORIGINAL, hasLengths = true).apply {
val group = createOrGet(0)
group.checksum = 0x01234567
group.version = 0x89ABCDEF.toInt()
group.length = 1000
group.uncompressedLength = 2000
}
private val uncompressedChecksumIndex = Js5Index(Js5Protocol.ORIGINAL, hasUncompressedChecksums = true).apply {
val group = createOrGet(0)
group.checksum = 0x01234567
group.version = 0x89ABCDEF.toInt()
group.uncompressedChecksum = 0xAAAA5555.toInt()
}
private val allFlagsIndex = Js5Index(
Js5Protocol.ORIGINAL,
hasNames = true,
hasDigests = true,
hasLengths = true,
hasUncompressedChecksums = true
).apply {
val group = createOrGet("hello")
group.checksum = 0x01234567
group.version = 0x89ABCDEF.toInt()
group.digest = ByteBufUtil.decodeHexDump(
"19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A7" +
"3E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3"
)
group.length = 1000
group.uncompressedLength = 2000
group.uncompressedChecksum = 0xAAAA5555.toInt()
group.createOrGet("world")
}
@Test
fun testReadEmpty() {
read("empty.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(emptyIndex, index)
}
}
@Test
fun testWriteEmpty() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
emptyIndex.write(actual)
read("empty.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testReadUnsupportedProtocol() {
wrappedBuffer(4).use { buf ->
assertFailsWith<IllegalArgumentException> {
Js5Index.read(buf)
}
}
wrappedBuffer(8).use { buf ->
assertFailsWith<IllegalArgumentException> {
Js5Index.read(buf)
}
}
}
@Test
fun testReadVersioned() {
read("versioned.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(versionedIndex, index)
}
}
@Test
fun testWriteVersioned() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
versionedIndex.write(actual)
read("versioned.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testReadNoFlags() {
read("no-flags.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(noFlagsIndex, index)
}
}
@Test
fun testWriteNoFlags() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
noFlagsIndex.write(actual)
read("no-flags.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testReadNamed() {
read("named.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(namedIndex, index)
}
}
@Test
fun testWriteNamed() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
namedIndex.write(actual)
read("named.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testReadSmart() {
read("smart.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(smartIndex, index)
}
}
@Test
fun testWriteSmart() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
smartIndex.write(actual)
read("smart.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testWriteNonSmartOutOfRange() {
val index = Js5Index(Js5Protocol.ORIGINAL)
index.createOrGet(65536)
ByteBufAllocator.DEFAULT.buffer().use { buf ->
assertFailsWith<IllegalStateException> {
index.write(buf)
}
}
}
@Test
fun testReadDigest() {
read("digest.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(digestIndex, index)
}
}
@Test
fun testWriteDigest() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
digestIndex.write(actual)
read("digest.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testWriteNullDigest() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
nullDigestIndex.write(actual)
read("null-digest.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testReadLengths() {
read("lengths.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(lengthsIndex, index)
}
}
@Test
fun testWriteLengths() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
lengthsIndex.write(actual)
read("lengths.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testReadUncompressedChecksum() {
read("uncompressed-checksum.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(uncompressedChecksumIndex, index)
}
}
@Test
fun testWriteUncompressedChecksum() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
uncompressedChecksumIndex.write(actual)
read("uncompressed-checksum.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testReadAllFlags() {
read("all-flags.dat").use { buf ->
val index = Js5Index.read(buf)
assertFalse(buf.isReadable)
assertEquals(allFlagsIndex, index)
}
}
@Test
fun testWriteAllFlags() {
ByteBufAllocator.DEFAULT.buffer().use { actual ->
allFlagsIndex.write(actual)
read("all-flags.dat").use { expected ->
assertEquals(expected, actual)
}
}
}
@Test
fun testRenameGroup() {
val index = Js5Index(Js5Protocol.ORIGINAL)
val group = index.createOrGet(0)
assertEquals(-1, group.nameHash)
assertNull(index["hello"])
group.setName("hello")
assertEquals("hello".krHashCode(), group.nameHash)
assertEquals(group, index["hello"])
group.clearName()
assertEquals(-1, group.nameHash)
assertNull(index["hello"])
}
@Test
fun testRenameFile() {
val index = Js5Index(Js5Protocol.ORIGINAL)
val group = index.createOrGet(0)
val file = group.createOrGet(0)
assertEquals(-1, file.nameHash)
assertNull(group["hello"])
file.setName("hello")
assertEquals("hello".krHashCode(), file.nameHash)
assertEquals(file, group["hello"])
file.clearName()
assertEquals(-1, file.nameHash)
assertNull(group["hello"])
}
@Test
fun testRemoveGroup() {
val index = Js5Index(Js5Protocol.ORIGINAL)
val group = index.createOrGet(0)
assertEquals(1, index.size)
assertEquals(1, index.capacity)
assertTrue(0 in index)
assertEquals(group, index[0])
group.remove()
assertEquals(0, index.size)
assertEquals(0, index.capacity)
assertFalse(0 in index)
assertNull(index[0])
group.remove()
assertEquals(0, index.size)
assertEquals(0, index.capacity)
assertFalse(0 in index)
assertNull(index[0])
}
@Test
fun testRemoveFile() {
val index = Js5Index(Js5Protocol.ORIGINAL)
val group = index.createOrGet(0)
val file = group.createOrGet(0)
assertEquals(1, group.size)
assertEquals(1, group.capacity)
assertTrue(0 in group)
assertEquals(file, group[0])
file.remove()
assertEquals(0, group.size)
assertEquals(0, group.capacity)
assertFalse(0 in group)
assertNull(group[0])
file.remove()
assertEquals(0, group.size)
assertEquals(0, group.capacity)
assertFalse(0 in group)
assertNull(group[0])
}
private fun read(name: String): ByteBuf {
Js5IndexTest::class.java.getResourceAsStream("index/$name").use { input ->
return Unpooled.wrappedBuffer(input.readAllBytes())
}
}
}