Skip to content

Commit 42efc3b

Browse files
committed
Add secure testing files
1 parent fb9e6f8 commit 42efc3b

File tree

8 files changed

+297
-10
lines changed

8 files changed

+297
-10
lines changed

.idea/codeStyles/Project.xml

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.sample.easyprefs.secure
2+
3+
object Const {
4+
const val PREF_SAMPLE_FILE = "secure_sample_file_name"
5+
const val PREF_SAMPLE_FILE_2 = "secure_sample_file_name_two"
6+
7+
const val SAMPLE_STRING_KEY = "secure_sample_string_key"
8+
const val SAMPLE_STRING_KEY_ASYNC = "secure_sample_string_key_async"
9+
10+
const val SAMPLE_STRING_SET_KEY = "secure_sample_string_set_key"
11+
const val SAMPLE_STRING_SET_KEY_ASYNC = "secure_sample_string_set_key_async"
12+
13+
const val SAMPLE_INT_KEY = "secure_sample_int_key"
14+
const val SAMPLE_INT_KEY_ASYNC = "secure_sample_int_key_async"
15+
16+
const val SAMPLE_LONG_KEY = "secure_sample_long_key"
17+
const val SAMPLE_LONG_KEY_ASYNC = "secure_sample_long_key_async"
18+
19+
const val SAMPLE_FLOAT_KEY = "secure_sample_float_key"
20+
const val SAMPLE_FLOAT_KEY_ASYNC = "secure_sample_float_key_async"
21+
22+
const val SAMPLE_DOUBLE_KEY = "secure_sample_double_key"
23+
const val SAMPLE_DOUBLE_KEY_ASYNC = "secure_sample_double_key_async"
24+
25+
const val SAMPLE_BOOLEAN_KEY = "secure_sample_boolean_key"
26+
const val SAMPLE_BOOLEAN_KEY_ASYNC = "secure_sample_boolean_key_async"
27+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.sample.easyprefs.secure
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import androidx.test.platform.app.InstrumentationRegistry
5+
import io.easyprefs.Prefs
6+
import org.junit.Assert.assertEquals
7+
import org.junit.Assert.assertTrue
8+
import org.junit.Before
9+
import org.junit.Test
10+
import org.junit.runner.RunWith
11+
12+
/**
13+
* Instrumented test, which will execute on an Android device.
14+
*
15+
* See [testing documentation](http://d.android.com/tools/testing).
16+
*/
17+
@RunWith(AndroidJUnit4::class)
18+
class SecurePrefsReadAsyncTest {
19+
20+
@Before
21+
fun initApp() {
22+
Prefs.initializeApp(InstrumentationRegistry.getInstrumentation().targetContext)
23+
}
24+
25+
@Test
26+
fun testStringAsync() {
27+
val value = "Async..."
28+
val data = Prefs.securely().read().string(Const.SAMPLE_STRING_KEY_ASYNC, "")
29+
assertEquals(value, data)
30+
}
31+
32+
@Test
33+
fun testIntAsync() {
34+
val value = Int.MAX_VALUE
35+
val data = Prefs.securely().read().int(Const.SAMPLE_INT_KEY_ASYNC, Int.MIN_VALUE)
36+
assertEquals(value, data)
37+
}
38+
39+
@Test
40+
fun testFloatAsync() {
41+
val value = Float.MAX_VALUE
42+
val data = Prefs.securely().read().float(Const.SAMPLE_FLOAT_KEY_ASYNC, Float.MIN_VALUE)
43+
assertEquals(value, data)
44+
}
45+
46+
@Test
47+
fun testLongAsync() {
48+
val value = Long.MAX_VALUE
49+
val data = Prefs.securely().read().long(Const.SAMPLE_LONG_KEY_ASYNC, Long.MIN_VALUE)
50+
assertEquals(value, data)
51+
}
52+
53+
@Test
54+
fun testDoubleAsync() {
55+
val value = Double.MAX_VALUE
56+
val data = Prefs.securely().read().double(Const.SAMPLE_DOUBLE_KEY_ASYNC, Double.MIN_VALUE)
57+
assertEquals(value.toString(), data.toString())
58+
}
59+
60+
@Test
61+
fun testBooleanAsync() {
62+
val value = false
63+
val data = Prefs.securely().read().boolean(Const.SAMPLE_BOOLEAN_KEY_ASYNC, true)
64+
assertEquals(value, data)
65+
}
66+
67+
@Test
68+
fun testStringSetAsync() {
69+
val value = setOf("A", "B", "C", "D")
70+
val data = Prefs.securely().read().stringSet(Const.SAMPLE_STRING_SET_KEY_ASYNC, setOf())
71+
assertEquals(value, data)
72+
}
73+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package com.sample.easyprefs.secure
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import androidx.test.platform.app.InstrumentationRegistry
5+
import io.easyprefs.Prefs
6+
import org.junit.Assert.assertEquals
7+
import org.junit.Assert.assertTrue
8+
import org.junit.Before
9+
import org.junit.Test
10+
import org.junit.runner.RunWith
11+
12+
/**
13+
* Instrumented test, which will execute on an Android device.
14+
*
15+
* See [testing documentation](http://d.android.com/tools/testing).
16+
*/
17+
@RunWith(AndroidJUnit4::class)
18+
class SecurePrefsTest {
19+
20+
@Before
21+
fun initApp() {
22+
Prefs.initializeApp(InstrumentationRegistry.getInstrumentation().targetContext)
23+
}
24+
25+
@Test
26+
fun testString() {
27+
val value = "Hello..."
28+
assertTrue(Prefs.securely().write().string(Const.SAMPLE_STRING_KEY, value))
29+
30+
val data = Prefs.securely().read().string(Const.SAMPLE_STRING_KEY, "")
31+
assertEquals(value, data)
32+
}
33+
34+
@Test
35+
fun testStringAsync() {
36+
val value = "Async..."
37+
Prefs.securely().write().stringAsync(Const.SAMPLE_STRING_KEY_ASYNC, value)
38+
}
39+
40+
@Test
41+
fun testInt() {
42+
val value = Int.MAX_VALUE
43+
assertTrue(Prefs.securely().write().int(Const.SAMPLE_INT_KEY, value))
44+
45+
val data = Prefs.securely().read().int(Const.SAMPLE_INT_KEY, Int.MIN_VALUE)
46+
assertEquals(value, data)
47+
}
48+
49+
@Test
50+
fun testIntAsync() {
51+
val value = Int.MAX_VALUE
52+
Prefs.securely().write().intAsync(Const.SAMPLE_INT_KEY_ASYNC, value)
53+
}
54+
55+
@Test
56+
fun testFloat() {
57+
val value = Float.MAX_VALUE
58+
assertTrue(Prefs.securely().write().float(Const.SAMPLE_FLOAT_KEY, value))
59+
60+
val data = Prefs.securely().read().float(Const.SAMPLE_FLOAT_KEY, Float.MIN_VALUE)
61+
assertEquals(value, data)
62+
}
63+
64+
@Test
65+
fun testFloatAsync() {
66+
val value = Float.MAX_VALUE
67+
Prefs.securely().write().floatAsync(Const.SAMPLE_FLOAT_KEY_ASYNC, value)
68+
}
69+
70+
@Test
71+
fun testLong() {
72+
val value = Long.MAX_VALUE
73+
assertTrue(Prefs.securely().write().long(Const.SAMPLE_LONG_KEY, value))
74+
75+
val data = Prefs.securely().read().long(Const.SAMPLE_LONG_KEY, Long.MIN_VALUE)
76+
assertEquals(value, data)
77+
}
78+
79+
@Test
80+
fun testLongAsync() {
81+
val value = Long.MAX_VALUE
82+
Prefs.securely().write().longAsync(Const.SAMPLE_LONG_KEY_ASYNC, value)
83+
}
84+
85+
@Test
86+
fun testDouble() {
87+
val value = Double.MAX_VALUE
88+
assertTrue(Prefs.securely().write().double(Const.SAMPLE_DOUBLE_KEY, value))
89+
90+
val data = Prefs.securely().read().double(Const.SAMPLE_DOUBLE_KEY, Double.MIN_VALUE)
91+
assertEquals(value.toString(), data.toString())
92+
}
93+
94+
@Test
95+
fun testDoubleAsync() {
96+
val value = Double.MAX_VALUE
97+
Prefs.securely().write().doubleAsync(Const.SAMPLE_DOUBLE_KEY_ASYNC, value)
98+
}
99+
100+
@Test
101+
fun testBoolean() {
102+
val value = false
103+
assertTrue(Prefs.securely().write().boolean(Const.SAMPLE_BOOLEAN_KEY, value))
104+
105+
val data = Prefs.securely().read().boolean(Const.SAMPLE_BOOLEAN_KEY, true)
106+
assertEquals(value, data)
107+
}
108+
109+
@Test
110+
fun testBooleanAsync() {
111+
val value = false
112+
Prefs.securely().write().booleanAsync(Const.SAMPLE_BOOLEAN_KEY_ASYNC, value)
113+
}
114+
115+
@Test
116+
fun testStringSet() {
117+
val value = setOf("A", "B", "C", "D")
118+
assertTrue(Prefs.securely().write().stringSet(Const.SAMPLE_STRING_SET_KEY, value))
119+
120+
val data = Prefs.securely().read().stringSet(Const.SAMPLE_STRING_SET_KEY, setOf())
121+
assertEquals(value, data)
122+
}
123+
124+
@Test
125+
fun testStringSetAsync() {
126+
val value = setOf("A", "B", "C", "D")
127+
Prefs.securely().write().stringSetAsync(Const.SAMPLE_STRING_SET_KEY_ASYNC, value)
128+
}
129+
}

app/src/main/java/com/sample/easyprefs/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.sample.easyprefs
22

33
import android.os.Bundle
44
import androidx.appcompat.app.AppCompatActivity
5+
import io.easyprefs.Prefs
56

67
class MainActivity : AppCompatActivity() {
78
override fun onCreate(savedInstanceState: Bundle?) {

library/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ dependencies {
2828
implementation fileTree(dir: "libs", include: ["*.jar"])
2929
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
3030
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
31+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
3132
}

library/src/main/java/io/easyprefs/impl/ReadImpl.kt

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.SharedPreferences
44
import io.easyprefs.contract.Read
55
import io.easyprefs.secure.Crypt
66
import io.easyprefs.typedef.Encryption
7+
import org.json.JSONArray
78

89
class ReadImpl(
910
private val pref: SharedPreferences,
@@ -20,7 +21,7 @@ class ReadImpl(
2021
}
2122

2223
private fun decrypt(key: String, defaultValue: String): String {
23-
var value = pref.getString(key, defaultValue) ?: defaultValue
24+
var value = pref.getString(key, null) ?: defaultValue
2425
return if (aesKey.isEmpty()) {
2526
if (value != defaultValue) {
2627
value = Crypt.decrypt(key, value)
@@ -35,26 +36,56 @@ class ReadImpl(
3536
}
3637

3738
override fun string(key: String, defaultValue: String): String {
38-
return pref.getString(key, defaultValue) ?: defaultValue
39+
return if (encType == Encryption.NONE) {
40+
pref.getString(key, defaultValue) ?: defaultValue
41+
} else {
42+
decrypt(key, defaultValue)
43+
}
3944
}
4045

4146
override fun long(key: String, defaultValue: Long): Long {
42-
return pref.getLong(key, defaultValue)
47+
return if (encType == Encryption.NONE) {
48+
pref.getLong(key, defaultValue)
49+
} else {
50+
decrypt(key, defaultValue.toString()).toLong()
51+
}
4352
}
4453

4554
override fun float(key: String, defaultValue: Float): Float {
46-
return pref.getFloat(key, defaultValue)
55+
return if (encType == Encryption.NONE) {
56+
pref.getFloat(key, defaultValue)
57+
} else {
58+
decrypt(key, defaultValue.toString()).toFloat()
59+
}
4760
}
4861

4962
override fun double(key: String, defaultValue: Double): Double {
5063
return string(key, defaultValue.toString()).toDouble()
5164
}
5265

5366
override fun boolean(key: String, defaultValue: Boolean): Boolean {
54-
return pref.getBoolean(key, defaultValue)
67+
return if (encType == Encryption.NONE) {
68+
pref.getBoolean(key, defaultValue)
69+
} else {
70+
decrypt(key, defaultValue.toString()).toBoolean()
71+
}
5572
}
5673

5774
override fun stringSet(key: String, defaultValue: Set<String>): Set<String> {
58-
return pref.getStringSet(key, defaultValue) ?: defaultValue
75+
return if (encType == Encryption.NONE) {
76+
return pref.getStringSet(key, defaultValue) ?: defaultValue
77+
} else {
78+
val value = decrypt(key, "")
79+
if (value.isEmpty()) {
80+
defaultValue
81+
} else {
82+
val set = mutableSetOf<String>()
83+
val array = JSONArray(value)
84+
for (i in 0 until array.length()) {
85+
set.add(array.optString(i))
86+
}
87+
set
88+
}
89+
}
5990
}
6091
}

library/src/main/java/io/easyprefs/impl/WriteImpl.kt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import android.content.SharedPreferences
44
import io.easyprefs.contract.Write
55
import io.easyprefs.secure.Crypt
66
import io.easyprefs.typedef.Encryption
7+
import kotlinx.coroutines.Dispatchers
78
import kotlinx.coroutines.GlobalScope
89
import kotlinx.coroutines.launch
10+
import kotlinx.coroutines.withContext
911
import org.json.JSONArray
1012

1113
class WriteImpl(
@@ -30,16 +32,23 @@ class WriteImpl(
3032
}
3133
}
3234

33-
private fun cryptAsync(key: String, value: String) {
34-
GlobalScope.launch {
35+
private suspend fun cryptAsyncSuspend(key: String, value: String): String {
36+
return withContext(Dispatchers.IO) {
3537
if (aesKey.isEmpty()) {
36-
edit.putString(key, Crypt.encrypt(key, value)).apply()
38+
Crypt.encrypt(key, value)
3739
} else {
38-
edit.putString(key, Crypt.encrypt(aesKey, value)).apply()
40+
Crypt.encrypt(aesKey, value)
3941
}
4042
}
4143
}
4244

45+
private fun cryptAsync(key: String, value: String) {
46+
GlobalScope.launch(Dispatchers.Main) {
47+
val encrypted = cryptAsyncSuspend(key, value)
48+
edit.putString(key, encrypted).apply()
49+
}
50+
}
51+
4352
override fun intAsync(key: String, value: Int) {
4453
if (encType == Encryption.NONE) {
4554
edit.putInt(key, value).apply()

0 commit comments

Comments
 (0)