Expand OTP and PasswordEntry tests (#968)
(cherry picked from commit e3cf73885c
)
This commit is contained in:
parent
5c28fe9817
commit
35a8e8b42c
3 changed files with 111 additions and 3 deletions
18
.github/workflows/pull_request.yml
vendored
18
.github/workflows/pull_request.yml
vendored
|
@ -69,8 +69,8 @@ jobs:
|
|||
if: ${{ steps.service-changed.outputs.result == 'true' }}
|
||||
run: ./gradlew test${{ matrix.variant }} lint${{ matrix.variant}} -Dpre-dex=false
|
||||
|
||||
- name: Run instrumentation tests
|
||||
if: ${{ steps.service-changed.outputs.result == 'true' }}
|
||||
- name: Run instrumentation tests on free flavor
|
||||
if: ${{ steps.service-changed.outputs.result == 'true' && matrix.variant == 'freeRelease' }}
|
||||
uses: reactivecircus/android-emulator-runner@v2.11.0
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
|
@ -79,4 +79,16 @@ jobs:
|
|||
adb shell settings put global animator_duration_scale 0
|
||||
adb shell settings put global transition_animation_scale 0
|
||||
adb shell settings put global window_animation_scale 0
|
||||
./gradlew connectedCheck
|
||||
./gradlew :app:connectedFreeDebugAndroidTest
|
||||
|
||||
- name: Run instrumentation tests on nonFree flavor
|
||||
if: ${{ steps.service-changed.outputs.result == 'true' && matrix.variant == 'nonFreeRelease' }}
|
||||
uses: reactivecircus/android-emulator-runner@v2.11.0
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
target: default
|
||||
script: |
|
||||
adb shell settings put global animator_duration_scale 0
|
||||
adb shell settings put global transition_animation_scale 0
|
||||
adb shell settings put global window_animation_scale 0
|
||||
./gradlew :app:connectedNonFreeDebugAndroidTest
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved.
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
package com.zeapo.pwdstore.model
|
||||
|
||||
import com.zeapo.pwdstore.utils.Otp
|
||||
import com.zeapo.pwdstore.utils.UriTotpFinder
|
||||
import java.util.Date
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class PasswordEntryAndroidTest {
|
||||
|
||||
private fun makeEntry(content: String) = PasswordEntry(content, UriTotpFinder())
|
||||
|
||||
@Test fun testGetPassword() {
|
||||
assertEquals("fooooo", makeEntry("fooooo\nbla\n").password)
|
||||
assertEquals("fooooo", makeEntry("fooooo\nbla").password)
|
||||
assertEquals("fooooo", makeEntry("fooooo\n").password)
|
||||
assertEquals("fooooo", makeEntry("fooooo").password)
|
||||
assertEquals("", makeEntry("\nblubb\n").password)
|
||||
assertEquals("", makeEntry("\nblubb").password)
|
||||
assertEquals("", makeEntry("\n").password)
|
||||
assertEquals("", makeEntry("").password)
|
||||
}
|
||||
|
||||
@Test fun testGetExtraContent() {
|
||||
assertEquals("bla\n", makeEntry("fooooo\nbla\n").extraContent)
|
||||
assertEquals("bla", makeEntry("fooooo\nbla").extraContent)
|
||||
assertEquals("", makeEntry("fooooo\n").extraContent)
|
||||
assertEquals("", makeEntry("fooooo").extraContent)
|
||||
assertEquals("blubb\n", makeEntry("\nblubb\n").extraContent)
|
||||
assertEquals("blubb", makeEntry("\nblubb").extraContent)
|
||||
assertEquals("", makeEntry("\n").extraContent)
|
||||
assertEquals("", makeEntry("").extraContent)
|
||||
}
|
||||
|
||||
@Test fun testGetUsername() {
|
||||
for (field in PasswordEntry.USERNAME_FIELDS) {
|
||||
assertEquals("username", makeEntry("\n$field username").username)
|
||||
assertEquals("username", makeEntry("\n${field.toUpperCase()} username").username)
|
||||
}
|
||||
assertEquals(
|
||||
"username",
|
||||
makeEntry("secret\nextra\nlogin: username\ncontent\n").username)
|
||||
assertEquals(
|
||||
"username",
|
||||
makeEntry("\nextra\nusername: username\ncontent\n").username)
|
||||
assertEquals(
|
||||
"username", makeEntry("\nUSERNaMe: username\ncontent\n").username)
|
||||
assertEquals("username", makeEntry("\nlogin: username").username)
|
||||
assertEquals("foo@example.com", makeEntry("\nemail: foo@example.com").username)
|
||||
assertEquals("username", makeEntry("\nidentity: username\nlogin: another_username").username)
|
||||
assertEquals("username", makeEntry("\nLOGiN:username").username)
|
||||
assertNull(makeEntry("secret\nextra\ncontent\n").username)
|
||||
}
|
||||
|
||||
@Test fun testHasUsername() {
|
||||
assertTrue(makeEntry("secret\nextra\nlogin: username\ncontent\n").hasUsername())
|
||||
assertFalse(makeEntry("secret\nextra\ncontent\n").hasUsername())
|
||||
assertFalse(makeEntry("secret\nlogin failed\n").hasUsername())
|
||||
assertFalse(makeEntry("\n").hasUsername())
|
||||
assertFalse(makeEntry("").hasUsername())
|
||||
}
|
||||
|
||||
@Test fun testGeneratesOtpFromTotpUri() {
|
||||
val entry = makeEntry("secret\nextra\n$TOTP_URI")
|
||||
assertTrue(entry.hasTotp())
|
||||
val code = Otp.calculateCode(
|
||||
entry.totpSecret!!,
|
||||
// The hardcoded date value allows this test to stay reproducible.
|
||||
Date(8640000).time / (1000 * entry.totpPeriod),
|
||||
entry.totpAlgorithm,
|
||||
entry.digits
|
||||
)
|
||||
assertNotNull(code) { "Generated OTP cannot be null" }
|
||||
assertEquals(entry.digits.toInt(), code.length)
|
||||
assertEquals("545293", code)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val TOTP_URI = "otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"
|
||||
}
|
||||
}
|
|
@ -16,25 +16,30 @@ class UriTotpFinderTest {
|
|||
fun findSecret() {
|
||||
assertEquals("HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", totpFinder.findSecret(TOTP_URI))
|
||||
assertEquals("HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", totpFinder.findSecret("name\npassword\ntotp: HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ"))
|
||||
assertEquals("HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", totpFinder.findSecret(PASS_FILE_CONTENT))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findDigits() {
|
||||
assertEquals("12", totpFinder.findDigits(TOTP_URI))
|
||||
assertEquals("12", totpFinder.findDigits(PASS_FILE_CONTENT))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findPeriod() {
|
||||
assertEquals(25, totpFinder.findPeriod(TOTP_URI))
|
||||
assertEquals(25, totpFinder.findPeriod(PASS_FILE_CONTENT))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findAlgorithm() {
|
||||
assertEquals("SHA256", totpFinder.findAlgorithm(TOTP_URI))
|
||||
assertEquals("SHA256", totpFinder.findAlgorithm(PASS_FILE_CONTENT))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val TOTP_URI = "otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA256&digits=12&period=25"
|
||||
const val PASS_FILE_CONTENT = "password\n$TOTP_URI"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue