Skip to content

Commit 893381b

Browse files
committed
create test to prove getService is not thread safe
Create test to confirm that ServiceBuilder.getService() should return the same instance, even when accessed from two threads. To ensure the test is consistent we made the constructor slow so the thread both end on the same line of code.
1 parent 221a02e commit 893381b

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.onesignal.common
2+
3+
import com.onesignal.common.services.ServiceBuilder
4+
import com.onesignal.common.services.ServiceProvider
5+
import io.kotest.core.spec.style.FunSpec
6+
import io.kotest.matchers.types.shouldBeSameInstanceAs
7+
import java.util.concurrent.LinkedBlockingQueue
8+
9+
internal interface IMyTestInterface
10+
11+
internal class MySlowConstructorClass : IMyTestInterface {
12+
init {
13+
// NOTE: Keep these println calls, otherwise Kotlin optimizes
14+
// something which cases the test not fail when it should.
15+
println("MySlowConstructorClass BEFORE")
16+
Thread.sleep(10)
17+
println("MySlowConstructorClass AFTER")
18+
}
19+
}
20+
21+
class ServiceProviderTest : FunSpec({
22+
23+
fun setupServiceProviderWithSlowInitClass(): ServiceProvider {
24+
val serviceBuilder = ServiceBuilder()
25+
serviceBuilder.register<MySlowConstructorClass>().provides<IMyTestInterface>()
26+
return serviceBuilder.build()
27+
}
28+
29+
test("getService is thread safe") {
30+
val services = setupServiceProviderWithSlowInitClass()
31+
32+
val queue = LinkedBlockingQueue<IMyTestInterface>()
33+
Thread {
34+
queue.add(services.getService<IMyTestInterface>())
35+
}.start()
36+
Thread {
37+
queue.add(services.getService<IMyTestInterface>())
38+
}.start()
39+
40+
val firstReference = queue.take()
41+
val secondReference = queue.take()
42+
firstReference shouldBeSameInstanceAs secondReference
43+
}
44+
})

0 commit comments

Comments
 (0)