<commit_before>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation
import XCTest
import ConcurrencyHelpers
import NIO
import Dispatch
@testable import NIOHTTP1

private func assertSuccess(_ f: FutureValue<()>, file: StaticString = #file, line: Int = #line) {
    switch f {
    case .success(()):
        ()
    case .failure(let err):
        XCTFail("error received: \(err)", file: file, line: UInt(line))
    }
}

extension Array where Array.Element == ByteBuffer {
    public func allAsData() -> Data {
        return self.flatMap {
            var bb = $0
            return bb.readData(length: bb.readableBytes)
            }.reduce(Data(), { $0 + $1 })
    }
    
    public func allAsString() -> String? {
        return String(bytes: self.allAsData(), encoding: .utf8)
    }
}

class HTTPServerClientTest : XCTestCase {
    
    private class SimpleHTTPServer: ChannelInboundHandler {
        typealias InboundIn = HTTPRequestPart
        typealias OutboundOut = HTTPResponsePart
        
        public func channelRead(ctx: ChannelHandlerContext, data: IOData) {
            switch self.unwrapInboundIn(data) {
            case .head(let req):
                switch req.uri {
                case "/helloworld":
                    let replyString = "Hello World!\r\n"
                    var head = HTTPResponseHead(version: req.version, status: .ok)
                    head.headers.add(name: "Content-Length", value: "\(replyString.utf8.count)")
                    head.headers.add(name: "Connection", value: "close")
                    let r = HTTPResponsePart.head(head)
                    ctx.write(data: self.wrapOutboundOut(r), promise: nil)
                    var b = ctx.channel!.allocator.buffer(capacity: replyString.count)
                    b.write(string: replyString)
                    ctx.writeAndFlush(data: self.wrapOutboundOut(.body(.last(buffer: b)))).whenComplete { r in
                        assertSuccess(r)
                        ctx.close().whenComplete { r in
                            assertSuccess(r)
                        }
                    }
                case "/count-to-ten":
                    var head = HTTPResponseHead(version: req.version, status: .ok)
                    head.headers.add(name: "Connection", value: "close")
                    let r = HTTPResponsePart.head(head)
                    ctx.writeAndFlush(data: self.wrapOutboundOut(r)).whenComplete { r in
                        assertSuccess(r)
                    }
                    var b = ctx.channel!.allocator.buffer(capacity: 1024)
                    for i in 1...10 {
                        b.clear()
                        b.write(string: "\(i)")
                        ctx.writeAndFlush(data: self.wrapOutboundOut(.body(.more(buffer: b)))).whenComplete { r in
                            assertSuccess(r)
                        }
                    }
                    ctx.writeAndFlush(data: self.wrapOutboundOut(.body(.last(buffer: nil)))).whenComplete { r in
                        assertSuccess(r)
                        ctx.close().whenComplete { r in
                            assertSuccess(r)
                        }
                    }
                default:
                    XCTFail("received request to unknown URI \(req.uri)")
                }
            case .body(.last(let chunk)):
                XCTAssertNil(chunk)
            default:
                XCTFail("wrong")
            }
        }
    }
    
    private class ArrayAccumulationHandler<T>: ChannelInboundHandler {
        typealias InboundIn = T
        private var receiveds: [T] = []
        private var allDoneBlock: DispatchWorkItem! = nil
        
        public init(completion: @escaping ([T]) -> Void) {
            self.allDoneBlock = DispatchWorkItem { [unowned self] () -> Void in
                completion(self.receiveds)
            }<commit_msg>HTTPServerClientTest: depend on channelReadComplete working <commit_after>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Foundation
import XCTest
import ConcurrencyHelpers
import NIO
import Dispatch
@testable import NIOHTTP1

private func assertSuccess(_ f: FutureValue<()>, file: StaticString = #file, line: Int = #line) {
    switch f {
    case .success(()):
        ()
    case .failure(let err):
        XCTFail("error received: \(err)", file: file, line: UInt(line))
    }
}

extension Array where Array.Element == ByteBuffer {
    public func allAsData() -> Data {
        return self.flatMap {
            var bb = $0
            return bb.readData(length: bb.readableBytes)
            }.reduce(Data(), { $0 + $1 })
    }
    
    public func allAsString() -> String? {
        return String(bytes: self.allAsData(), encoding: .utf8)
    }
}

class HTTPServerClientTest : XCTestCase {
    
    private class SimpleHTTPServer: ChannelInboundHandler {
        typealias InboundIn = HTTPRequestPart
        typealias OutboundOut = HTTPResponsePart
        
        public func channelRead(ctx: ChannelHandlerContext, data: IOData) {
            switch self.unwrapInboundIn(data) {
            case .head(let req):
                switch req.uri {
                case "/helloworld":
                    let replyString = "Hello World!\r\n"
                    var head = HTTPResponseHead(version: req.version, status: .ok)
                    head.headers.add(name: "Content-Length", value: "\(replyString.utf8.count)")
                    head.headers.add(name: "Connection", value: "close")
                    let r = HTTPResponsePart.head(head)
                    ctx.write(data: self.wrapOutboundOut(r), promise: nil)
                    var b = ctx.channel!.allocator.buffer(capacity: replyString.count)
                    b.write(string: replyString)
                    ctx.write(data: self.wrapOutboundOut(.body(.last(buffer: b)))).whenComplete { r in
                        assertSuccess(r)
                        ctx.close().whenComplete { r in
                            assertSuccess(r)
                        }
                    }
                case "/count-to-ten":
                    var head = HTTPResponseHead(version: req.version, status: .ok)
                    head.headers.add(name: "Connection", value: "close")
                    let r = HTTPResponsePart.head(head)
                    ctx.write(data: self.wrapOutboundOut(r)).whenComplete { r in
                        assertSuccess(r)
                    }
                    var b = ctx.channel!.allocator.buffer(capacity: 1024)
                    for i in 1...10 {
                        b.clear()
                        b.write(string: "\(i)")
                        ctx.write(data: self.wrapOutboundOut(.body(.more(buffer: b)))).whenComplete { r in
                            assertSuccess(r)
                        }
                    }
                    ctx.write(data: self.wrapOutboundOut(.body(.last(buffer: nil)))).whenComplete { r in
                        assertSuccess(r)
                        ctx.close().whenComplete { r in
                            assertSuccess(r)
                        }
                    }
                default:
                    XCTFail("received request to unknown URI \(req.uri)")
                }
            case .body(.last(let chunk)):
                XCTAssertNil(chunk)
            default:
                XCTFail("wrong")
            }
        }

        public func channelReadComplete(ctx: ChannelHandlerContext) {
            ctx.flush().whenComplete {
                assertSuccess($0)
            }
        }
    }
    
    private class ArrayAccumulationHandler<T>: ChannelInboundHandler {
        typealias InboundIn = T
        private var receiveds: [T] = []
        private var allDoneBlock: DispatchWorkItem! = nil
        
        public init(completion: @escaping ([T]) -> Void) {
            self.allDoneBlock = DispatchWorkItem { [unowned self] () -> Void in
                completion(self.receiveds)
            }
{'fraction_non_alphanumeric': 0.13357966633075805, 'fraction_numerical': 0.005710446758481693, 'mean_word_length': 1.4317996188401851, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '666330', 'n_tokens_mistral': 2350, 'n_tokens_neox': 2193, 'n_words': 545}