Inconsistent data from request.
I'm using EnvoyAmbassador in unit tests to mock my API server. In order to validate the JSON body that the software under test sends, I'm using DataReader.read(input) like below. This works fine most of the time, but sometimes it fails. When it does fail, it looks like there's no data read by the DataReader(input) method. In the case below, the buffer has length 0.
Give the sporadic nature of the error, it feels like it might be a race condition? Any clues as to why this might fail once in a while?
if let input = environ["swsgi.input"] as? SWSGIInput {
let buffer = NSMutableData()
DataReader.read(input) { data in
for var d in data { // data is list of UInt8
buffer.appendData(NSData(bytes: &d, length: sizeof(UInt8)))
}
}
swiftyJson = JSON(data: buffer)
if (buffer.length == 0) {
XCTFail("Found zero length buffer parsing JSON")
}
@jaylyerly DataReader.read(input) is an async operation, namely, it's not blocking until it reads data. Instead, it only calls the closure you pass in when data is available.
So, instead of assert the data after DataReader.read(input), I would suggest you just assert inside the read closure like this:
if let input = environ["swsgi.input"] as? SWSGIInput {
let buffer = NSMutableData()
DataReader.read(input) { data in
for var d in data { // data is list of UInt8
buffer.appendData(NSData(bytes: &d, length: sizeof(UInt8)))
}
swiftyJson = JSON(data: buffer)
if (buffer.length == 0) {
XCTFail("Found zero length buffer parsing JSON")
}
}
Ah, I see. Silly mistake on my part. Thanks for the pointer. I've made the change to validate the data inside the read closure and things are working very well.
Thanks again for the great framework!
Weirdly, I upgraded to Xcode 8 and Swift 2.3 and the instability is back. I'm doing all my data inspection inside the read closure, but sometimes it's still empty. Any clue as to why the Xcode/Swift change might cause the behavior to change?
if let input = environ["swsgi.input"] as? SWSGIInput {
DataReader.read(input) { data in
let buffer = NSMutableData()
for var d in data { // data is list of UInt8
buffer.appendData(NSData(bytes: &d, length: sizeof(UInt8)))
}
if (buffer.length == 0) && (expectEmpty == false) {
XCTFail("Found zero length buffer parsing JSON")
}
let swiftyJson = JSON(data: buffer)
if expectEmpty == false {
XCTAssertNotEqual(swiftyJson, JSON(data: NSData()))
}
completion?(swiftyJson)
}
}
Oops. Forgot to reopen.
Hi, I seem to be getting this problem too. I'm on Swift 3.1 with the same problem.
It does seem to be a race condition. In fact, if I force a wait on line 130 of Transport.swift, like
do {
sleep(1) // For debugging
data = try socket.recv(size: Transport.recvChunkSize)
}
All the data, including the body is received, but without the debug code the request body will be missing. So it seems to be some form of race condition within the TCPSocket class.
Hi. I described this issue again and provided a solution. See https://github.com/envoy/Ambassador/issues/18. (Didn't realized that this is the same problem. Sorry!)