1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-09-11 17:15:34 +03:00

Fix MsgpackRpc Neovim example

This commit is contained in:
Tae Won Ha 2023-12-23 17:38:31 +01:00
parent a8be0f282c
commit 2b7afdd5e1
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
5 changed files with 451 additions and 613 deletions

View File

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4B0225EF224AAE260052362B"
BuildableName = "MinimalNvimViewDemo.app"
BlueprintName = "MinimalNvimViewDemo"
ReferencedContainer = "container:NvimViewSupport.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4B0225EF224AAE260052362B"
BuildableName = "MinimalNvimViewDemo.app"
BlueprintName = "MinimalNvimViewDemo"
ReferencedContainer = "container:NvimViewSupport.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4B0225EF224AAE260052362B"
BuildableName = "MinimalNvimViewDemo.app"
BlueprintName = "MinimalNvimViewDemo"
ReferencedContainer = "container:NvimViewSupport.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,65 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Nimble
import RxBlocking
import RxPack
import RxSwift
import XCTest
@testable import RxPack
class RxMessagePortTest: XCTestCase {
let disposeBag = DisposeBag()
let serverName = "com.qvacua.RxPack.RxMessagePortTest.server.\(UUID().uuidString)"
let server = RxMessagePortServer(queueQos: .default)
let client = RxMessagePortClient(queueQos: .default)
override func setUp() {
super.setUp()
self.server
.stream
.subscribe(onNext: nil)
.disposed(by: self.disposeBag)
_ = try! self.server
.run(as: self.serverName)
.andThen(self.client.connect(to: self.serverName))
.toBlocking()
.first()
}
override func tearDown() {
super.tearDown()
_ = try! self.client
.stop()
.andThen(self.server.stop())
.toBlocking()
.first()
}
func testSth() {
self.server
.syncReplyBody = { msgid, inputData in data("response-to-\(msgid)-\(str(inputData))") }
var response = try! self.client
.send(msgid: 0, data: data("first-msg"), expectsReply: true)
.toBlocking()
.first()!
expect(str(response)).to(equal("response-to-0-first-msg"))
response = try! self.client
.send(msgid: 1, data: data("second-msg"), expectsReply: true)
.toBlocking()
.first()!
expect(str(response)).to(equal("response-to-1-second-msg"))
}
}
private func str(_ data: Data?) -> String { String(data: data!, encoding: .utf8)! }
private func data(_ str: String) -> Data { str.data(using: .utf8)! }

View File

@ -1,85 +1,148 @@
/// Tae Won Ha - http://taewon.de - @hataewon
/// See LICENSE
import Nimble
import RxBlocking
import RxPack
import RxSwift
import XCTest
extension PrimitiveSequenceType {
func waitCompletion() throws {
_ = try self.primitiveSequence.toBlocking().first()
}
}
private func delayingCompletable() -> Completable {
Single.just(0)
.delay(.milliseconds(10), scheduler: MainScheduler.instance)
.asCompletable()
}
/// No real test, just a sample code to see that it works with Neovim: Execute
///
/// ```bash
/// NVIM_LISTEN_ADDRESS=/tmp/nvim.sock nvim --headless $SOMEFILE
/// ```
///
/// in Terminal and rename xtestExample() to testExample() to run.
class RxMsgpackRpcNeovimExample: XCTestCase {
let connection = RxMsgpackRpc(queueQos: .default)
let rpc = RxMsgpackRpc(queueQos: .default)
let disposeBag = DisposeBag()
var proc: Process!
override func setUp() {
super.setUp()
self.connection.stream
.subscribe(
onNext: { msg in
switch msg {
case let .notification(method, params):
print("NOTIFICATION: \(method): array of \(params.count) elements")
case let .error(value, msg):
print("ERROR: \(msg) with \(value)")
default:
print("???")
}
},
onError: { print("ERROR: \($0)") },
onCompleted: { print("COMPLETED!") }
)
.disposed(by: self.disposeBag)
self.rpc.stream.subscribe(
onNext: { msg in
switch msg {
case let .notification(method, params):
print("NOTIFICATION: \(method): array of \(params.count) elements")
case let .error(value, msg):
print("ERROR: \(msg) with \(value)")
case let .response(msgid, error, result):
print("RESPONSE: \(msgid), \(error), \(result)")
default:
fail("Unknown msg type from rpc")
}
},
onError: { print("ERROR: \($0)") },
onCompleted: { print("COMPLETED!") }
)
.disposed(by: self.disposeBag)
_ = try! self.connection.run(at: "/tmp/nvim.sock").toBlocking().first()
self.proc = self.neovimProcess()
let inPipe = self.proc.standardInput as! Pipe
let outPipe = self.proc.standardOutput as! Pipe
let errorPipe = self.proc.standardError as! Pipe
try! self.proc.run()
try! self.rpc.run(inPipe: inPipe, outPipe: outPipe, errorPipe: errorPipe).waitCompletion()
}
override func tearDown() {
super.tearDown()
_ = try! self.connection
.request(
method: "nvim_command", params: [.string("q!")],
expectsReturnValue: false
)
.toBlocking()
.first()
try! self.rpc.request(
method: "nvim_command", params: [.string("q!")],
expectsReturnValue: false
).waitCompletion()
_ = try! self.connection.stop().toBlocking().first()
try! self.rpc.stop().waitCompletion()
self.proc.waitUntilExit()
}
func xtestExample() {
let lineCount = try! self.connection
.request(
method: "nvim_buf_line_count",
params: [.int(0)],
expectsReturnValue: true
)
.toBlocking()
.first()
print(lineCount!)
func testExample() throws {
try self.rpc.request(
method: "nvim_ui_attach",
params: [80, 24, [:]],
expectsReturnValue: false
).waitCompletion()
let formatter = DateFormatter()
formatter.dateFormat = "mm:ss.SSS"
for i in 0...100 {
let date = Date()
let response = try! self.connection
let response = try self.rpc
.request(
method: "nvim_command_output",
params: [.string("echo '\(i) \(formatter.string(from: date))'")],
expectsReturnValue: true
)
.toBlocking()
.first()
.toBlocking().first()!
print(response!)
Swift.print(response)
}
let testFileUrl: URL = FileManager.default
.homeDirectoryForCurrentUser.appending(components: "test/big.swift")
guard FileManager.default.fileExists(atPath: testFileUrl.path) else {
try self.rpc.request(method: "nvim_ui_detach", params: [], expectsReturnValue: false)
.waitCompletion()
return
}
try self.rpc.request(
method: "nvim_command",
params: [.string("e \(testFileUrl.path)")],
expectsReturnValue: false
).waitCompletion()
let lineCount = try self.rpc.request(
method: "nvim_buf_line_count",
params: [.int(0)],
expectsReturnValue: true
)
.toBlocking().first()!
Swift.print("Line count of \(testFileUrl): \(lineCount)")
let repeatCount = 200
for _ in 0...repeatCount {
try self.rpc
.request(method: "nvim_input", params: ["<PageDown>"], expectsReturnValue: false)
.waitCompletion()
try delayingCompletable().waitCompletion()
}
for _ in 0...repeatCount {
try self.rpc
.request(method: "nvim_input", params: ["<PageUp>"], expectsReturnValue: false)
.waitCompletion()
try delayingCompletable().waitCompletion()
}
Thread.sleep(forTimeInterval: 1)
try self.rpc.request(method: "nvim_ui_detach", params: [], expectsReturnValue: false)
.waitCompletion()
}
private func neovimProcess() -> Process {
let inPipe = Pipe()
let outPipe = Pipe()
let errorPipe = Pipe()
let process = Process()
process.executableURL = URL(fileURLWithPath: "/opt/homebrew/bin/nvim")
process.standardInput = inPipe
process.standardError = errorPipe
process.standardOutput = outPipe
process.arguments = ["--embed"]
return process
}
}

View File

@ -7,347 +7,346 @@ import Nimble
import RxBlocking
import RxPack
import RxSwift
import Socket
import XCTest
class RxMsgpackRpcrTests: XCTestCase {
typealias Value = RxMsgpackRpc.Value
typealias Message = RxMsgpackRpc.Message
typealias MessageType = RxMsgpackRpc.MessageType
var testFinished = false
let testFinishedCond = NSCondition()
var serverReady = false
let serverReadyCond = NSCondition()
var server: TestServer!
var clientSocket: Socket!
let msgpackRpc = RxMsgpackRpc(queueQos: .default)
var requestsFromClient = [[Value]]()
let responseScheduler = ConcurrentDispatchQueueScheduler(qos: .default)
let disposeBag = DisposeBag()
let uuid = UUID().uuidString
override func setUp() {
super.setUp()
self.server = TestServer(
path: FileManager.default
.temporaryDirectory
.appendingPathComponent("\(self.uuid).sock")
.path
)
self.server.queue.async {
self.server.waitForClientAndStartReading()
self.clientSocket = self.server.connectedSocket
self.serverReadyCond.lock()
self.serverReady = true
self.serverReadyCond.signal()
self.serverReadyCond.unlock()
}
}
override func tearDown() {
_ = try! self.msgpackRpc.stop().toBlocking().first()
self.server.shutdownServer()
super.tearDown()
}
func testResponsesFromServer() {
self.runClient(readBufferSize: Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE)
var beginAssertion = false
let beginAssertionCond = NSCondition()
self.assertMsgsFromClient { data, _ in
// WARNING:
// - Sometimes, the first and the second message get coalesced to one read operation by the
// server.
// - Sometimes, second message arrives first.
let requests = try! unpackAll(data)
.map(\.arrayValue!)
.sorted { left, right in left[2].stringValue! < right[2].stringValue! }
for request in requests {
expect(request).to(haveCount(4))
self.requestsFromClient.append(request)
if request[2].stringValue! == "2-second-request" {
beginAssertionCond.lock()
beginAssertion = true
beginAssertionCond.signal()
beginAssertionCond.unlock()
}
}
}
var responseCount = 0
self.sendRequests {
self.msgpackRpc
.request(method: "1-first-request", params: [.uint(123)], expectsReturnValue: true)
.subscribe(on: self.responseScheduler)
.subscribe(onSuccess: { response in
expect(response.error).to(equal(.nil))
expect(response.result).to(equal(.float(0.321)))
responseCount += 1
self.signalEndOfTest()
})
.disposed(by: self.disposeBag)
self.msgpackRpc
.request(method: "2-second-request", params: [.uint(321)], expectsReturnValue: true)
.subscribe(on: self.responseScheduler)
.subscribe(onSuccess: { response in
expect(response.error).to(equal(.nil))
expect(response.result).to(equal(.float(0.123)))
responseCount += 1
})
.disposed(by: self.disposeBag)
beginAssertionCond.lock()
while beginAssertion == false {
beginAssertionCond.wait(until: Date(timeIntervalSinceNow: 2 * 60))
}
beginAssertionCond.unlock()
let request1 = self.requestsFromClient[0]
expect(request1[0].uint64Value).to(equal(MessageType.request.rawValue))
expect(request1[2].stringValue).to(equal("1-first-request"))
expect(request1[3].arrayValue).to(equal([.uint(123)]))
let request2 = self.requestsFromClient[1]
expect(request2[0].uint64Value).to(equal(MessageType.request.rawValue))
expect(request2[2].stringValue).to(equal("2-second-request"))
expect(request2[3].arrayValue).to(equal([.uint(321)]))
try! self.clientSocket
.write(from: self.dataForResponse(msgid: 1, error: .nil, params: .float(0.123)))
try! self.clientSocket
.write(from: self.dataForResponse(msgid: 0, error: .nil, params: .float(0.321)))
}
expect(responseCount).to(equal(2))
}
func testNotificationsFromServer() {
DispatchQueue.global(qos: .default).async {
let msgs = try! self.msgpackRpc.stream.toBlocking().toArray()
expect(msgs).to(haveCount(2))
let (method1, params1) = self.notification(from: msgs[0])
let (method2, params2) = self.notification(from: msgs[1])
expect(method1).to(equal("first-msg"))
expect(params1).to(haveCount(2))
expect(params1[0].uintValue).to(equal(321))
expect(params1[1].dataValue).to(haveCount(321))
expect(method2).to(equal("second-msg"))
expect(params2).to(haveCount(2))
expect(params2[0].dataValue).to(haveCount(123))
expect(params2[1].floatValue).to(equal(0.123))
self.signalEndOfTest()
}
self.runClient(readBufferSize: Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE)
self.sendRequests {
let data1 = dataForNotification(
method: "first-msg",
params: [.uint(321), .binary(.random(ofCount: 321))]
)
let data2 = dataForNotification(
method: "second-msg",
params: [.binary(.random(ofCount: 123)), .float(0.123)]
)
try! self.clientSocket.write(from: data1)
try! self.clientSocket.write(from: data2)
self.server.shutdownServer()
}
}
func testPartialRequestFromServer() {
DispatchQueue.global(qos: .default).async {
let msgs = try! self.msgpackRpc.stream.toBlocking().toArray()
expect(msgs).to(haveCount(2))
let (method1, params1) = self.notification(from: msgs[0])
let (method2, params2) = self.notification(from: msgs[1])
expect(method1).to(equal("first-msg"))
expect(params1).to(haveCount(2))
expect(params1[0].uintValue).to(equal(321))
expect(params1[1].dataValue).to(haveCount(321))
expect(method2).to(equal("second-msg"))
expect(params2).to(haveCount(2))
expect(params2[0].dataValue).to(haveCount(123))
expect(params2[1].floatValue).to(equal(0.123))
self.signalEndOfTest()
}
self.runClient(readBufferSize: Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE)
self.sendRequests {
let data1 = dataForNotification(
method: "first-msg",
params: [.uint(321), .binary(.random(ofCount: 321))]
)
let data2 = dataForNotification(
method: "second-msg",
params: [.binary(.random(ofCount: 123)), .float(0.123)]
)
var msg1 = data1
msg1.append(data2[..<100])
let msg2 = data2[100...]
try! self.clientSocket.write(from: msg1)
try! self.clientSocket.write(from: msg2)
self.server.shutdownServer()
}
}
}
extension RxMsgpackRpcrTests {
func dataForResponse(msgid: UInt64, error: Value, params: Value) -> Data {
pack(.array([
.uint(MessageType.response.rawValue),
.uint(msgid),
error,
params,
]))
}
func dataForNotification(method: String, params: [Value]) -> Data {
pack(.array([
.uint(MessageType.notification.rawValue),
.string(method),
.array(params),
]))
}
func assertMsgsFromClient(assertFn: @escaping TestServer.DataReadCallback) {
self.server.dataReadCallback = assertFn
}
func runClient(readBufferSize: Int) {
usleep(500)
_ = try! self.msgpackRpc
.run(at: self.server.path, readBufferSize: readBufferSize)
.toBlocking()
.first()
self.serverReadyCond.lock()
while self.serverReady == false {
self.serverReadyCond.wait(until: Date(timeIntervalSinceNow: 2 * 60))
}
self.serverReadyCond.unlock()
}
func sendRequests(requestFn: () -> Void) {
requestFn()
self.waitForAssertions()
}
func signalEndOfTest() {
self.testFinishedCond.lock()
self.testFinished = true
self.testFinishedCond.signal()
self.testFinishedCond.unlock()
}
func waitForAssertions() {
var signalled = false
self.testFinishedCond.lock()
while self.testFinished == false {
signalled = self.testFinishedCond.wait(until: Date(timeIntervalSinceNow: 2 * 60))
}
expect(signalled).to(beTrue())
self.testFinishedCond.unlock()
}
func notification(from msg: Message) -> (method: String, params: [Value]) {
guard case let .notification(method, params) = msg else {
preconditionFailure("\(msg) is not a notification")
}
return (method: method, params: params)
}
}
/// Modified version of the example in the README of https://github.com/Kitura/BlueSocket.
/// It only supports one connection. Everywhere ! and no error handling whatsoever.
class TestServer {
typealias DataReadCallback = (Data, Int) -> Void
let queue = DispatchQueue(label: "com.qvacua.RxPack.TestServer")
var connectedSocket: Socket!
var path: String
var readBufferSize: Int = 1024 * 1024
var dataReadCallback: DataReadCallback = { _, _ in }
private var listenSocket: Socket!
init(path: String) { self.path = path }
deinit { self.shutdownServer() }
func waitForClientAndStartReading() {
self.listenSocket = try! Socket.create(family: .unix)
try! self.listenSocket.listen(on: self.path)
let newSocket = try! self.listenSocket.acceptClientConnection()
self.connectedSocket = newSocket
self.readData(from: newSocket)
}
func readData(from socket: Socket) {
self.queue.async { [unowned self] in
var shouldKeepRunning = true
var readData = Data(capacity: self.readBufferSize)
repeat {
guard let bytesRead = try? socket.read(into: &readData) else {
shouldKeepRunning = false
break
}
if bytesRead > 0 {
self.dataReadCallback(readData, bytesRead)
} else {
shouldKeepRunning = false
break
}
readData.count = 0
} while shouldKeepRunning
socket.close()
}
}
func shutdownServer() {
self.connectedSocket?.close()
self.listenSocket?.close()
}
}
extension Data {
static func random(ofCount count: Int) -> Data {
Data((0..<count).map { _ in UInt8.random(in: UInt8.min...UInt8.max) })
}
}
// class RxMsgpackRpcrTests: XCTestCase {
// typealias Value = RxMsgpackRpc.Value
// typealias Message = RxMsgpackRpc.Message
// typealias MessageType = RxMsgpackRpc.MessageType
//
// var testFinished = false
// let testFinishedCond = NSCondition()
//
// var serverReady = false
// let serverReadyCond = NSCondition()
//
// var server: TestServer!
// var clientSocket: Socket!
// let msgpackRpc = RxMsgpackRpc(queueQos: .default)
//
// var requestsFromClient = [[Value]]()
// let responseScheduler = ConcurrentDispatchQueueScheduler(qos: .default)
// let disposeBag = DisposeBag()
//
// let uuid = UUID().uuidString
//
// override func setUp() {
// super.setUp()
//
// self.server = TestServer(
// path: FileManager.default
// .temporaryDirectory
// .appendingPathComponent("\(self.uuid).sock")
// .path
// )
//
// self.server.queue.async {
// self.server.waitForClientAndStartReading()
// self.clientSocket = self.server.connectedSocket
//
// self.serverReadyCond.lock()
// self.serverReady = true
// self.serverReadyCond.signal()
// self.serverReadyCond.unlock()
// }
// }
//
// override func tearDown() {
// _ = try! self.msgpackRpc.stop().toBlocking().first()
// self.server.shutdownServer()
//
// super.tearDown()
// }
//
// func testResponsesFromServer() {
// self.runClient(readBufferSize: Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE)
//
// var beginAssertion = false
// let beginAssertionCond = NSCondition()
//
// self.assertMsgsFromClient { data, _ in
// // WARNING:
// // - Sometimes, the first and the second message get coalesced to one read operation by the
// // server.
// // - Sometimes, second message arrives first.
// let requests = try! unpackAll(data)
// .map(\.arrayValue!)
// .sorted { left, right in left[2].stringValue! < right[2].stringValue! }
//
// for request in requests {
// expect(request).to(haveCount(4))
// self.requestsFromClient.append(request)
//
// if request[2].stringValue! == "2-second-request" {
// beginAssertionCond.lock()
// beginAssertion = true
// beginAssertionCond.signal()
// beginAssertionCond.unlock()
// }
// }
// }
//
// var responseCount = 0
// self.sendRequests {
// self.msgpackRpc
// .request(method: "1-first-request", params: [.uint(123)], expectsReturnValue: true)
// .subscribe(on: self.responseScheduler)
// .subscribe(onSuccess: { response in
// expect(response.error).to(equal(.nil))
// expect(response.result).to(equal(.float(0.321)))
// responseCount += 1
//
// self.signalEndOfTest()
// })
// .disposed(by: self.disposeBag)
//
// self.msgpackRpc
// .request(method: "2-second-request", params: [.uint(321)], expectsReturnValue: true)
// .subscribe(on: self.responseScheduler)
// .subscribe(onSuccess: { response in
// expect(response.error).to(equal(.nil))
// expect(response.result).to(equal(.float(0.123)))
// responseCount += 1
// })
// .disposed(by: self.disposeBag)
//
// beginAssertionCond.lock()
// while beginAssertion == false {
// beginAssertionCond.wait(until: Date(timeIntervalSinceNow: 2 * 60))
// }
// beginAssertionCond.unlock()
//
// let request1 = self.requestsFromClient[0]
// expect(request1[0].uint64Value).to(equal(MessageType.request.rawValue))
// expect(request1[2].stringValue).to(equal("1-first-request"))
// expect(request1[3].arrayValue).to(equal([.uint(123)]))
//
// let request2 = self.requestsFromClient[1]
// expect(request2[0].uint64Value).to(equal(MessageType.request.rawValue))
// expect(request2[2].stringValue).to(equal("2-second-request"))
// expect(request2[3].arrayValue).to(equal([.uint(321)]))
//
// try! self.clientSocket
// .write(from: self.dataForResponse(msgid: 1, error: .nil, params: .float(0.123)))
//
// try! self.clientSocket
// .write(from: self.dataForResponse(msgid: 0, error: .nil, params: .float(0.321)))
// }
//
// expect(responseCount).to(equal(2))
// }
//
// func testNotificationsFromServer() {
// DispatchQueue.global(qos: .default).async {
// let msgs = try! self.msgpackRpc.stream.toBlocking().toArray()
// expect(msgs).to(haveCount(2))
//
// let (method1, params1) = self.notification(from: msgs[0])
// let (method2, params2) = self.notification(from: msgs[1])
//
// expect(method1).to(equal("first-msg"))
// expect(params1).to(haveCount(2))
// expect(params1[0].uintValue).to(equal(321))
// expect(params1[1].dataValue).to(haveCount(321))
//
// expect(method2).to(equal("second-msg"))
// expect(params2).to(haveCount(2))
// expect(params2[0].dataValue).to(haveCount(123))
// expect(params2[1].floatValue).to(equal(0.123))
//
// self.signalEndOfTest()
// }
//
// self.runClient(readBufferSize: Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE)
//
// self.sendRequests {
// let data1 = dataForNotification(
// method: "first-msg",
// params: [.uint(321), .binary(.random(ofCount: 321))]
// )
// let data2 = dataForNotification(
// method: "second-msg",
// params: [.binary(.random(ofCount: 123)), .float(0.123)]
// )
//
// try! self.clientSocket.write(from: data1)
// try! self.clientSocket.write(from: data2)
//
// self.server.shutdownServer()
// }
// }
//
// func testPartialRequestFromServer() {
// DispatchQueue.global(qos: .default).async {
// let msgs = try! self.msgpackRpc.stream.toBlocking().toArray()
// expect(msgs).to(haveCount(2))
//
// let (method1, params1) = self.notification(from: msgs[0])
// let (method2, params2) = self.notification(from: msgs[1])
//
// expect(method1).to(equal("first-msg"))
// expect(params1).to(haveCount(2))
// expect(params1[0].uintValue).to(equal(321))
// expect(params1[1].dataValue).to(haveCount(321))
//
// expect(method2).to(equal("second-msg"))
// expect(params2).to(haveCount(2))
// expect(params2[0].dataValue).to(haveCount(123))
// expect(params2[1].floatValue).to(equal(0.123))
//
// self.signalEndOfTest()
// }
//
// self.runClient(readBufferSize: Socket.SOCKET_MINIMUM_READ_BUFFER_SIZE)
// self.sendRequests {
// let data1 = dataForNotification(
// method: "first-msg",
// params: [.uint(321), .binary(.random(ofCount: 321))]
// )
// let data2 = dataForNotification(
// method: "second-msg",
// params: [.binary(.random(ofCount: 123)), .float(0.123)]
// )
//
// var msg1 = data1
// msg1.append(data2[..<100])
// let msg2 = data2[100...]
//
// try! self.clientSocket.write(from: msg1)
// try! self.clientSocket.write(from: msg2)
//
// self.server.shutdownServer()
// }
// }
// }
//
// extension RxMsgpackRpcrTests {
// func dataForResponse(msgid: UInt64, error: Value, params: Value) -> Data {
// pack(.array([
// .uint(MessageType.response.rawValue),
// .uint(msgid),
// error,
// params,
// ]))
// }
//
// func dataForNotification(method: String, params: [Value]) -> Data {
// pack(.array([
// .uint(MessageType.notification.rawValue),
// .string(method),
// .array(params),
// ]))
// }
//
// func assertMsgsFromClient(assertFn: @escaping TestServer.DataReadCallback) {
// self.server.dataReadCallback = assertFn
// }
//
// func runClient(readBufferSize: Int) {
// usleep(500)
// _ = try! self.msgpackRpc
// .run(at: self.server.path, readBufferSize: readBufferSize)
// .toBlocking()
// .first()
//
// self.serverReadyCond.lock()
// while self.serverReady == false {
// self.serverReadyCond.wait(until: Date(timeIntervalSinceNow: 2 * 60))
// }
// self.serverReadyCond.unlock()
// }
//
// func sendRequests(requestFn: () -> Void) {
// requestFn()
// self.waitForAssertions()
// }
//
// func signalEndOfTest() {
// self.testFinishedCond.lock()
// self.testFinished = true
// self.testFinishedCond.signal()
// self.testFinishedCond.unlock()
// }
//
// func waitForAssertions() {
// var signalled = false
// self.testFinishedCond.lock()
// while self.testFinished == false {
// signalled = self.testFinishedCond.wait(until: Date(timeIntervalSinceNow: 2 * 60))
// }
// expect(signalled).to(beTrue())
// self.testFinishedCond.unlock()
// }
//
// func notification(from msg: Message) -> (method: String, params: [Value]) {
// guard case let .notification(method, params) = msg else {
// preconditionFailure("\(msg) is not a notification")
// }
//
// return (method: method, params: params)
// }
// }
//
///// Modified version of the example in the README of https://github.com/Kitura/BlueSocket.
///// It only supports one connection. Everywhere ! and no error handling whatsoever.
// class TestServer {
// typealias DataReadCallback = (Data, Int) -> Void
//
// let queue = DispatchQueue(label: "com.qvacua.RxPack.TestServer")
// var connectedSocket: Socket!
//
// var path: String
// var readBufferSize: Int = 1024 * 1024
// var dataReadCallback: DataReadCallback = { _, _ in }
//
// private var listenSocket: Socket!
//
// init(path: String) { self.path = path }
// deinit { self.shutdownServer() }
//
// func waitForClientAndStartReading() {
// self.listenSocket = try! Socket.create(family: .unix)
//
// try! self.listenSocket.listen(on: self.path)
// let newSocket = try! self.listenSocket.acceptClientConnection()
// self.connectedSocket = newSocket
//
// self.readData(from: newSocket)
// }
//
// func readData(from socket: Socket) {
// self.queue.async { [unowned self] in
// var shouldKeepRunning = true
//
// var readData = Data(capacity: self.readBufferSize)
// repeat {
// guard let bytesRead = try? socket.read(into: &readData) else {
// shouldKeepRunning = false
// break
// }
//
// if bytesRead > 0 {
// self.dataReadCallback(readData, bytesRead)
// } else {
// shouldKeepRunning = false
// break
// }
//
// readData.count = 0
// } while shouldKeepRunning
//
// socket.close()
// }
// }
//
// func shutdownServer() {
// self.connectedSocket?.close()
// self.listenSocket?.close()
// }
// }
//
// extension Data {
// static func random(ofCount count: Int) -> Data {
// Data((0..<count).map { _ in UInt8.random(in: UInt8.min...UInt8.max) })
// }
// }

View File

@ -1,82 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BEBA5041CFF374B00673FDF"
BuildableName = "VimR.app"
BlueprintName = "VimR"
ReferencedContainer = "container:VimR.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BEBA5041CFF374B00673FDF"
BuildableName = "VimR.app"
BlueprintName = "VimR"
ReferencedContainer = "container:VimR.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
referenceType = "1">
</LocationScenarioReference>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BEBA5041CFF374B00673FDF"
BuildableName = "VimR.app"
BlueprintName = "VimR"
ReferencedContainer = "container:VimR.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>