package org.openrs2.cache import io.netty.buffer.ByteBufAllocator import io.netty.buffer.ByteBufUtil import io.netty.buffer.Unpooled import org.openrs2.buffer.use import org.openrs2.crypto.Rsa import java.nio.file.Path import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith class Js5MasterIndexTest { @Test fun testCreateOriginal() { val index = Store.open(ROOT.resolve("original")).use { store -> Js5MasterIndex.create(store) } assertEquals( Js5MasterIndex( MasterIndexFormat.ORIGINAL, mutableListOf( Js5MasterIndex.Entry( 0, 609698396, ByteBufUtil.decodeHexDump( "0e1a2b93c80a41c7ad2a985dff707a6a8ff82e229cbc468f04191198920955a1" + "4b3d7eab77a17faf99208dee5b44afb789962ad79f230b3b59106a0af892219c" ) ), ) ), index ) } @Test fun testCreateVersioned() { val index = Store.open(ROOT.resolve("versioned")).use { store -> Js5MasterIndex.create(store) } assertEquals( Js5MasterIndex( MasterIndexFormat.VERSIONED, mutableListOf( Js5MasterIndex.Entry( 0, 609698396, ByteBufUtil.decodeHexDump( "0e1a2b93c80a41c7ad2a985dff707a6a8ff82e229cbc468f04191198920955a1" + "4b3d7eab77a17faf99208dee5b44afb789962ad79f230b3b59106a0af892219c" ) ), Js5MasterIndex.Entry( 0x12345678, 78747481, ByteBufUtil.decodeHexDump( "180ff4ad371f56d4a90d81e0b69b23836cd9b101b828f18b7e6d232c4d302539" + "638eb2e9259957645aae294f09b2d669c93dbbfc0d8359f1b232ae468f678ca1" ) ), Js5MasterIndex.Entry(0, 0, null), Js5MasterIndex.Entry( 0x9ABCDEF0.toInt(), -456081154, ByteBufUtil.decodeHexDump( "972003261b7628525346e0052567662e5695147ad710f877b63b9ab53b3f6650" + "ca003035fde4398b2ef73a60e4b13798aa597a30c1bf0a13c0cd412394af5f96" ) ), Js5MasterIndex.Entry(0, 0, null), Js5MasterIndex.Entry(0, 0, null), Js5MasterIndex.Entry( 0xAA55AA55.toInt(), 186613982, ByteBufUtil.decodeHexDump( "d50a6e9abd3b5269606304dc2769cbc8618e1ae6ff705291c0dfcc374e450dd2" + "5f1be5f1d5459651d22d3e87ef0a1c69be7807f661cd001be24a6609f6d57916" ) ) ) ), index ) } @Test fun testCreateWhirlpool() { val index = Store.open(ROOT.resolve("whirlpool")).use { store -> Js5MasterIndex.create(store) } assertEquals( Js5MasterIndex( MasterIndexFormat.WHIRLPOOL, mutableListOf( Js5MasterIndex.Entry( 0, 668177970, ByteBufUtil.decodeHexDump( "2faa83116e1d1719d5db15f128eb57f62afbf0207c47bced3f558ec17645d138" + "72f4fb9b0e36a5f6f5d30e1295b3fa49556dfd0819cb5137f3b69f64155f3fb7" ) ), Js5MasterIndex.Entry( 0, 1925442845, ByteBufUtil.decodeHexDump( "fcc45b0ab6d0067889e44de0004bcbb6cc538aff8f80edf1b49b583cedd73fea" + "937ae6990235257fe8aa35c44d35450c13e670711337ee5116957cd98cc27985" ) ) ) ), index ) } @Test fun testReadOriginal() { Unpooled.wrappedBuffer(encodedOriginal).use { buf -> val index = Js5MasterIndex.read(buf, MasterIndexFormat.ORIGINAL) assertEquals(decodedOriginal, index) } assertFailsWith { Unpooled.wrappedBuffer(byteArrayOf(0)).use { buf -> Js5MasterIndex.read(buf, MasterIndexFormat.ORIGINAL) } } } @Test fun testWriteOriginal() { ByteBufAllocator.DEFAULT.buffer().use { actual -> decodedOriginal.write(actual) Unpooled.wrappedBuffer(encodedOriginal).use { expected -> assertEquals(expected, actual) } } } @Test fun testReadVersioned() { Unpooled.wrappedBuffer(encodedVersioned).use { buf -> val index = Js5MasterIndex.read(buf, MasterIndexFormat.VERSIONED) assertEquals(decodedVersioned, index) } assertFailsWith { Unpooled.wrappedBuffer(byteArrayOf(0, 0, 0, 0)).use { buf -> Js5MasterIndex.read(buf, MasterIndexFormat.VERSIONED) } } } @Test fun testWriteVersioned() { ByteBufAllocator.DEFAULT.buffer().use { actual -> decodedVersioned.write(actual) Unpooled.wrappedBuffer(encodedVersioned).use { expected -> assertEquals(expected, actual) } } } @Test fun testReadWhirlpool() { Unpooled.wrappedBuffer(encodedWhirlpool).use { buf -> val index = Js5MasterIndex.read(buf, MasterIndexFormat.WHIRLPOOL) assertEquals(decodedWhirlpool, index) } } @Test fun testReadWhirlpoolInvalidSignature() { Unpooled.copiedBuffer(encodedWhirlpool).use { buf -> val lastIndex = buf.writerIndex() - 1 buf.setByte(lastIndex, buf.getByte(lastIndex).toInt().inv()) assertFailsWith { Js5MasterIndex.read(buf, MasterIndexFormat.WHIRLPOOL) } } } @Test fun testReadWhirlpoolInvalidSignatureLength() { Unpooled.wrappedBuffer(encodedWhirlpool, 0, encodedWhirlpool.size - 1).use { buf -> assertFailsWith { Js5MasterIndex.read(buf, MasterIndexFormat.WHIRLPOOL) } } } @Test fun testWriteWhirlpool() { ByteBufAllocator.DEFAULT.buffer().use { actual -> decodedWhirlpool.write(actual) Unpooled.wrappedBuffer(encodedWhirlpool).use { expected -> assertEquals(expected, actual) } } } @Test fun testWriteWhirlpoolNullDigest() { ByteBufAllocator.DEFAULT.buffer().use { actual -> decodedWhirlpoolNullDigest.write(actual) Unpooled.wrappedBuffer(encodedWhirlpoolNullDigest).use { expected -> assertEquals(expected, actual) } } } @Test fun testReadSigned() { Unpooled.wrappedBuffer(encodedSigned).use { buf -> val index = Js5MasterIndex.read(buf, MasterIndexFormat.WHIRLPOOL, PUBLIC_KEY) assertEquals(decodedWhirlpool, index) } } @Test fun testReadSignedInvalidSignature() { Unpooled.copiedBuffer(encodedSigned).use { buf -> val lastIndex = buf.writerIndex() - 1 buf.setByte(lastIndex, buf.getByte(lastIndex).toInt().inv()) assertFailsWith { Js5MasterIndex.read(buf, MasterIndexFormat.WHIRLPOOL, PUBLIC_KEY) } } } @Test fun testReadSignedInvalidSignatureLength() { Unpooled.wrappedBuffer(encodedSigned, 0, encodedSigned.size - 1).use { buf -> assertFailsWith { Js5MasterIndex.read(buf, MasterIndexFormat.WHIRLPOOL, PUBLIC_KEY) } } } @Test fun testWriteSigned() { ByteBufAllocator.DEFAULT.buffer().use { actual -> decodedWhirlpool.write(actual, PRIVATE_KEY) Unpooled.wrappedBuffer(encodedSigned).use { expected -> assertEquals(expected, actual) } } } private companion object { private val ROOT = Path.of(FlatFileStoreTest::class.java.getResource("master-index").toURI()) private val PRIVATE_KEY = Rsa.readPrivateKey(ROOT.resolve("private.key")) private val PUBLIC_KEY = Rsa.readPublicKey(ROOT.resolve("public.key")) private val encodedOriginal = ByteBufUtil.decodeHexDump("000000010000000300000005") private val decodedOriginal = Js5MasterIndex( MasterIndexFormat.ORIGINAL, mutableListOf( Js5MasterIndex.Entry(0, 1, null), Js5MasterIndex.Entry(0, 3, null), Js5MasterIndex.Entry(0, 5, null) ) ) private val encodedVersioned = ByteBufUtil.decodeHexDump("000000010000000000000003000000020000000500000004") private val decodedVersioned = Js5MasterIndex( MasterIndexFormat.VERSIONED, mutableListOf( Js5MasterIndex.Entry(0, 1, null), Js5MasterIndex.Entry(2, 3, null), Js5MasterIndex.Entry(4, 5, null) ) ) private val encodedWhirlpool = ByteBufUtil.decodeHexDump( "01" + "89abcdef" + "01234567" + "0e1a2b93c80a41c7ad2a985dff707a6a8ff82e229cbc468f04191198920955a1" + "4b3d7eab77a17faf99208dee5b44afb789962ad79f230b3b59106a0af892219c" + "0a" + "ee8f66a2ce0b07de4d2b792eed26ae7a6c307b763891d085c63ea55b4c003bc0" + "b3ecb77cc1a8f9ccd53c405b3264e598820b4940f630ff079a9feb950f639671" ) private val decodedWhirlpool = Js5MasterIndex( MasterIndexFormat.WHIRLPOOL, mutableListOf( Js5MasterIndex.Entry( 0x01234567, 0x89ABCDEF.toInt(), ByteBufUtil.decodeHexDump( "0e1a2b93c80a41c7ad2a985dff707a6a8ff82e229cbc468f04191198920955a1" + "4b3d7eab77a17faf99208dee5b44afb789962ad79f230b3b59106a0af892219c" ) ) ) ) private val encodedWhirlpoolNullDigest = ByteBufUtil.decodeHexDump( "01" + "89abcdef" + "01234567" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0a" + "4a0e22540fb0a9bc06fe84bfb35f9281ba9fbd30288c3375c508ad741c4d4491" + "8a65765bc2dce9d67029be79bd544f96055a41d725c080bc5b85a48b5aae6e4d" ) private val decodedWhirlpoolNullDigest = Js5MasterIndex( MasterIndexFormat.WHIRLPOOL, mutableListOf( Js5MasterIndex.Entry(0x01234567, 0x89ABCDEF.toInt(), null) ) ) private val encodedSigned = ByteBufUtil.decodeHexDump( "01" + "89abcdef" + "01234567" + "0e1a2b93c80a41c7ad2a985dff707a6a8ff82e229cbc468f04191198920955a1" + "4b3d7eab77a17faf99208dee5b44afb789962ad79f230b3b59106a0af892219c" + "2134b1e637d4c9f3b7bdd446ad40cedb6d824cfb48f937ae0d6e2ba3977881ea" + "ed02adae179ed89cea56e98772186bb569bb24a4951e441716df0d5d7199c088" + "28974d43c3644e74bf29ec1435e425f6cb05aca14a84163c5b46b6e6a9362f22" + "4f69f4a5888b3fe7aec0141da25b17c7f65069eed59f3be134fa1ade4e191b41" + "d561447446cd1cc4d11e6499c49e00066173908491d8d2ff282aefa86e6c6b15" + "dceb437d0436b6195ef60d4128e1e0184bf6929b73abd1a8aa2a047e3cb90d03" + "57707ce3f4f5a7af8471eda5c0c0748454a9cbb48c25ebe4e7fd94e3881b6461" + "d06e2bce128dc96decb537b8e9611591d445d7dfd3701d25ac05f8d091581aef" ) } }