diceware: add Die class and tests

This commit is contained in:
Harsh Shandilya 2021-12-09 23:23:46 +05:30
parent 67f8eb8404
commit 16392b7581
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
4 changed files with 102 additions and 0 deletions

View file

@ -0,0 +1,10 @@
public final class dev/msfjarvis/aps/passgen/diceware/Die {
public fun <init> (ILdev/msfjarvis/aps/passgen/diceware/RandomIntGenerator;)V
public final fun roll ()I
public final fun rollMultiple (I)I
}
public abstract interface class dev/msfjarvis/aps/passgen/diceware/RandomIntGenerator {
public abstract fun get (Lkotlin/ranges/IntRange;)I
}

View file

@ -0,0 +1,30 @@
/*
* Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
package dev.msfjarvis.aps.passgen.diceware
import javax.inject.Inject
/** Basic implementation of a die with configurable number of sides. */
public class Die
@Inject
constructor(
private val sides: Int,
private val random: RandomIntGenerator,
) {
/** Roll the die to return a single number. */
public fun roll(): Int {
return random.get(1..sides)
}
/**
* Roll the die multiple times, concatenating each result to obtain a number with [iterations]
* digits.
*/
public fun rollMultiple(iterations: Int): Int {
return StringBuilder().apply { repeat(iterations) { append(roll()) } }.toString().toInt()
}
}

View file

@ -0,0 +1,15 @@
/*
* Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
package dev.msfjarvis.aps.passgen.diceware
/**
* SAM interface that takes in an [IntRange] and returns a randomly chosen [Int] within its bounds.
* This is used as a replacement for [kotlin.random.Random] since there is no CSPRNG-backed
* implementation of it in the Kotlin stdlib.
*/
public fun interface RandomIntGenerator {
public fun get(range: IntRange): Int
}

View file

@ -0,0 +1,47 @@
/*
* Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
package dev.msfjarvis.aps.passgen.diceware
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
class DieTest {
/** Pre-seeded [Random] instance to ensure tests are deterministic. */
private val random = Random(1_00_000)
private val intGenerator = RandomIntGenerator { it.random(random) }
@Test
fun test_one_roll() {
val die = Die(6, intGenerator)
assertEquals(5, die.roll())
}
@Test
fun test_multiple_rolls() {
val die = Die(6, intGenerator)
assertEquals(526242, die.rollMultiple(6))
}
@Test
fun test_consecutive_rolls() {
val die = Die(6, intGenerator)
assertEquals(5, die.roll())
assertEquals(2, die.roll())
assertEquals(6, die.roll())
assertEquals(2, die.roll())
assertEquals(4, die.roll())
assertEquals(2, die.roll())
}
@Test
fun test_100_sides() {
val die = Die(100, intGenerator)
assertEquals(67, die.roll())
}
}