From 4ffd7ed9bffa5139277ffb91de5a69f2b714222c Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Fri, 17 Apr 2020 00:24:13 +0530 Subject: Enable emulator tests (#708) * github: Enable instrumentation testing in PRs Signed-off-by: Harsh Shandilya * Upgrade to Gradle 6.3 Signed-off-by: Harsh Shandilya * Remove outdated and broken tests, redo PasswordEntryTest in Kotlin Signed-off-by: Harsh Shandilya * Remove now unused test assets Signed-off-by: Harsh Shandilya * github: Disable debug APK uploads in PR testing Signed-off-by: Harsh Shandilya * Update .github/workflows/pull_request.yml * Update .github/workflows/pull_request.yml Switching to Ubuntu fails due to the SDK 29 missing. Co-authored-by: Fabian Henneke --- .../androidTest/assets/clear-store/category/sub | 3 - app/src/androidTest/assets/clear-store/pass | 3 - .../assets/encrypted-store/category/sub.gpg | Bin 362 -> 0 bytes .../androidTest/assets/encrypted-store/pass.gpg | Bin 361 -> 0 bytes app/src/androidTest/assets/private_key | Bin 2575 -> 0 bytes .../java/com/zeapo/pwdstore/DecryptTest.kt | 182 --------------------- .../java/com/zeapo/pwdstore/EncryptTest.kt | 100 ----------- .../java/com/zeapo/pwdstore/OtpTest.java | 15 -- .../java/com/zeapo/pwdstore/PasswordEntryTest.java | 97 ----------- .../java/com/zeapo/pwdstore/PasswordEntryTest.kt | 97 +++++++++++ 10 files changed, 97 insertions(+), 400 deletions(-) delete mode 100644 app/src/androidTest/assets/clear-store/category/sub delete mode 100644 app/src/androidTest/assets/clear-store/pass delete mode 100644 app/src/androidTest/assets/encrypted-store/category/sub.gpg delete mode 100644 app/src/androidTest/assets/encrypted-store/pass.gpg delete mode 100644 app/src/androidTest/assets/private_key delete mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/DecryptTest.kt delete mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/EncryptTest.kt delete mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/OtpTest.java delete mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.java create mode 100644 app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.kt (limited to 'app/src/androidTest') diff --git a/app/src/androidTest/assets/clear-store/category/sub b/app/src/androidTest/assets/clear-store/category/sub deleted file mode 100644 index eb9106c1..00000000 --- a/app/src/androidTest/assets/clear-store/category/sub +++ /dev/null @@ -1,3 +0,0 @@ -sub_pass -login: user -sub_extra diff --git a/app/src/androidTest/assets/clear-store/pass b/app/src/androidTest/assets/clear-store/pass deleted file mode 100644 index 8415d1ab..00000000 --- a/app/src/androidTest/assets/clear-store/pass +++ /dev/null @@ -1,3 +0,0 @@ -password -username: user -extra diff --git a/app/src/androidTest/assets/encrypted-store/category/sub.gpg b/app/src/androidTest/assets/encrypted-store/category/sub.gpg deleted file mode 100644 index dded0132..00000000 Binary files a/app/src/androidTest/assets/encrypted-store/category/sub.gpg and /dev/null differ diff --git a/app/src/androidTest/assets/encrypted-store/pass.gpg b/app/src/androidTest/assets/encrypted-store/pass.gpg deleted file mode 100644 index 53c614c4..00000000 Binary files a/app/src/androidTest/assets/encrypted-store/pass.gpg and /dev/null differ diff --git a/app/src/androidTest/assets/private_key b/app/src/androidTest/assets/private_key deleted file mode 100644 index 7141d6f4..00000000 Binary files a/app/src/androidTest/assets/private_key and /dev/null differ diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/DecryptTest.kt b/app/src/androidTest/java/com/zeapo/pwdstore/DecryptTest.kt deleted file mode 100644 index 17c7cbed..00000000 --- a/app/src/androidTest/java/com/zeapo/pwdstore/DecryptTest.kt +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore - -import android.annotation.SuppressLint -import android.content.ClipboardManager -import android.content.Context -import android.content.Intent -import android.os.IBinder -import android.os.ParcelFileDescriptor -import android.os.SystemClock -import android.util.Log -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.LargeTest -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.rule.ActivityTestRule -import com.zeapo.pwdstore.crypto.PgpActivity -import java.io.File -import java.io.FileOutputStream -import java.io.IOException -import java.nio.charset.StandardCharsets -import kotlinx.android.synthetic.main.decrypt_layout.crypto_extra_show -import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_category_decrypt -import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_file -import kotlinx.android.synthetic.main.decrypt_layout.crypto_password_show -import kotlinx.android.synthetic.main.decrypt_layout.crypto_username_show -import org.apache.commons.io.FileUtils -import org.apache.commons.io.IOUtils -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.openintents.openpgp.IOpenPgpService2 - -@RunWith(AndroidJUnit4::class) -@LargeTest -class DecryptTest { - private lateinit var targetContext: Context - private lateinit var testContext: Context - lateinit var activity: PgpActivity - - private val name = "sub" - private val parentPath = "/category/" - lateinit var path: String - lateinit var repoPath: String - - @Rule @JvmField - var mActivityRule: ActivityTestRule = ActivityTestRule(PgpActivity::class.java, true, false) - - private fun init() { - targetContext = InstrumentationRegistry.getInstrumentation().targetContext - testContext = InstrumentationRegistry.getInstrumentation().context - copyAssets("encrypted-store", File(targetContext.filesDir, "test-store").absolutePath) - repoPath = File(targetContext.filesDir, "test-store").absolutePath - path = "$repoPath/$parentPath/$name.gpg".replace("//", "/") - - val intent = Intent(targetContext, PgpActivity::class.java) - intent.putExtra("OPERATION", "DECRYPT") - intent.putExtra("FILE_PATH", path) - intent.putExtra("REPO_PATH", repoPath) - - activity = mActivityRule.launchActivity(intent) - } - - @Test - fun pathShouldDecompose() { - val pathOne = "/fake/path/cat1/n1.gpg" - val pathTwo = "/fake/path/n2.gpg" - - assertEquals("/cat1/n1.gpg", PgpActivity.getRelativePath(pathOne, "/fake/path")) - assertEquals("/cat1/", PgpActivity.getParentPath(pathOne, "/fake/path")) - assertEquals("n1", PgpActivity.getName("$pathOne/fake/path")) - // test that even if we append a `/` it still works - assertEquals("n1", PgpActivity.getName("$pathOne/fake/path/")) - - assertEquals("/n2.gpg", PgpActivity.getRelativePath(pathTwo, "/fake/path")) - assertEquals("/", PgpActivity.getParentPath(pathTwo, "/fake/path")) - assertEquals("n2", PgpActivity.getName("$pathTwo/fake/path")) - assertEquals("n2", PgpActivity.getName("$pathTwo/fake/path/")) - } - - @Test - fun activityShouldShowName() { - init() - - val categoryView = activity.crypto_password_category_decrypt - assertNotNull(categoryView) - assertEquals(parentPath, categoryView.text) - - val nameView = activity.crypto_password_file - assertNotNull(nameView) - assertEquals(name, nameView.text) - } - - @SuppressLint("ApplySharedPref") // we need the preferences right away - @Test - fun shouldDecrypt() { - init() - val clearPass = IOUtils.toString(testContext.assets.open("clear-store/category/sub"), StandardCharsets.UTF_8) - val passEntry = PasswordEntry(clearPass) - - // Setup the timer to 1 second - // first remember the previous timer to set it back later - val showTime = try { - Integer.parseInt(activity.settings.getString("general_show_time", "45") ?: "45") - } catch (e: NumberFormatException) { - 45 - } - // second set the new timer - activity.settings.edit().putString("general_show_time", "2").commit() - - activity.onBound(object : IOpenPgpService2 { - override fun createOutputPipe(p0: Int): ParcelFileDescriptor { - TODO("Not yet implemented") - } - - override fun asBinder(): IBinder { - TODO("Not yet implemented") - } - - override fun execute(p0: Intent?, p1: ParcelFileDescriptor?, p2: Int): Intent { - TODO("Not yet implemented") - } - }) - - // have we decrypted things correctly? - assertEquals(passEntry.password, activity.crypto_password_show.text) - assertEquals(passEntry.username, activity.crypto_username_show.text.toString()) - assertEquals(passEntry.extraContent, activity.crypto_extra_show.text.toString()) - - // did we copy the password? - val clipboard: ClipboardManager = activity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - assertEquals(passEntry.password, clipboard.primaryClip!!.getItemAt(0).text) - - // wait until the clipboard is cleared - SystemClock.sleep(4000) - - // The clipboard should be cleared!! - for (i in 0..clipboard.primaryClip!!.itemCount) { - assertEquals("", clipboard.primaryClip!!.getItemAt(i).text) - } - - // set back the timer - activity.settings.edit().putString("general_show_time", showTime.toString()).commit() - } - - companion object { - fun copyAssets(source: String, destination: String) { - FileUtils.forceMkdir(File(destination)) - FileUtils.cleanDirectory(File(destination)) - - val testContext = InstrumentationRegistry.getInstrumentation().context - val assetManager = testContext.assets - val files: Array? = assetManager.list(source) - - files?.map { filename -> - val destPath = "$destination/$filename" - val sourcePath = "$source/$filename" - - if (assetManager.list(sourcePath)!!.isNotEmpty()) { - FileUtils.forceMkdir(File(destination, filename)) - copyAssets("$source/$filename", destPath) - } else { - try { - val input = assetManager.open(sourcePath) - val outFile = File(destination, filename) - val output = FileOutputStream(outFile) - IOUtils.copy(input, output) - input.close() - output.flush() - output.close() - } catch (e: IOException) { - Log.e("tag", "Failed to copy asset file: $filename", e) - } - } - } - } - } -} diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/EncryptTest.kt b/app/src/androidTest/java/com/zeapo/pwdstore/EncryptTest.kt deleted file mode 100644 index ba63ce1a..00000000 --- a/app/src/androidTest/java/com/zeapo/pwdstore/EncryptTest.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore - -import android.annotation.SuppressLint -import android.content.Context -import android.content.Intent -import android.os.IBinder -import android.os.ParcelFileDescriptor -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.action.ViewActions.scrollTo -import androidx.test.espresso.action.ViewActions.typeText -import androidx.test.espresso.assertion.ViewAssertions -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.LargeTest -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.rule.ActivityTestRule -import com.zeapo.pwdstore.crypto.PgpActivity -import java.io.File -import org.apache.commons.io.FileUtils -import org.apache.commons.io.IOUtils -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.openintents.openpgp.IOpenPgpService2 - -@RunWith(AndroidJUnit4::class) -@LargeTest -class EncryptTest { - private lateinit var targetContext: Context - private lateinit var testContext: Context - private lateinit var activity: PgpActivity - - private val name = "sub" - private val parentPath = "/category/" - private lateinit var path: String - private lateinit var repoPath: String - - @Rule @JvmField - var mActivityRule: ActivityTestRule = ActivityTestRule(PgpActivity::class.java, true, false) - - private fun init() { - targetContext = InstrumentationRegistry.getInstrumentation().targetContext - testContext = InstrumentationRegistry.getInstrumentation().context - - // have an empty store - FileUtils.forceMkdir(File(targetContext.filesDir, "test-store")) - FileUtils.cleanDirectory(File(targetContext.filesDir, "test-store")) - - repoPath = File(targetContext.filesDir, "test-store").absolutePath - - path = "$repoPath/$parentPath/".replace("//", "/") - - val intent = Intent(targetContext, PgpActivity::class.java) - intent.putExtra("OPERATION", "ENCRYPT") - intent.putExtra("FILE_PATH", path) - intent.putExtra("REPO_PATH", repoPath) - - activity = mActivityRule.launchActivity(intent) - } - - @SuppressLint("ApplySharedPref", "SetTextI18n") - @Test - fun shouldEncrypt() { - init() - - onView(withId(R.id.crypto_password_category)).check(ViewAssertions.matches(withText(parentPath))) - activity.onBound(object : IOpenPgpService2 { - override fun createOutputPipe(p0: Int): ParcelFileDescriptor { - TODO("Not yet implemented") - } - - override fun asBinder(): IBinder { - TODO("Not yet implemented") - } - - override fun execute(p0: Intent?, p1: ParcelFileDescriptor?, p2: Int): Intent { - TODO("Not yet implemented") - } - }) - val clearPass = IOUtils.toString(testContext.assets.open("clear-store/category/sub"), Charsets.UTF_8.name()) - val passEntry = PasswordEntry(clearPass) - - onView(withId(R.id.crypto_password_file_edit)).perform(typeText("sub")) - onView(withId(R.id.crypto_password_edit)).perform(typeText(passEntry.password)) - onView(withId(R.id.crypto_extra_edit)).perform(scrollTo(), click()) - onView(withId(R.id.crypto_extra_edit)).perform(typeText(passEntry.extraContent)) - - // we should return to the home screen once we confirm - onView(withId(R.id.crypto_confirm_add)).perform(click()) - - // The resulting file should exist - assert(File("$path/$name.gpg").exists()) - } -} diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/OtpTest.java b/app/src/androidTest/java/com/zeapo/pwdstore/OtpTest.java deleted file mode 100644 index 76be43a1..00000000 --- a/app/src/androidTest/java/com/zeapo/pwdstore/OtpTest.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore; - -import com.zeapo.pwdstore.utils.Otp; -import junit.framework.TestCase; - -public class OtpTest extends TestCase { - public void testOtp() { - String code = Otp.calculateCode("JBSWY3DPEHPK3PXP", 0L, "sha1", "s"); - assertEquals("282760", code); - } -} diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.java b/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.java deleted file mode 100644 index dd55fbda..00000000 --- a/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. - * SPDX-License-Identifier: GPL-3.0-only - */ -package com.zeapo.pwdstore; - -import junit.framework.TestCase; - -public class PasswordEntryTest extends TestCase { - - public void testGetPassword() { - assertEquals("fooooo", new PasswordEntry("fooooo\nbla\n").getPassword()); - assertEquals("fooooo", new PasswordEntry("fooooo\nbla").getPassword()); - assertEquals("fooooo", new PasswordEntry("fooooo\n").getPassword()); - assertEquals("fooooo", new PasswordEntry("fooooo").getPassword()); - assertEquals("", new PasswordEntry("\nblubb\n").getPassword()); - assertEquals("", new PasswordEntry("\nblubb").getPassword()); - assertEquals("", new PasswordEntry("\n").getPassword()); - assertEquals("", new PasswordEntry("").getPassword()); - } - - public void testGetExtraContent() { - assertEquals("bla\n", new PasswordEntry("fooooo\nbla\n").getExtraContent()); - assertEquals("bla", new PasswordEntry("fooooo\nbla").getExtraContent()); - assertEquals("", new PasswordEntry("fooooo\n").getExtraContent()); - assertEquals("", new PasswordEntry("fooooo").getExtraContent()); - assertEquals("blubb\n", new PasswordEntry("\nblubb\n").getExtraContent()); - assertEquals("blubb", new PasswordEntry("\nblubb").getExtraContent()); - assertEquals("", new PasswordEntry("\n").getExtraContent()); - assertEquals("", new PasswordEntry("").getExtraContent()); - } - - public void testGetUsername() { - assertEquals( - "username", - new PasswordEntry("secret\nextra\nlogin: username\ncontent\n").getUsername()); - assertEquals( - "username", - new PasswordEntry("\nextra\nusername: username\ncontent\n").getUsername()); - assertEquals( - "username", new PasswordEntry("\nUSERNaMe: username\ncontent\n").getUsername()); - assertEquals("username", new PasswordEntry("\nLOGiN:username").getUsername()); - assertNull(new PasswordEntry("secret\nextra\ncontent\n").getUsername()); - } - - public void testHasUsername() { - assertTrue(new PasswordEntry("secret\nextra\nlogin: username\ncontent\n").hasUsername()); - assertFalse(new PasswordEntry("secret\nextra\ncontent\n").hasUsername()); - assertFalse(new PasswordEntry("secret\nlogin failed\n").hasUsername()); - assertFalse(new PasswordEntry("\n").hasUsername()); - assertFalse(new PasswordEntry("").hasUsername()); - } - - public void testNoTotpUriPresent() { - PasswordEntry entry = new PasswordEntry("secret\nextra\nlogin: username\ncontent"); - assertFalse(entry.hasTotp()); - assertNull(entry.getTotpSecret()); - } - - public void testTotpUriInPassword() { - PasswordEntry entry = new PasswordEntry("otpauth://totp/test?secret=JBSWY3DPEHPK3PXP"); - assertTrue(entry.hasTotp()); - assertEquals("JBSWY3DPEHPK3PXP", entry.getTotpSecret()); - } - - public void testTotpUriInContent() { - PasswordEntry entry = - new PasswordEntry( - "secret\nusername: test\notpauth://totp/test?secret=JBSWY3DPEHPK3PXP"); - assertTrue(entry.hasTotp()); - assertEquals("JBSWY3DPEHPK3PXP", entry.getTotpSecret()); - } - - public void testNoHotpUriPresent() { - PasswordEntry entry = new PasswordEntry("secret\nextra\nlogin: username\ncontent"); - assertFalse(entry.hasHotp()); - assertNull(entry.getHotpSecret()); - assertNull(entry.getHotpCounter()); - } - - public void testHotpUriInPassword() { - PasswordEntry entry = - new PasswordEntry("otpauth://hotp/test?secret=JBSWY3DPEHPK3PXP&counter=25"); - assertTrue(entry.hasHotp()); - assertEquals("JBSWY3DPEHPK3PXP", entry.getHotpSecret()); - assertEquals(new Long(25), entry.getHotpCounter()); - } - - public void testHotpUriInContent() { - PasswordEntry entry = - new PasswordEntry( - "secret\nusername: test\notpauth://hotp/test?secret=JBSWY3DPEHPK3PXP&counter=25"); - assertTrue(entry.hasHotp()); - assertEquals("JBSWY3DPEHPK3PXP", entry.getHotpSecret()); - assertEquals(new Long(25), entry.getHotpCounter()); - } -} diff --git a/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.kt b/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.kt new file mode 100644 index 00000000..2f7028a4 --- /dev/null +++ b/app/src/androidTest/java/com/zeapo/pwdstore/PasswordEntryTest.kt @@ -0,0 +1,97 @@ +/* + * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore + +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNull +import kotlin.test.assertTrue +import org.junit.Test + +class PasswordEntryTest { + @Test fun testGetPassword() { + assertEquals("fooooo", PasswordEntry("fooooo\nbla\n").password) + assertEquals("fooooo", PasswordEntry("fooooo\nbla").password) + assertEquals("fooooo", PasswordEntry("fooooo\n").password) + assertEquals("fooooo", PasswordEntry("fooooo").password) + assertEquals("", PasswordEntry("\nblubb\n").password) + assertEquals("", PasswordEntry("\nblubb").password) + assertEquals("", PasswordEntry("\n").password) + assertEquals("", PasswordEntry("").password) + } + + @Test fun testGetExtraContent() { + assertEquals("bla\n", PasswordEntry("fooooo\nbla\n").extraContent) + assertEquals("bla", PasswordEntry("fooooo\nbla").extraContent) + assertEquals("", PasswordEntry("fooooo\n").extraContent) + assertEquals("", PasswordEntry("fooooo").extraContent) + assertEquals("blubb\n", PasswordEntry("\nblubb\n").extraContent) + assertEquals("blubb", PasswordEntry("\nblubb").extraContent) + assertEquals("", PasswordEntry("\n").extraContent) + assertEquals("", PasswordEntry("").extraContent) + } + + @Test fun testGetUsername() { + assertEquals( + "username", + PasswordEntry("secret\nextra\nlogin: username\ncontent\n").username) + assertEquals( + "username", + PasswordEntry("\nextra\nusername: username\ncontent\n").username) + assertEquals( + "username", PasswordEntry("\nUSERNaMe: username\ncontent\n").username) + assertEquals("username", PasswordEntry("\nLOGiN:username").username) + assertNull(PasswordEntry("secret\nextra\ncontent\n").username) + } + + @Test fun testHasUsername() { + assertTrue(PasswordEntry("secret\nextra\nlogin: username\ncontent\n").hasUsername()) + assertFalse(PasswordEntry("secret\nextra\ncontent\n").hasUsername()) + assertFalse(PasswordEntry("secret\nlogin failed\n").hasUsername()) + assertFalse(PasswordEntry("\n").hasUsername()) + assertFalse(PasswordEntry("").hasUsername()) + } + + @Test fun testNoTotpUriPresent() { + val entry = PasswordEntry("secret\nextra\nlogin: username\ncontent") + assertFalse(entry.hasTotp()) + assertNull(entry.totpSecret) + } + + @Test fun testTotpUriInPassword() { + val entry = PasswordEntry("otpauth://totp/test?secret=JBSWY3DPEHPK3PXP") + assertTrue(entry.hasTotp()) + assertEquals("JBSWY3DPEHPK3PXP", entry.totpSecret) + } + + @Test fun testTotpUriInContent() { + val entry = PasswordEntry( + "secret\nusername: test\notpauth://totp/test?secret=JBSWY3DPEHPK3PXP") + assertTrue(entry.hasTotp()) + assertEquals("JBSWY3DPEHPK3PXP", entry.totpSecret) + } + + @Test fun testNoHotpUriPresent() { + val entry = PasswordEntry("secret\nextra\nlogin: username\ncontent") + assertFalse(entry.hasHotp()) + assertNull(entry.hotpSecret) + assertNull(entry.hotpCounter) + } + + @Test fun testHotpUriInPassword() { + val entry = PasswordEntry("otpauth://hotp/test?secret=JBSWY3DPEHPK3PXP&counter=25") + assertTrue(entry.hasHotp()) + assertEquals("JBSWY3DPEHPK3PXP", entry.hotpSecret) + assertEquals(25, entry.hotpCounter) + } + + @Test fun testHotpUriInContent() { + val entry = PasswordEntry( + "secret\nusername: test\notpauth://hotp/test?secret=JBSWY3DPEHPK3PXP&counter=25") + assertTrue(entry.hasHotp()) + assertEquals("JBSWY3DPEHPK3PXP", entry.hotpSecret) + assertEquals(25, entry.hotpCounter) + } +} -- cgit v1.2.3