Enable emulator tests (#708)
* github: Enable instrumentation testing in PRs Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Upgrade to Gradle 6.3 Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Remove outdated and broken tests, redo PasswordEntryTest in Kotlin Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * Remove now unused test assets Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * github: Disable debug APK uploads in PR testing Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * 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 <FabianHenneke@users.noreply.github.com>
This commit is contained in:
parent
8b4751f825
commit
4ffd7ed9bf
13 changed files with 109 additions and 406 deletions
16
.github/workflows/pull_request.yml
vendored
16
.github/workflows/pull_request.yml
vendored
|
@ -3,7 +3,10 @@ on: pull_request
|
|||
name: Check pull request
|
||||
jobs:
|
||||
test-pr:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
api-level: [23, 25, 27, 29]
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@master
|
||||
|
@ -16,9 +19,12 @@ jobs:
|
|||
path: ~/.gradle/caches
|
||||
key: gradle-${{ runner.os }}-${{ hashFiles('**/build.gradle') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/dependencies.gradle') }}
|
||||
|
||||
- run: ./gradlew spotlessCheck assembleDebug testDebug lintDebug -Dpre-dex=false
|
||||
- name: Run unit tests
|
||||
run: ./gradlew spotlessCheck testDebug lintDebug -Dpre-dex=false
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
- name: Run instrumentation tests
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
name: Debug APK
|
||||
path: app/build/outputs/apk/debug/app-debug.apk
|
||||
api-level: ${{ matrix.api-level }}
|
||||
target: default
|
||||
script: ./gradlew connectedCheck
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
sub_pass
|
||||
login: user
|
||||
sub_extra
|
|
@ -1,3 +0,0 @@
|
|||
password
|
||||
username: user
|
||||
extra
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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<PgpActivity> = ActivityTestRule<PgpActivity>(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<String>? = 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<PgpActivity> = ActivityTestRule<PgpActivity>(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())
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
Loading…
Reference in a new issue