mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-08-30 22:05:19 +00:00
diceware: add Die class and tests
This commit is contained in:
10
passgen/diceware/api/diceware.api
Normal file
10
passgen/diceware/api/diceware.api
Normal 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
|
||||||
|
}
|
||||||
|
|
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
@@ -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
|
||||||
|
}
|
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user