1package com.peachpasswords.vault23import java.io.File4import org.junit.Assert.assertEquals5import org.junit.Assert.assertFalse6import org.junit.Assert.assertNull7import org.junit.Assert.assertTrue8import org.junit.Test910class PinUnlockStoreTest {11 @Test fun pin_policy_requires_four_to_twelve_ascii_digits() {12 assertEquals("PIN must be 4–12 digits", pinValidationError("123"))13 assertEquals("PIN must contain digits only", pinValidationError("12a4"))14 assertNull(pinValidationError("1234"))15 assertNull(pinValidationError("123456789012"))16 }1718 @Test fun pin_store_uses_hardware_envelope_and_limited_use_attempt_gates() {19 val relativePath = "app/src/main/java/com/peachpasswords/vault/PinUnlockStore.kt"20 val source = (File(relativePath).takeIf { it.exists() } ?: File("../$relativePath")).readText()2122 assertTrue(source.contains("AndroidKeyStore"))23 assertTrue(source.contains("KeyProperties.KEY_ALGORITHM_HMAC_SHA256"))24 assertTrue(source.contains("setMaxUsageCount(1)"))25 assertTrue(source.contains("probeLimitedUseEnforcement()"))26 assertTrue(source.contains("const val FORMAT_VERSION = 3"))27 assertTrue(source.contains("setIsStrongBoxBacked(true)"))28 assertTrue(source.contains("StrongBoxUnavailableException"))29 assertTrue(source.contains("KeyInfo"))30 assertFalse(source.contains("VaultCrypto.encrypt(vaultKey, pinKey"))31 assertFalse(source.contains("wrap(vaultKey, pinKey)"))32 }33}