Skip to content

Commit 574f975

Browse files
Merge pull request #2 from michallaskowski/add-tests
Add tests
2 parents e770f5a + 767fb16 commit 574f975

File tree

13 files changed

+253
-26
lines changed

13 files changed

+253
-26
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Run tests
2+
on:
3+
push:
4+
branches:
5+
- master
6+
pull_request:
7+
branches:
8+
- master
9+
10+
jobs:
11+
android_tests:
12+
name: Android tests
13+
runs-on: ubuntu-18.04
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v2
17+
- name: Cache gradle dependencies
18+
uses: actions/cache@v2
19+
with:
20+
path: ~/.gradle/caches
21+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
22+
restore-keys: |
23+
${{ runner.os }}-gradle-
24+
- name: Set up JDK 1.8
25+
uses: actions/setup-java@v1
26+
with:
27+
java-version: 1.8
28+
- name: Tests
29+
run: bash ./gradlew library:testDebugUnitTest
30+
31+
ios_tests:
32+
name: iOS Tests
33+
runs-on: macOS-latest
34+
steps:
35+
- name: Checkout
36+
uses: actions/checkout@v2
37+
with:
38+
lfs: true
39+
- name: Cache gradle dependencies
40+
uses: actions/cache@v2
41+
with:
42+
path: ~/.gradle/caches
43+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
44+
restore-keys: |
45+
${{ runner.os }}-gradle-
46+
- name: Cache Kotlin Native dependencies
47+
uses: actions/cache@v2
48+
with:
49+
path: |
50+
~/.konan/kotlin-native-macos-*
51+
~/.konan/dependencies
52+
key: ${{ runner.os }}-kotlin-native-${{ hashFiles('build.gradle') }}
53+
restore-keys: |
54+
${{ runner.os }}-kotlin-native-
55+
- name: Select Xcode 11.4
56+
run: sudo xcode-select -s /Applications/Xcode_11.4.app
57+
- name: Boot simulator
58+
run: xcrun simctl boot "iPhone 8"
59+
- name: Tests
60+
run: ./gradlew library:iosTest

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ buildscript {
1717

1818
allprojects {
1919

20-
group 'dev.michallaskowski.kuiks'
20+
group 'dev.michallaskowski.mokttp'
2121
version = '0.0.1'
2222

2323
repositories {

library/build.gradle

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ android {
1010
targetSdkVersion 29
1111
versionCode 1
1212
versionName "1.0"
13+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1314
}
1415
buildTypes {
1516
release {
@@ -37,6 +38,7 @@ kotlin {
3738
embedBitcode("disable")
3839
linkerOpts("-F$projectDir/../Carthage/Build/iOS")
3940
}
41+
getTest("DEBUG").linkerOpts("-F$projectDir/../Carthage/Build/iOS", "-framework", "GCDWebServers")
4042
}
4143

4244
compilations.main.cinterops {
@@ -60,29 +62,68 @@ kotlin {
6062
}
6163
}
6264

63-
// posixMain {
64-
// kotlin.srcDir("src/posix/kotlin")
65-
// dependencies {
66-
// implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core-native', version: "1.3.4"
67-
// }
68-
// }
65+
commonTest {
66+
dependencies {
67+
implementation 'org.jetbrains.kotlin:kotlin-test-common'
68+
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
69+
implementation 'io.ktor:ktor-client-core:1.3.2'
70+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5-native-mt'
71+
}
72+
}
6973

7074
androidMain {
71-
dependencies {
72-
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
73-
implementation 'com.squareup.okhttp3:mockwebserver:4.4.0'
74-
api 'com.squareup.okio:okio:2.6.0' // needed because of actual typalias Data
75-
}
75+
dependencies {
76+
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
77+
implementation 'com.squareup.okhttp3:mockwebserver:4.4.0'
78+
api 'com.squareup.okio:okio:2.6.0' // needed because of actual typalias Data
79+
}
7680
}
7781

78-
iosMain {
79-
// kotlin.srcDirs('src/posix/kotlin')
80-
// dependsOn posixMain
82+
androidTest {
83+
dependencies {
84+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.5-native-mt'
85+
implementation 'androidx.test.ext:junit:1.1.1'
86+
implementation 'org.robolectric:robolectric:4.3.1'
87+
implementation 'org.jetbrains.kotlin:kotlin-test'
88+
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
89+
implementation 'io.ktor:ktor-client-android:1.3.2'
90+
}
91+
}
92+
93+
iosTest {
94+
dependencies {
95+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.5-native-mt'
96+
implementation 'io.ktor:ktor-client-ios:1.3.2'
97+
}
8198
}
8299

83-
// macOsMain {
84-
// kotlin.srcDirs('src/iOSMain/kotlin')
85-
//// dependsOn posixMain
86-
// }
87100
}
88-
}
101+
}
102+
103+
def testOutputFile() {
104+
return kotlin.targets["iosX64"].binaries.getTest('DEBUG').outputFile
105+
}
106+
107+
task copyGCDWebServers(type: Copy) {
108+
def testDir = testOutputFile().parentFile.absolutePath
109+
def path = "$testDir/Frameworks/GCDWebServers.framework"
110+
111+
from "$projectDir/../Carthage/Build/iOS/GCDWebServers.framework"
112+
into path
113+
}
114+
115+
task iosTest {
116+
dependsOn 'linkDebugTestIosX64'
117+
group = JavaBasePlugin.VERIFICATION_GROUP
118+
description = "Runs tests for target 'ios' on an iOS simulator"
119+
120+
doLast {
121+
def binary = testOutputFile().absolutePath
122+
exec {
123+
commandLine 'xcrun', 'simctl', 'spawn', 'booted', binary
124+
}
125+
}
126+
}
127+
128+
iosTest.dependsOn copyGCDWebServers
129+
copyGCDWebServers.mustRunAfter(linkDebugTestIosX64)

library/src/androidMain/kotlin/actual.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ private class DispatcherImpl: Dispatcher() {
3232

3333
if (it.body != null) {
3434
setBody(it.body)
35+
} else {
36+
setHeader("Content-Length", 0)
3537
}
3638
}
3739
} ?: MockResponse()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import kotlinx.coroutines.CoroutineScope
5+
import kotlinx.coroutines.runBlocking
6+
import org.junit.Rule
7+
import org.junit.runner.RunWith
8+
9+
@RunWith(AndroidJUnit4::class)
10+
actual abstract class BaseTest {
11+
@get:Rule
12+
var coroutineTestRule = CoroutineTestRule()
13+
14+
actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
15+
runBlocking { block() }
16+
}
17+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import kotlinx.coroutines.Dispatchers
4+
import kotlinx.coroutines.ExecutorCoroutineDispatcher
5+
import kotlinx.coroutines.newSingleThreadContext
6+
import kotlinx.coroutines.test.resetMain
7+
import kotlinx.coroutines.test.setMain
8+
import org.junit.rules.TestWatcher
9+
import org.junit.runner.Description
10+
11+
/**
12+
* Use this rule to update the Main dispatcher ahead of tests. By delegating the main dispatcher to a new thread.
13+
* we can block the current thread and still dispatch main coroutines
14+
*/
15+
class CoroutineTestRule(
16+
private val testDispatcher: ExecutorCoroutineDispatcher = newSingleThreadContext("UI thread")
17+
) : TestWatcher() {
18+
override fun starting(description: Description?) {
19+
super.starting(description)
20+
Dispatchers.setMain(testDispatcher)
21+
}
22+
23+
override fun finished(description: Description?) {
24+
super.finished(description)
25+
Dispatchers.resetMain()
26+
}
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import kotlinx.coroutines.CoroutineScope
4+
5+
// based on https://github.com/touchlab/KaMPKit/blob/master/shared/src/commonTest/kotlin/co/touchlab/kampkit/BaseTest.kt
6+
expect abstract class BaseTest() {
7+
fun <T> runTest(block: suspend CoroutineScope.() -> T)
8+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import io.ktor.client.HttpClient
4+
import io.ktor.client.request.get
5+
import io.ktor.client.statement.HttpResponse
6+
import io.ktor.http.HttpStatusCode
7+
import kotlin.test.AfterTest
8+
import kotlin.test.BeforeTest
9+
import kotlin.test.Test
10+
import kotlin.test.assertEquals
11+
12+
class HttpServerTest: BaseTest() {
13+
14+
private lateinit var server: HttpServer
15+
private lateinit var client: HttpClient
16+
17+
@BeforeTest
18+
fun setup() = runTest {
19+
server = HttpServer()
20+
client = HttpClient()
21+
}
22+
23+
@AfterTest
24+
fun teardown() = runTest {
25+
// todo: server close
26+
client.close()
27+
}
28+
29+
@Test
30+
fun returnsResponsePerPath() = runTest {
31+
server.router = object: Router {
32+
override fun handleRequest(request: Request): Response {
33+
if (request.path != "/test") {
34+
return Response(404, emptyMap(), null, null)
35+
}
36+
return Response(200, emptyMap(), Data("test"), "text/plain")
37+
}
38+
}
39+
40+
server.start(8080)
41+
42+
val response = client.get<String>("http://localhost:8080/test")
43+
assertEquals(response, "test")
44+
45+
val httpResponse = client.get<HttpResponse>("http://localhost:8080/notTest")
46+
assertEquals(httpResponse.status, HttpStatusCode.NotFound)
47+
}
48+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import kotlinx.coroutines.CoroutineScope
4+
import kotlinx.coroutines.Dispatchers
5+
import kotlinx.coroutines.GlobalScope
6+
import kotlinx.coroutines.launch
7+
import platform.CoreFoundation.CFRunLoopGetCurrent
8+
import platform.CoreFoundation.CFRunLoopRun
9+
import platform.CoreFoundation.CFRunLoopStop
10+
11+
actual abstract class BaseTest {
12+
actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
13+
var error: Throwable? = null
14+
GlobalScope.launch(Dispatchers.Main) {
15+
try {
16+
block()
17+
} catch (t: Throwable) {
18+
error = t
19+
} finally {
20+
CFRunLoopStop(CFRunLoopGetCurrent())
21+
}
22+
}
23+
CFRunLoopRun()
24+
error?.also { throw it }
25+
}
26+
}

sample-android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ dependencies {
4949
implementation 'androidx.recyclerview:recyclerview:1.1.0'
5050
implementation 'androidx.recyclerview:recyclerview-selection:1.0.0'
5151

52-
implementation project(':mokttp')
52+
implementation project(':library')
5353
implementation project(':sample-sharedCode')
5454

5555
testImplementation 'junit:junit:4.13'

0 commit comments

Comments
 (0)