Skip to content

Commit 34d797b

Browse files
authored
increase test coverage (#38)
* increase test coverage for Builders.kt * increase test coverage for DeviceTokenPluginTests.kt * refactor DeviceTokenPluginTests.kt to proper folder * increase test coverage for LoggerTest.kt * increase test coverage for Metric.kt * increase test coverage for SegmentDestinationTests.kt * refactor SegmentDestinationTests.kt to folder * increase test coverage for StartupQueueTest.kt * increase test coverage for JavaAnalytics.kt * refactor DestinationPluginTests.kt to folder * increase test coverage for EventsFileManager.kt * increase test coverage for PropertiesFile.kt * fix PropertiesFile.kt bug * increase test coverage for StorageImpl.kt * increase test coverage for HTTPClient.kt * HTTPClient bug fix * Increase test coverage for StateTest.kt * refactor Base64UtilsTest.kt to folder * fix httpclient issue * fix httpclient test
1 parent d4a4de6 commit 34d797b

File tree

18 files changed

+925
-55
lines changed

18 files changed

+925
-55
lines changed

core/src/main/java/com/segment/analytics/kotlin/core/HTTPClient.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ abstract class Connection(
7878
}
7979
}
8080

81-
fun safeGetInputStream(connection: HttpURLConnection): InputStream {
81+
fun safeGetInputStream(connection: HttpURLConnection): InputStream? {
8282
return try {
8383
connection.inputStream
8484
} catch (ignored: IOException) {
@@ -109,7 +109,7 @@ internal fun HttpURLConnection.createPostConnection(): Connection {
109109
var inputStream: InputStream? = null
110110
try {
111111
inputStream = safeGetInputStream(this.connection)
112-
responseBody = inputStream.bufferedReader().use(BufferedReader::readText)
112+
responseBody = inputStream?.bufferedReader()?.use(BufferedReader::readText)
113113
} catch (e: IOException) {
114114
responseBody = ("Could not read response body for rejected message: "
115115
+ e.toString())

core/src/main/java/com/segment/analytics/kotlin/core/compat/Builders.kt

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -111,26 +111,26 @@ class Builders {
111111
*/
112112
fun putJsonArray(key: String, action: java.util.function.Consumer<in JsonArrayBuilder>): JsonObjectBuilder = apply{ put(key, buildJsonArray(action)) }
113113

114+
/**
115+
* add another JsonObject to current JsonObject with a given key. the other JsonObject is
116+
* built through a lambda expression or a Function in Java
117+
* returns the builder instance
118+
*/
119+
fun putJsonObjectFunc(key: String, action: JsonObjectBuilder.() -> Unit): JsonObjectBuilder = apply{ put(key, buildJsonObject(action)) }
120+
121+
/**
122+
* add a JsonArray to current JsonObject with a given key. the JsonArray is built through a
123+
* lambda expression or a Function in Java
124+
* returns the builder instance
125+
*/
126+
fun putJsonArrayFunc(key: String, action: JsonArrayBuilder.() -> Unit): JsonObjectBuilder = apply{ put(key, buildJsonArray(action)) }
127+
114128
/**
115129
* build the content in JsonObject form
116130
*/
117131
internal fun build(): JsonObject = JsonObject(content)
118132
}
119133

120-
/**
121-
* add another JsonObject to current JsonObject with a given key. the other JsonObject is
122-
* built through a lambda expression or a Function in Java
123-
* returns the builder instance
124-
*/
125-
fun JsonObjectBuilder.putJsonObject(key: String, action: JsonObjectBuilder.() -> Unit): JsonObjectBuilder = apply{ put(key, buildJsonObject(action)) }
126-
127-
/**
128-
* add a JsonArray to current JsonObject with a given key. the JsonArray is built through a
129-
* lambda expression or a Function in Java
130-
* returns the builder instance
131-
*/
132-
fun JsonObjectBuilder.putJsonArray(key: String, action: JsonArrayBuilder.() -> Unit): JsonObjectBuilder = apply{ put(key, buildJsonArray(action)) }
133-
134134
/**
135135
* DSL builder for Kotlin JsonArray
136136
*/
@@ -176,26 +176,26 @@ class Builders {
176176
*/
177177
fun addJsonArray(action: java.util.function.Consumer<in JsonArrayBuilder>): JsonArrayBuilder = apply{ add(buildJsonArray(action)) }
178178

179+
/**
180+
* add a JsonObject to current JsonArray. the JsonObject is
181+
* built through a lambda expression or a Function in Java
182+
* returns the builder instance
183+
*/
184+
fun addJsonObjectFunc(action: JsonObjectBuilder.() -> Unit): JsonArrayBuilder = apply{ add(buildJsonObject(action)) }
185+
186+
/**
187+
* add another JsonArray to current JsonArray. the other JsonArray is
188+
* built through a lambda expression or a Function in Java
189+
* returns the builder instance
190+
*/
191+
fun addJsonArrayFunc(action: JsonArrayBuilder.() -> Unit): JsonArrayBuilder = apply{ add(buildJsonArray(action)) }
192+
179193
/**
180194
* build the content in JsonArray form
181195
*/
182196
internal fun build(): JsonArray = JsonArray(content)
183197
}
184198

185-
/**
186-
* add a JsonObject to current JsonArray. the JsonObject is
187-
* built through a lambda expression or a Function in Java
188-
* returns the builder instance
189-
*/
190-
fun JsonArrayBuilder.addJsonObject(action: JsonObjectBuilder.() -> Unit): JsonArrayBuilder = apply{ add(buildJsonObject(action)) }
191-
192-
/**
193-
* add another JsonArray to current JsonArray. the other JsonArray is
194-
* built through a lambda expression or a Function in Java
195-
* returns the builder instance
196-
*/
197-
fun JsonArrayBuilder.addJsonArray(action: JsonArrayBuilder.() -> Unit): JsonArrayBuilder = apply{ add(buildJsonArray(action)) }
198-
199199
@DslMarker
200200
internal annotation class JsonDslMarker
201201
}

core/src/main/java/com/segment/analytics/kotlin/core/platform/plugins/SegmentDestination.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,4 @@ class SegmentDestination(
204204
}
205205
}
206206
}
207-
208-
override fun reset() {
209-
super.reset()
210-
}
211207
}

core/src/main/java/com/segment/analytics/kotlin/core/utilities/PropertiesFile.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class PropertiesFile(private val directory: File, writeKey: String) : KVS {
4747
underlyingProperties.getProperty(key, defaultVal)
4848

4949
fun remove(key: String): Boolean {
50-
underlyingProperties.setProperty(key, null)
50+
underlyingProperties.remove(key)
5151
save()
5252
return true
5353
}

core/src/test/kotlin/com/segment/analytics/kotlin/core/AnalyticsTests.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package com.segment.analytics.kotlin.core
22

33
import com.segment.analytics.kotlin.core.platform.DestinationPlugin
4+
import com.segment.analytics.kotlin.core.platform.EventPlugin
45
import com.segment.analytics.kotlin.core.platform.Plugin
56
import com.segment.analytics.kotlin.core.platform.plugins.ContextPlugin
7+
import com.segment.analytics.kotlin.core.platform.plugins.MetricType
8+
import com.segment.analytics.kotlin.core.platform.plugins.addMetric
69
import com.segment.analytics.kotlin.core.utils.StubPlugin
710
import com.segment.analytics.kotlin.core.utils.TestRunPlugin
811
import com.segment.analytics.kotlin.core.utils.clearPersistentStorage
@@ -187,6 +190,29 @@ class AnalyticsTests {
187190
}
188191
}
189192

193+
@Test
194+
fun `event metrics get populated`() {
195+
val mockPlugin = spyk(object : EventPlugin {
196+
override val type: Plugin.Type = Plugin.Type.Before
197+
override lateinit var analytics: Analytics
198+
override fun track(payload: TrackEvent): BaseEvent? {
199+
payload.addMetric(MetricType.Counter, "test", 1.0)
200+
return super.track(payload)
201+
}
202+
})
203+
analytics.add(mockPlugin)
204+
analytics.track("track", buildJsonObject { put("foo", "bar") })
205+
val track = slot<TrackEvent>()
206+
verify { mockPlugin.track(capture(track)) }
207+
track.captured.let {
208+
assertTrue(it.anonymousId.isNotBlank())
209+
assertTrue(it.messageId.isNotBlank())
210+
assertEquals(epochTimestamp, it.timestamp)
211+
assertTrue(it.context.containsKey("metrics"))
212+
assertEquals(emptyJsonObject, it.integrations)
213+
}
214+
}
215+
190216
@Nested
191217
inner class Track {
192218
@Test

core/src/test/kotlin/com/segment/analytics/kotlin/core/HTTPClientTests.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ package com.segment.analytics.kotlin.core
22

33
import com.segment.analytics.kotlin.core.Constants.LIBRARY_VERSION
44
import io.mockk.clearConstructorMockk
5+
import io.mockk.every
6+
import io.mockk.spyk
57
import org.junit.jupiter.api.Assertions.*
68
import org.junit.jupiter.api.Test
79
import org.junit.jupiter.api.TestInstance
10+
import java.io.IOException
11+
import java.io.InputStream
12+
import java.net.HttpURLConnection
13+
import java.net.URL
814

915
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
1016
class HTTPClientTests {
@@ -50,4 +56,29 @@ class HTTPClientTests {
5056
// is not possible https://bit.ly/3CVpR3J
5157
}
5258
}
59+
60+
@Test
61+
fun `safeGetInputStream properly catches exception`() {
62+
val connection = spyk(URL("https://api.segment.io/v1/batch").openConnection() as HttpURLConnection)
63+
every { connection.inputStream } throws IOException()
64+
val errorStream: InputStream? = safeGetInputStream(connection)
65+
assertEquals(connection.errorStream, errorStream)
66+
}
67+
68+
@Test
69+
fun `createPostConnection close`() {
70+
val connection = spyk(httpClient.upload("api.segment.io/v1"))
71+
every { connection.connection.responseCode } returns 300
72+
every { connection.connection.inputStream } throws IOException()
73+
every { connection.connection.responseMessage } returns "test"
74+
every { connection.outputStream?.close() } returns Unit
75+
every { connection.connection.errorStream } returns null
76+
try {
77+
connection.close()
78+
}
79+
catch (e: IOException) {
80+
e.message?: fail()
81+
e.message?.let { assertTrue(it.contains("300")) }
82+
}
83+
}
5384
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package com.segment.analytics.kotlin.core
2+
3+
import com.segment.analytics.kotlin.core.utils.clearPersistentStorage
4+
import kotlinx.coroutines.test.TestCoroutineDispatcher
5+
import kotlinx.coroutines.test.TestCoroutineScope
6+
import kotlinx.serialization.json.buildJsonObject
7+
import kotlinx.serialization.json.put
8+
import org.junit.jupiter.api.Assertions.assertEquals
9+
import org.junit.jupiter.api.Assertions.assertNull
10+
import org.junit.jupiter.api.BeforeEach
11+
import org.junit.jupiter.api.Nested
12+
import org.junit.jupiter.api.Test
13+
14+
internal class StateTest {
15+
private lateinit var analytics: Analytics
16+
17+
private val testDispatcher = TestCoroutineDispatcher()
18+
private val testScope = TestCoroutineScope(testDispatcher)
19+
20+
@BeforeEach
21+
fun setup() {
22+
clearPersistentStorage()
23+
val config = Configuration(
24+
writeKey = "123",
25+
application = "Test"
26+
)
27+
config.ioDispatcher = testDispatcher
28+
config.analyticsDispatcher = testDispatcher
29+
config.analyticsScope = testScope
30+
31+
analytics = Analytics(config)
32+
analytics.configuration.autoAddSegmentDestination = false
33+
}
34+
35+
@Nested
36+
inner class UserInfoTests {
37+
38+
@Test
39+
fun resetAction() {
40+
val traits = buildJsonObject { put("behaviour", "bad") }
41+
analytics.store.dispatch(
42+
UserInfo.SetUserIdAndTraitsAction(
43+
"oldUserId",
44+
traits),
45+
UserInfo::class
46+
)
47+
48+
assertEquals("oldUserId", analytics.userId())
49+
assertEquals(traits, analytics.traits())
50+
51+
analytics.store.dispatch(UserInfo.ResetAction(), UserInfo::class)
52+
assertNull(analytics.userId())
53+
assertNull(analytics.traits())
54+
}
55+
56+
@Test
57+
fun setUserIdAction() {
58+
analytics.store.dispatch(UserInfo.SetUserIdAction("oldUserId"), UserInfo::class)
59+
assertEquals("oldUserId", analytics.userId())
60+
61+
analytics.store.dispatch(UserInfo.SetUserIdAction("newUserId"), UserInfo::class)
62+
assertEquals("newUserId", analytics.userId())
63+
}
64+
65+
@Test
66+
fun setAnonymousIdAction() {
67+
analytics.store.dispatch(UserInfo.SetAnonymousIdAction("anonymous"), UserInfo::class)
68+
assertEquals("anonymous", analytics.store.currentState(UserInfo::class)?.anonymousId)
69+
}
70+
71+
@Test
72+
fun setTraitsAction() {
73+
val traits = buildJsonObject { put("behaviour", "bad") }
74+
75+
analytics.store.dispatch(UserInfo.SetUserIdAction("oldUserId"), UserInfo::class)
76+
assertEquals("oldUserId", analytics.userId())
77+
assertEquals(emptyJsonObject, analytics.traits())
78+
79+
analytics.store.dispatch(UserInfo.SetTraitsAction(traits), UserInfo::class)
80+
assertEquals(traits, analytics.traits())
81+
}
82+
83+
@Test
84+
fun setUserIdAndTraitsAction() {
85+
val traits = buildJsonObject { put("behaviour", "bad") }
86+
analytics.store.dispatch(
87+
UserInfo.SetUserIdAndTraitsAction(
88+
"oldUserId",
89+
traits),
90+
UserInfo::class
91+
)
92+
93+
assertEquals("oldUserId", analytics.userId())
94+
assertEquals(traits, analytics.traits())
95+
}
96+
}
97+
}

core/src/test/kotlin/com/segment/analytics/kotlin/core/compat/BuildersTest.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,11 @@ internal class BuildersTest {
121121
put("double", 1.0)
122122
put("string", "1")
123123
put("boolean", true)
124-
putJsonObject("object") {
125-
it.put("string", "this is object")
124+
putJsonObjectFunc("object") {
125+
put("string", "this is object")
126126
}
127-
putJsonArray("array") {
128-
it.add("this is array")
127+
putJsonArrayFunc("array") {
128+
add("this is array")
129129
}
130130
}
131131

@@ -161,11 +161,11 @@ internal class BuildersTest {
161161
add(1.0)
162162
add("1")
163163
add(true)
164-
addJsonObject() {
165-
it.put("string", "this is object")
164+
addJsonObjectFunc {
165+
put("string", "this is object")
166166
}
167-
addJsonArray() {
168-
it.add("this is array")
167+
addJsonArrayFunc {
168+
add("this is array")
169169
}
170170
}
171171

core/src/test/kotlin/com/segment/analytics/kotlin/core/compat/JavaAnalyticsTest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ internal class JavaAnalyticsTest {
4242
mockPlugin = spyk(StubPlugin())
4343
}
4444

45+
@Test
46+
fun `secondary constructor properly setup analytics`() {
47+
val actual = JavaAnalytics(analytics.analytics)
48+
assertNotNull(actual.analytics)
49+
assertEquals(analytics.analytics, actual.analytics)
50+
}
51+
4552
@Nested
4653
inner class Track {
4754

core/src/test/kotlin/com/segment/analytics/kotlin/core/DestinationPluginTests.kt renamed to core/src/test/kotlin/com/segment/analytics/kotlin/core/platform/DestinationPluginTests.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
package com.segment.analytics.kotlin.core
1+
package com.segment.analytics.kotlin.core.platform
22

33
import com.segment.analytics.kotlin.core.*
44
import com.segment.analytics.kotlin.core.utils.mockAnalytics
5-
import com.segment.analytics.kotlin.core.platform.DestinationPlugin
6-
import com.segment.analytics.kotlin.core.platform.Plugin
7-
import com.segment.analytics.kotlin.core.platform.Timeline
85
import com.segment.analytics.kotlin.core.utilities.putInContext
96
import io.mockk.spyk
107
import io.mockk.verify

0 commit comments

Comments
 (0)