Skip to content

Commit

Permalink
WIP new test server
Browse files Browse the repository at this point in the history
  • Loading branch information
joffrey-bion committed Feb 26, 2024
1 parent 64656f6 commit 7d4b737
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 0 deletions.
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "kto
ktor-client-websockets = { module = "io.ktor:ktor-client-websockets", version.ref = "ktor" }
ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
#ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
#ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }
#ktor-server-websockets = { module = "io.ktor:ktor-server-websockets", version.ref = "ktor" }
moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
moshiKotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
Expand Down
1 change: 1 addition & 0 deletions test-server/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ dependencyResolutionManagement {
}
}

//include("websocket-test-api")
include("websocket-test-server")
include("websocket-test-server-gradle-plugin")
39 changes: 39 additions & 0 deletions test-server/websocket-test-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//plugins {
// alias(libs.plugins.kotlin.multiplatform)
//}
//
//kotlin {
// jvm()
// js {
// browser()
// nodejs()
// }
// mingwX64()
// linuxX64()
// linuxArm64()
// macosX64()
// macosArm64()
// iosX64()
// iosArm64()
// iosSimulatorArm64()
// watchosX64()
// watchosArm32()
// watchosArm64()
// watchosDeviceArm64()
// watchosSimulatorArm64()
// tvosX64()
// tvosArm64()
// tvosSimulatorArm64()
// androidNativeArm32()
// androidNativeArm64()
// androidNativeX64()
// androidNativeX86()
//
// sourceSets {
// commonMain {
// dependencies {
//
// }
// }
// }
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.hildan.krossbow.websocket.test.api

//interface TestServer {
//
// val host: String
// val wsPort: Int
// val httpPort: Int
//
// fun socket(id: String): ServerSocket
//
// fun stop()
//}
//
//interface ServerSocket {
//
// /**
// * Sends text data to the last connected client.
// */
// suspend fun send(text: String)
//
// /**
// * Sends binary data to the last connected client.
// */
// suspend fun send(bytes: ByteArray)
//
// /**
// * Sends the closing handshake. May be sent in response to another handshake.
// */
// suspend fun close(code: Int, reason: String? = null)
//
// /**
// * Closes the connection immediately without a proper close handshake.
// *
// * The code and the message therefore won't be transferred over the wire also they will be forwarded to
// * onClose/onWebsocketClose.
// */
// suspend fun closeConnection(code: Int, message: String? = null)
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.hildan.krossbow.websocket.test.testcases

//object TestCases {
// val ALL = listOf(
// TestCase("1.1", "", events = emptyList())
// )
//}
//
//data class TestCase(
// val id: String,
// val description: String,
// val events: List<TestEvent>,
//)
//
//sealed interface TestEvent
//
//sealed interface ClientEvent : TestEvent {
// data class TextFrame(val payload: String) : ClientEvent
// data class BinaryFrame(val payload: ByteArray) : ClientEvent
// data class CloseFrame(val code: Int, val reason: String? = null) : ClientEvent
// data object ConnectionClosed : ClientEvent
//}
//
//sealed interface ServerEvent : TestEvent {
// data class TextFrame(val payload: String) : ServerEvent
// data class BinaryFrame(val payload: ByteArray) : ServerEvent
// data class CloseFrame(val code: Int, val reason: String? = null) : ServerEvent
// data object ConnectionClosed : ServerEvent
//}
4 changes: 4 additions & 0 deletions test-server/websocket-test-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ plugins {
dependencies {
implementation(libs.java.websocket)
implementation(libs.kotlinx.coroutines.core)
// implementation(libs.ktor.server.netty)
// implementation(libs.ktor.server.websockets)

// runtimeOnly(libs.slf4j.simple)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.hildan.krossbow.test.server

//import kotlinx.coroutines.*
//import kotlinx.coroutines.channels.*
//import org.java_websocket.*
//import org.java_websocket.handshake.*
//import org.java_websocket.server.*
//import java.net.*
//import java.nio.*
//
//suspend fun startWebSocketServer(address: InetSocketAddress = InetSocketAddress(0)): KWebSocketServer {
// val server = EventWebSocketServer(address).apply {
// start()
// awaitStarted()
// }
// return KWebSocketServerAdapter(server)
//}
//
//interface KWebSocketServer {
// val port: Int
// val events: ReceiveChannel<WSServerEvent>
// fun stop()
//}
//
//// can't implement directly because of "accidental override"
//private class KWebSocketServerAdapter(private val server: EventWebSocketServer): KWebSocketServer {
// override val port: Int
// get() = server.port
// override val events: ReceiveChannel<WSServerEvent>
// get() = server.events
//
// override fun stop() = server.stop()
//}
//
//sealed interface WSServerEvent {
//
// val socket: WebSocket?
//
// data class Handshake(
// override val socket: WebSocket,
// val url: String,
// val headers: Map<String, String>,
// val body: ByteArray,
// ) : WSServerEvent
//
// data class FrameReceived(
// override val socket: WebSocket,
// val frame: Frame,
// ) : WSServerEvent
//
// data class Error(
// override val socket: WebSocket?,
// val exception: Exception?,
// ) : WSServerEvent
//}
//
//sealed interface Frame {
// data class TextMessage(val content: String) : Frame
// data class BinaryMessage(val bytes: ByteArray) : Frame
// data class Close(val code: Int, val reason: String?, val fromClient: Boolean) : Frame
//}
//
//private class EventWebSocketServer(address: InetSocketAddress) : WebSocketServer(address) {
//
// val events: Channel<WSServerEvent> = Channel(Channel.BUFFERED)
//
// private val started: CompletableDeferred<Unit> = CompletableDeferred()
//
// override fun onStart() {
// started.complete(Unit)
// }
//
// suspend fun awaitStarted() {
// started.await()
// }
//
// override fun onOpen(conn: WebSocket, handshake: ClientHandshake) {
// val handshakeEvent = WSServerEvent.Handshake(
// socket = conn,
// url = handshake.resourceDescriptor,
// headers = handshake.readHeaders(),
// body = handshake.content,
// )
// events.trySendBlocking(handshakeEvent)
// }
//
// override fun onMessage(conn: WebSocket, message: String) {
// conn.send(message)
// events.trySendBlocking(WSServerEvent.FrameReceived(conn, Frame.TextMessage(message)))
// }
//
// override fun onMessage(conn: WebSocket, message: ByteBuffer) {
// val bytes = ByteArray(message.remaining())
// message.get(bytes)
// conn.send(bytes)
// events.trySendBlocking(WSServerEvent.FrameReceived(conn, Frame.BinaryMessage(bytes)))
// }
//
// override fun onClose(conn: WebSocket, code: Int, reason: String?, remote: Boolean) {
// events.trySendBlocking(WSServerEvent.FrameReceived(conn, Frame.Close(code, reason, remote)))
// }
//
// override fun onError(conn: WebSocket?, ex: Exception?) {
// events.trySendBlocking(WSServerEvent.Error(conn, ex))
// }
//}
//
//private fun ClientHandshake.readHeaders(): Map<String, String> {
// val headerNames = iterateHttpFields()?.asSequence()?.toSet() ?: emptySet()
// return headerNames.associateWith { getFieldValue(it) }
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package org.hildan.krossbow.test.server

//import io.ktor.server.application.*
//import io.ktor.server.engine.*
//import io.ktor.server.netty.*
//import io.ktor.server.request.*
//import io.ktor.server.response.*
//import io.ktor.server.routing.*
//
//suspend fun startTestServerNew(): TestServer {
// println("Starting test WS server...")
// val wsServer = startWebSocketServer()
// val wsPort = wsServer.port
// println("Test WS server listening on port $wsPort")
//
// println("Starting test HTTP server...")
// val httpServer = startHttpServer(WebSocketTestServer(wsServer))
// val httpPort = httpServer.resolvedConnectors().first().port
// println("Test HTTP server listening on port $httpPort")
//
// return object : TestServer {
// override val host: String = "localhost"
// override val wsPort: Int get() = wsPort
// override val httpPort: Int get() = httpPort
//
// override fun stop() {
// wsServer.stop()
// }
// }
//}
//
//class WebSocketTestServer(server: KWebSocketServer) {
//
//}
//
//fun startHttpServer(wsServer: WebSocketTestServer): NettyApplicationEngine {
// return embeddedServer(
// factory = Netty,
// port = 0,
// host = "0.0.0.0",
// ) {
// module(wsServer)
// }.start(wait = false)
//}
//
//private fun Application.module(wsServer: WebSocketTestServer) {
// routing {
// get("hello") {
// call.respondText("Hello")
// }
// route("connection/{connectionId}") {
// post("sendText") {
// val connectionId = call.connectionIdParam
// println(connectionId)
// val body = call.receiveText()
//// wsServer.socket(connectionId).send(body)
// }
// post("close") {
// val connectionId = call.connectionIdParam
//// wsServer.socket(connectionId).close(0) // TODO
// }
// }
// }
//}
//
//private val ApplicationCall.connectionIdParam
// get() = parameters["connectionId"] ?: error("Missing connectionId parameter")

0 comments on commit 7d4b737

Please sign in to comment.