~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain-android

1 collaborator
0
1
main
62 lines · 2.1 KB Raw History
package social.grain

import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import social.grain.util.Tid

/**
 * TIDs are the reason a publish is safe to retry, so their two load-bearing
 * properties — valid syntax and strict monotonicity — are worth pinning down.
 */
class TidTest {

    @Test
    fun `next produces a valid 13-character record key`() {
        repeat(100) {
            val tid = Tid.next()
            assertEquals(13, tid.length)
            assertTrue("'$tid' should be a valid TID", Tid.isValid(tid))
        }
    }

    @Test
    fun `successive TIDs strictly increase even within one clock tick`() {
        // The whole point of the lastMicros bump: two calls in the same
        // millisecond must still sort in the order they were issued.
        val tids = List(1_000) { Tid.next() }
        for (index in 1 until tids.size) {
            assertTrue(
                "${tids[index]} should sort after ${tids[index - 1]}",
                tids[index] > tids[index - 1],
            )
        }
        assertEquals(tids.size, tids.toSet().size)
    }

    @Test
    fun `encode packs micros and clock id into sortable base32`() {
        val earlier = Tid.encode(micros = 1_700_000_000_000_000, clockId = 5)
        val later = Tid.encode(micros = 1_700_000_000_000_001, clockId = 5)
        assertTrue(later > earlier)
        assertNotEquals(earlier, later)
        assertTrue(Tid.isValid(earlier))
    }

    @Test
    fun `encode never sets the high bit`() {
        // A leading character above 'j' would mean the 64-bit value's top bit
        // is set, which the TID spec forbids.
        val extreme = Tid.encode(micros = 0x1FFFFFFFFFFFFF, clockId = 0x3FF)
        assertTrue("Leading char '${extreme.first()}' out of range", Tid.isValid(extreme))
    }

    @Test
    fun `isValid rejects malformed keys`() {
        assertTrue(!Tid.isValid(""))
        assertTrue(!Tid.isValid("short"))
        assertTrue(!Tid.isValid("zzzzzzzzzzzzz")) // leading char too high
        assertTrue(!Tid.isValid("3aaaaaaaaaaa1")) // '1' is not in the alphabet
    }
}