swift - 为什么 XMPPFramework 会阻塞?

标签 swift unit-testing concurrency xctest xmppframework

我们正在尝试获取 XMPPFramework 运行的最小示例。

考虑这个简单的类:

import Foundation
import XMPPFramework

class Connection: NSObject, XMPPStreamDelegate {
    let stream: XMPPStream

    override init() {
        self.stream = XMPPStream()!
    }

    func connectToServer(timeout: TimeInterval) {
        stream.addDelegate(self, delegateQueue: DispatchQueue.main)
        stream.myJID = XMPPJID(string: "myuser")
        stream.hostName = "myserver.tld"
        stream.hostPort = 5222

        do {
            try stream.connect(withTimeout: timeout)
        }
        catch {
            print(error)
        }
    }

    func xmppStreamWillConnect(_ sender: XMPPStream!) {
        print("will connect")
    }

    func xmppStreamDidConnect(_ sender: XMPPStream!) {
        print("did connect")
        self.stream.disconnect()
    }
}

这个简单的测试类:

import Foundation
import XCTest
@testable import MyModule

class ConnectionTests: XCTestCase {
    func testConnect() {
        let connection = Connection()

        print("Try to connect")
        let expectation = self.expectation(description: "connect")
        connection.connectToServer(timeout: 3)
        self.waitForExpectations(timeout: 5)
    }
}

我期望这个输出:

Try to connect
will connect
did connect
<5s timeout since I don't fulfill>

如果我的 XMPP 服务器不小心没有对我的请求做出积极的 react ,我想看看:

Try to connect
will connect
<some error message>

如果 XMPP 服务器没有(快速)回复,我希望:

Try to connect
will connect
<3s timeout reached>

但是,我没有得到这些,而是​​:

Try to connect
will connect
<5s timeout since I don't fulfill>

这是怎么回事?

这是我收集到的。

  • XCTest 等待 DispatchQueue.main .
  • 我们可以控制代表的运行位置; DispatchQueue.main 似乎并不重要或DispatchQueue(label: "test", qos: .userInitiated, attributes: .concurrent)被使用。
  • 我可以跟踪执行情况直到 dispatch_sync(xmppQueue, block);XMPPStream.connectWithTimeout哪里xmppQueue是一个带有标签 xmpp 的新队列;该 block 似乎也已完全执行。

所以我不明白谁在这里阻止了谁,以及如何防止它发生。

最佳答案

问题有三个:

  1. 期望超时,因为它从未实现。
  2. 我们从来没有看到“连接过”,因为它从来没有达到那么远。
  3. 我们对 XMPP(框架)了解不够,无法了解插入位置。

我们实现了一些额外的委托(delegate)方法:

func xmppStream(_ sender: XMPPStream!, socketDidConnect socket: GCDAsyncSocket!) {
    print("socket did connect")
}

func xmppStreamDidStartNegotiation(_ sender: XMPPStream!) {
    print("negotiation started")
}

...

func xmppStream(_ sender: XMPPStream!, didReceiveError error: DDXMLElement!) {
    print("error: \(error)")
}

func xmppStreamDidDisconnect(_ sender: XMPPStream!, withError error: Error!) {
    print("disconnected")
    self.afterConnection()
}

这里,self.afterConnection 是作为附加参数传递给 connectToServer 的函数。

我们在测试中进行了更改:

connection.connectToServer(timeout: 3, then: { expectation.fulfill() })

现在测试以有序方式终止,输出如下:

Try to connect
will connect
socket did connect
negotiation started
disconnected
error: Optional(<stream:error xmlns:stream="http://etherx.jabber.org/streams"><host-unknown xmlns="urn:ietf:params:xml:ns:xmpp-streams"/></stream:error>)

所以这毕竟是服务器的问题。我们需要实现正确的代表来诊断问题;我们预计 stream.connect 在这种情况下会抛出错误!

关于swift - 为什么 XMPPFramework 会阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44850053/

相关文章:

java - @Synchronized 方法中的 Kotlin IllegalMonitorStateException

ios - 如何取消初始化子 UIViewController?

swift - Swift 4 中未解析的标识符 'CALayerContentsGravity'

swift - 使用 Alamofire 帖子登录不起作用

java - JUnit 会并行运行测试吗?

java - 为此方法编写单元测试用例返回 RxJava Future

android - 如何设置 Mockito 模拟 Android 单元测试类

java - 预期的空指针导致意外的 InvokingTargetException

ios - 快速解析ip

java - 死锁检测的成本如何?