// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

// brpc - A framework to host and access services throughout Baidu.

// Date: 2015/10/22 16:28:44

#include <gtest/gtest.h>
#include <atomic>
#include "brpc/server.h"

#include "brpc/controller.h"
#include "brpc/channel.h"
#include "brpc/callback.h"
#include "brpc/socket.h"
#include "brpc/stream_impl.h"
#include "brpc/policy/streaming_rpc_protocol.h"
#include "echo.pb.h"

class AfterAcceptStream {
public:
    virtual void action(brpc::StreamId) = 0;
};

class MyServiceWithStream : public test::EchoService {
public:
    MyServiceWithStream(const brpc::StreamOptions& options) 
        : _options(options)
        , _after_accept_stream(NULL)
    {}
    MyServiceWithStream(const brpc::StreamOptions& options,
                        AfterAcceptStream* after_accept_stream) 
        : _options(options)
        , _after_accept_stream(after_accept_stream)
    {}
    MyServiceWithStream()
        : _options()
        , _after_accept_stream(NULL)
    {}

    void Echo(::google::protobuf::RpcController* controller,
                       const ::test::EchoRequest* request,
                       ::test::EchoResponse* response,
                       ::google::protobuf::Closure* done) {
        brpc::ClosureGuard done_guard(done);
        response->set_message(request->message());
        brpc::Controller* cntl = (brpc::Controller*)controller;
        brpc::StreamId response_stream;
        ASSERT_EQ(0, StreamAccept(&response_stream, *cntl, &_options));
        LOG(INFO) << "Created response_stream=" << response_stream;
        if (_after_accept_stream) {
            _after_accept_stream->action(response_stream);
        }
    }
private:
    brpc::StreamOptions _options;
    AfterAcceptStream* _after_accept_stream;
};

class StreamingRpcTest : public testing::Test {
protected:
    void SetUp() { request.set_message("hello world"); }
    void TearDown() {}

    test::EchoRequest request;
    test::EchoResponse response;
};

struct BatchStreamFeedbackRaceState {
    brpc::StreamId server_first_stream_id{brpc::INVALID_STREAM_ID};
    brpc::StreamId server_extra_stream_id{brpc::INVALID_STREAM_ID};
    brpc::StreamId client_extra_stream_id{brpc::INVALID_STREAM_ID};

    std::atomic<int> server_first_write_rc{-1};
    std::atomic<int> server_second_write_rc{-1};
    std::atomic<bool> client_got_first_msg{false};
    std::atomic<bool> client_got_second_msg{false};
    std::atomic<bool> server_write_done{false};
    std::atomic<bool> rpc_done{false};
    std::atomic<int> client_closed_count{0};

    bthread_t server_send_tid{0};
    std::atomic<bool> server_send_started{false};
};

class BatchStreamClientHandler : public brpc::StreamInputHandler {
public:
    explicit BatchStreamClientHandler(BatchStreamFeedbackRaceState* state)
        : _state(state) {}

    int on_received_messages(brpc::StreamId id,
                             butil::IOBuf* const messages[],
                             size_t size) override {
        if (id != _state->client_extra_stream_id) {
            // This test only cares about extra stream in batch creation.
            return 0;
        }
        for (size_t i = 0; i < size; ++i) {
            const size_t len = messages[i]->length();
            messages[i]->clear();
            // First payload: 64 bytes. Second payload: 1 byte.
            if (len == 64) {
                _state->client_got_first_msg.store(true, std::memory_order_release);
            } else if (len == 1) {
                _state->client_got_second_msg.store(true, std::memory_order_release);
            }
        }
        return 0;
    }

    void on_idle_timeout(brpc::StreamId /*id*/) override {}

    void on_closed(brpc::StreamId /*id*/) override {
        _state->client_closed_count.fetch_add(1, std::memory_order_release);
    }

    void on_failed(brpc::StreamId /*id*/, int /*error_code*/, const std::string& /*error_text*/) override {}

private:
    BatchStreamFeedbackRaceState* _state;
};

static void* SendTwoMessagesOnServerExtraStream(void* arg) {
    auto* state = static_cast<BatchStreamFeedbackRaceState*>(arg);
    const brpc::StreamId sid = state->server_extra_stream_id;

    // Wait until server-side stream is connected.
    const int64_t connect_deadline_us = butil::gettimeofday_us() + 2 * 1000 * 1000L;
    bool connected = false;
    while (butil::gettimeofday_us() < connect_deadline_us) {
        brpc::SocketUniquePtr ptr;
        if (brpc::Socket::Address(sid, &ptr) == 0) {
            brpc::Stream* s = static_cast<brpc::Stream*>(ptr->conn());
            if (s->_host_socket != NULL && s->_connected) {
                connected = true;
                break;
            }
        }
        usleep(1000);
    }

    if (!connected) {
        state->server_first_write_rc.store(ETIMEDOUT, std::memory_order_relaxed);
        state->server_second_write_rc.store(ETIMEDOUT, std::memory_order_relaxed);
        state->server_write_done.store(true, std::memory_order_release);
        return NULL;
    }

    // 1) Send a payload exactly equal to max_buf_size(64).
    {
        std::string payload(64, 'a');
        butil::IOBuf out;
        out.append(payload);
        state->server_first_write_rc.store(brpc::StreamWrite(sid, out), std::memory_order_relaxed);
    }

    // 2) Then send another byte. This write should become writable only after
    // client sends FEEDBACK with consumed_size >= 64.
    const int64_t write_deadline_us = butil::gettimeofday_us() + 2 * 1000 * 1000L;
    int rc = -1;
    while (butil::gettimeofday_us() < write_deadline_us) {
        butil::IOBuf out;
        out.append("b", 1);
        rc = brpc::StreamWrite(sid, out);
        if (rc == 0) {
            break;
        }
        if (rc != EAGAIN) {
            break;
        }
        const timespec duetime = butil::milliseconds_from_now(100);
        (void)brpc::StreamWait(sid, &duetime);
    }
    state->server_second_write_rc.store(rc, std::memory_order_relaxed);
    state->server_write_done.store(true, std::memory_order_release);
    return NULL;
}

class MyServiceWithBatchStream : public test::EchoService {
public:
    MyServiceWithBatchStream(const brpc::StreamOptions& options,
                             BatchStreamFeedbackRaceState* state)
        : _options(options), _state(state) {}

    void Echo(::google::protobuf::RpcController* controller,
              const ::test::EchoRequest* request,
              ::test::EchoResponse* response,
              ::google::protobuf::Closure* done) override {
        brpc::ClosureGuard done_guard(done);
        response->set_message(request->message());
        brpc::Controller* cntl = static_cast<brpc::Controller*>(controller);

        brpc::StreamIds response_streams;
        ASSERT_EQ(0, brpc::StreamAccept(response_streams, *cntl, &_options));
        ASSERT_EQ(2u, response_streams.size());
        _state->server_first_stream_id = response_streams[0];
        _state->server_extra_stream_id = response_streams[1];

        bthread_t tid;
        ASSERT_EQ(0, bthread_start_background(
                         &tid, &BTHREAD_ATTR_NORMAL,
                         SendTwoMessagesOnServerExtraStream, _state));
        _state->server_send_tid = tid;
        _state->server_send_started.store(true, std::memory_order_release);
    }

private:
    brpc::StreamOptions _options;
    BatchStreamFeedbackRaceState* _state;
};

static void SetAtomicTrue(std::atomic<bool>* f) {
    f->store(true, std::memory_order_release);
}

template <typename Pred>
static bool WaitForTrue(Pred pred, int timeout_ms) {
    const int64_t deadline_us = butil::gettimeofday_us() + (int64_t)timeout_ms * 1000L;
    while (!pred() && butil::gettimeofday_us() < deadline_us) {
        usleep(1000);
    }
    return pred();
}

static bool WaitForTrue(const std::atomic<bool>& f, int timeout_ms) {
    return WaitForTrue([&f]() { return f.load(std::memory_order_acquire); }, timeout_ms);
}

TEST_F(StreamingRpcTest, sanity) {
    brpc::Server server;
    MyServiceWithStream service;
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, NULL));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;
    usleep(10);
    brpc::StreamClose(request_stream);
    server.Stop(0);
    server.Join();
}

TEST_F(StreamingRpcTest, batch_create_stream_feedback_race) {
    BatchStreamFeedbackRaceState state;
    BatchStreamClientHandler client_handler(&state);

    brpc::StreamOptions server_stream_opt;
    // Make server-side sender sensitive to FEEDBACK quickly.
    server_stream_opt.max_buf_size = 16;

    brpc::Server server;
    MyServiceWithBatchStream service(server_stream_opt, &state);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));

    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));

    brpc::Controller cntl;
    brpc::StreamIds request_streams;
    brpc::StreamOptions client_stream_opt;
    client_stream_opt.handler = &client_handler;
    client_stream_opt.max_buf_size = 0;
    ASSERT_EQ(0, brpc::StreamCreate(request_streams, 2, cntl, &client_stream_opt));
    ASSERT_EQ(2u, request_streams.size());
    state.client_extra_stream_id = request_streams[1];

    // Block SetConnected() on the extra stream to enlarge the race window.
    brpc::SocketUniquePtr client_extra_ptr;
    ASSERT_EQ(0, brpc::Socket::Address(state.client_extra_stream_id, &client_extra_ptr));
    brpc::Stream* client_extra_stream = static_cast<brpc::Stream*>(client_extra_ptr->conn());
    bthread_mutex_lock(&client_extra_stream->_connect_mutex);
    struct UnlockGuard {
        bthread_mutex_t* m;
        ~UnlockGuard() {
            if (m) {
                bthread_mutex_unlock(m);
            }
        }
    } unlock_guard{&client_extra_stream->_connect_mutex};

    BRPC_SCOPE_EXIT {
        if (state.server_extra_stream_id != brpc::INVALID_STREAM_ID) {
            brpc::StreamClose(state.server_extra_stream_id);
        }
        if (state.server_first_stream_id != brpc::INVALID_STREAM_ID) {
            brpc::StreamClose(state.server_first_stream_id);
        }
        for (auto sid : request_streams) {
            brpc::StreamClose(sid);
        }

        if (state.server_send_tid) {
            bthread_join(state.server_send_tid, NULL);
        }
        server.Stop(0);
        server.Join();

        // Release the SocketUniquePtr held above so the fake socket can be
        // recycled. Otherwise BeforeRecycle / on_closed for the extra stream
        // is deferred until `client_extra_ptr` destructs at scope exit, which
        // happens *after* `client_handler` and `state` are destroyed -> UAF
        // inside Stream::Consume on Linux.
        client_extra_ptr.reset();

        // on_closed() runs asynchronously on each client stream's consumer
        // bthread. Wait for both before letting handler/state go out of
        // scope, otherwise Stream::Consume will dereference freed memory.
        int expected_closed = request_streams.size();
        WaitForTrue([&state, expected_closed]() {
            return state.client_closed_count.load(std::memory_order_acquire)
                   >= expected_closed;
        }, 2000);
    };

    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, brpc::NewCallback(SetAtomicTrue, &state.rpc_done));

    // Wait until client consumes the first 64B payload on extra stream.
    ASSERT_TRUE(WaitForTrue(state.client_got_first_msg, 2000));

    // Unblock SetConnected(); the fix in PR 3215 should send the first FEEDBACK
    // with consumed_size=64 here, making server-side stream writable again.
    bthread_mutex_unlock(&client_extra_stream->_connect_mutex);
    unlock_guard.m = NULL;

    ASSERT_TRUE(WaitForTrue(state.rpc_done, 2000));
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText();

    // Wait for server-side send thread to be started.
    ASSERT_TRUE(WaitForTrue(state.server_send_started, 2000));

    ASSERT_TRUE(WaitForTrue(state.server_write_done, 2000));
    ASSERT_EQ(0, state.server_first_write_rc.load(std::memory_order_relaxed));
    ASSERT_EQ(0, state.server_second_write_rc.load(std::memory_order_relaxed));
    ASSERT_TRUE(WaitForTrue(state.client_got_second_msg, 2000));
}

struct HandlerControl {
    HandlerControl()
        : block(false)
    {}
    bool block;
};

class OrderedInputHandler : public brpc::StreamInputHandler {
public:
    explicit OrderedInputHandler(HandlerControl *cntl = NULL)
        : _expected_next_value(0)
        , _failed(false)
        , _stopped(false)
        , _idle_times(0)
        , _cntl(cntl)
    {}

    int on_received_messages(brpc::StreamId /*id*/,
                             butil::IOBuf *const messages[],
                             size_t size) override {
        if (_cntl && _cntl->block) {
            while (_cntl->block) {
                usleep(100);
            }
        }
        for (size_t i = 0; i < size; ++i) {
            CHECK(messages[i]->length() == sizeof(int));
            int network = 0;
            messages[i]->cutn(&network, sizeof(int));
            EXPECT_EQ((int)ntohl(network), _expected_next_value++);
        }
        return 0;
    }

    void on_idle_timeout(brpc::StreamId /*id*/) override {
        ++_idle_times;
    }

    void on_closed(brpc::StreamId /*id*/) override {
        ASSERT_FALSE(_stopped);
        _stopped = true;
    }

    void on_failed(brpc::StreamId id, int error_code,
                   const std::string& /*error_text*/) override {
        ASSERT_FALSE(_failed);
        ASSERT_NE(0, error_code);
        _failed = true;
    }

    bool failed() const { return _failed; }
    bool stopped() const { return _stopped; }
    int idle_times() const { return _idle_times; }
private:
    int _expected_next_value;
    bool _failed;
    bool _stopped;
    int _idle_times;
    HandlerControl* _cntl;
};

TEST_F(StreamingRpcTest, received_in_order) {
    OrderedInputHandler handler;
    brpc::StreamOptions opt;
    opt.handler = &handler;
    opt.messages_in_batch = 100;
    brpc::Server server;
    MyServiceWithStream service(opt);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    brpc::StreamOptions request_stream_options;
    request_stream_options.max_buf_size = 0;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;
    const int N = 10000;
    for (int i = 0; i < N; ++i) {
        int network = htonl(i);
        butil::IOBuf out;
        out.append(&network, sizeof(network));
        ASSERT_EQ(0, brpc::StreamWrite(request_stream, out)) << "i=" << i;
    }
    ASSERT_EQ(0, brpc::StreamClose(request_stream));
    server.Stop(0);
    server.Join();
    while (!handler.stopped()) {
        usleep(100);
    }
    ASSERT_FALSE(handler.failed());
    ASSERT_EQ(0, handler.idle_times());
    ASSERT_EQ(N, handler._expected_next_value);
}

void on_writable(brpc::StreamId, void* arg, int error_code) {
    std::pair<bool, int>* p = (std::pair<bool, int>*)arg;
    p->first = true;
    p->second = error_code;
    LOG(INFO) << "error_code=" << error_code;
}

TEST_F(StreamingRpcTest, block) {
    HandlerControl hc;
    hc.block = true;
    OrderedInputHandler handler(&hc);
    brpc::StreamOptions opt;
    opt.handler = &handler;
    const int N = 10000;
    opt.max_buf_size = sizeof(uint32_t) *  N;
    brpc::Server server;
    MyServiceWithStream service(opt);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    brpc::ScopedStream stream_guard(request_stream);
    brpc::StreamOptions request_stream_options;
    request_stream_options.max_buf_size = sizeof(uint32_t) * N;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream="
                                << request_stream;
    for (int i = 0; i < N; ++i) {
        int network = htonl(i);
        butil::IOBuf out;
        out.append(&network, sizeof(network));
        ASSERT_EQ(0, brpc::StreamWrite(request_stream, out)) << "i=" << i;
    }
    // sync wait
    int dummy = 102030123;
    butil::IOBuf out;
    out.append(&dummy, sizeof(dummy));
    ASSERT_EQ(EAGAIN, brpc::StreamWrite(request_stream, out));
    hc.block = false;
    // wait flushing all the pending messages
    while (handler._expected_next_value != N) {
        usleep(100);
    }
    // block hanlder again to test async wait
    hc.block = true;
    // async wait
    for (int i = N; i < N + N; ++i) {
        ASSERT_EQ(0, brpc::StreamWait(request_stream, NULL));
        int network = htonl(i);
        butil::IOBuf out;
        out.append(&network, sizeof(network));
        ASSERT_EQ(0, brpc::StreamWrite(request_stream, out)) << "i=" << i;
    }
    out.clear();
    out.append(&dummy, sizeof(dummy));
    ASSERT_EQ(EAGAIN, brpc::StreamWrite(request_stream, out));
    hc.block = false;
    std::pair<bool, int> p = std::make_pair(false, 0);
    usleep(10);
    brpc::StreamWait(request_stream, NULL, on_writable, &p);
    while (!p.first) {
        usleep(100);
    }
    ASSERT_EQ(0, p.second);

    // wait flushing all the pending messages
    while (handler._expected_next_value != N + N) {
        usleep(100);
    }
    usleep(1000);

    LOG(INFO) << "Starting block";
    hc.block = true;
    for (int i = N + N; i < N + N + N; ++i) {
        int network = htonl(i);
        butil::IOBuf out;
        out.append(&network, sizeof(network));
        ASSERT_EQ(0, brpc::StreamWrite(request_stream, out)) << "i=" << i - N - N;
    }
    out.clear();
    out.append(&dummy, sizeof(dummy));
    ASSERT_EQ(EAGAIN, brpc::StreamWrite(request_stream, out));
    timespec duetime = butil::microseconds_from_now(1);
    p.first = false;
    LOG(INFO) << "Start wait";
    brpc::StreamWait(request_stream, &duetime, on_writable, &p);
    while (!p.first) {
        usleep(100);
    }
    ASSERT_TRUE(p.first);
    EXPECT_EQ(ETIMEDOUT, p.second);
    hc.block = false;
    ASSERT_EQ(0, brpc::StreamClose(request_stream));
    while (!handler.stopped()) {
        usleep(100);
    }

    ASSERT_FALSE(handler.failed());
    ASSERT_EQ(0, handler.idle_times());
    ASSERT_EQ(N + N + N, handler._expected_next_value);
}

TEST_F(StreamingRpcTest, auto_close_if_host_socket_closed) {
    HandlerControl hc;
    hc.block = true;
    OrderedInputHandler handler(&hc);
    brpc::StreamOptions opt;
    opt.handler = &handler;
    const int N = 10000;
    opt.max_buf_size = sizeof(uint32_t) *  N;
    brpc::Server server;
    MyServiceWithStream service(opt);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    brpc::StreamOptions request_stream_options;
    request_stream_options.max_buf_size = sizeof(uint32_t) * N;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;

    {
        brpc::SocketUniquePtr ptr;
        ASSERT_EQ(0, brpc::Socket::Address(request_stream, &ptr));
        brpc::Stream* s = (brpc::Stream*)ptr->conn();
        ASSERT_TRUE(s->_host_socket != NULL);
        s->_host_socket->SetFailed();
    }

    usleep(100);
    butil::IOBuf out;
    out.append("test");
    ASSERT_EQ(EINVAL, brpc::StreamWrite(request_stream, out));
    while (!handler.stopped()) {
        usleep(100);
    }
    ASSERT_TRUE(handler.failed());
    ASSERT_EQ(0, handler.idle_times());
    ASSERT_EQ(0, handler._expected_next_value);
}

TEST_F(StreamingRpcTest, failed_when_rst) {
    OrderedInputHandler handler;
    brpc::StreamOptions opt;
    opt.handler = &handler;
    opt.messages_in_batch = 100;
    brpc::Server server;
    MyServiceWithStream service(opt);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    brpc::StreamOptions request_stream_options;
    request_stream_options.max_buf_size = 0;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;
    const int N = 10000;
    for (int i = 0; i < N; ++i) {
        int network = htonl(i);
        butil::IOBuf out;
        out.append(&network, sizeof(network));
        ASSERT_EQ(0, brpc::StreamWrite(request_stream, out)) << "i=" << i;
    }

    while (handler._expected_next_value != N) {
        usleep(100);
    }
    {
        brpc::SocketUniquePtr ptr;
        ASSERT_EQ(0, brpc::Socket::Address(request_stream, &ptr));
        brpc::Stream* s = (brpc::Stream*)ptr->conn();
        ASSERT_TRUE(s->_host_socket != NULL);
        brpc::policy::SendStreamRst(s->_host_socket,
                                    s->_remote_settings.stream_id());
    }
    // ASSERT_EQ(0, brpc::StreamClose(request_stream));
    server.Stop(0);
    server.Join();
    while (!handler.stopped() && !handler.failed()) {
        usleep(100);
    }
    ASSERT_TRUE(handler.failed());
    ASSERT_EQ(0, handler.idle_times());
    ASSERT_EQ(N, handler._expected_next_value);
}

TEST_F(StreamingRpcTest, idle_timeout) {
    HandlerControl hc;
    hc.block = true;
    OrderedInputHandler handler(&hc);
    brpc::StreamOptions opt;
    opt.handler = &handler;
    opt.idle_timeout_ms = 2;
    const int N = 10000;
    opt.max_buf_size = sizeof(uint32_t) *  N;
    brpc::Server server;
    MyServiceWithStream service(opt);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    brpc::StreamOptions request_stream_options;
    request_stream_options.max_buf_size = sizeof(uint32_t) * N;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;
    usleep(10 * 1000 + 800);
    ASSERT_EQ(0, brpc::StreamClose(request_stream));
    while (!handler.stopped()) {
        usleep(100);
    }
    ASSERT_FALSE(handler.failed());
//    ASSERT_TRUE(handler.idle_times() >= 4 && handler.idle_times() <= 6)
//               << handler.idle_times();
    ASSERT_EQ(0, handler._expected_next_value);
}

class PingPongHandler : public brpc::StreamInputHandler {
public:
    int on_received_messages(brpc::StreamId id,
                             butil::IOBuf *const messages[],
                             size_t size) override {
        if (size != 1) {
            LOG(INFO) << "size=" << size;
            _error = true;
            return 0;
        }
        for (size_t i = 0; i < size; ++i) {
            CHECK(messages[i]->length() == sizeof(int));
            int network = 0;
            messages[i]->cutn(&network, sizeof(int));
            if ((int)ntohl(network) != _expected_next_value) {
                _error = true;
            }
            int send_back = ntohl(network) + 1;
            _expected_next_value = send_back + 1;
            butil::IOBuf out;
            network = htonl(send_back);
            out.append(&network, sizeof(network));
            // don't care the return value
            brpc::StreamWrite(id, out);
        }
        return 0;
    }

    void on_idle_timeout(brpc::StreamId /*id*/) override {
        ++_idle_times;
    }

    void on_closed(brpc::StreamId /*id*/) override {
        ASSERT_FALSE(_stopped);
        _stopped = true;
    }


    void on_failed(brpc::StreamId id, int error_code,
                   const std::string& /*error_text*/) override {
        ASSERT_FALSE(_failed);
        ASSERT_NE(0, error_code);
        _failed = true;
    }

    bool error() const { return _error; }
    bool failed() const { return _failed; }
    bool stopped() const { return _stopped; }
    int idle_times() const { return _idle_times; }
private:
    int _expected_next_value{0};
    bool _error{false};
    bool _failed{false};
    bool _stopped{false};
    int _idle_times{0};
};

TEST_F(StreamingRpcTest, ping_pong) {
    PingPongHandler resh;
    brpc::StreamOptions opt;
    opt.handler = &resh;
    const int N = 10000;
    opt.max_buf_size = sizeof(uint32_t) *  N;
    brpc::Server server;
    MyServiceWithStream service(opt);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    brpc::StreamOptions request_stream_options;
    PingPongHandler reqh;
    reqh._expected_next_value = 1;
    request_stream_options.handler = &reqh;
    request_stream_options.max_buf_size = sizeof(uint32_t) * N;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;
    int send = 0;
    butil::IOBuf out;
    out.append(&send, sizeof(send));
    ASSERT_EQ(0, brpc::StreamWrite(request_stream, out));
    usleep(10 * 1000);
    ASSERT_EQ(0, brpc::StreamClose(request_stream));
    while (!resh.stopped() || !reqh.stopped()) {
        usleep(100);
    }
    ASSERT_FALSE(resh.error());
    ASSERT_FALSE(reqh.error());
    ASSERT_EQ(0, resh.idle_times());
    ASSERT_EQ(0, reqh.idle_times());
}

class SendNAfterAcceptStream : public AfterAcceptStream {
public:
    explicit SendNAfterAcceptStream(int n)
        : _n(n) {}
    void action(brpc::StreamId s) {
        for (int i = 0; i < _n; ++i) {
            int network = htonl(i);
            butil::IOBuf out;
            out.append(&network, sizeof(network));
            ASSERT_EQ(0, brpc::StreamWrite(s, out)) << "i=" << i;
        }
    }
private:
    int _n;
};

TEST_F(StreamingRpcTest, server_send_data_before_run_done) {
    const int N = 10000;
    SendNAfterAcceptStream after_accept(N);
    brpc::StreamOptions opt;
    opt.max_buf_size = -1;
    brpc::Server server;
    MyServiceWithStream service(opt, &after_accept);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    OrderedInputHandler handler;
    brpc::StreamOptions request_stream_options;
    request_stream_options.handler = &handler;
    brpc::StreamId request_stream;
    brpc::Controller cntl;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;
    // wait flushing all the pending messages
    while (handler._expected_next_value != N) {
        usleep(100);
    }
    ASSERT_EQ(0, brpc::StreamClose(request_stream));
    while (!handler.stopped()) {
        usleep(100);
    }
    ASSERT_FALSE(handler.failed());
    ASSERT_EQ(0, handler.idle_times());
}

TEST_F(StreamingRpcTest, segment_stream_data_automatically) {
    GFLAGS_NAMESPACE::SetCommandLineOption("stream_write_max_segment_size", "1");
    OrderedInputHandler handler;
    brpc::StreamOptions opt;
    opt.handler = &handler;
    opt.messages_in_batch = 100;
    brpc::Server server;
    MyServiceWithStream service(opt);
    ASSERT_EQ(0, server.AddService(&service, brpc::SERVER_DOESNT_OWN_SERVICE));
    ASSERT_EQ(0, server.Start(9007, NULL));
    brpc::Channel channel;
    ASSERT_EQ(0, channel.Init("127.0.0.1:9007", NULL));
    brpc::Controller cntl;
    brpc::StreamId request_stream;
    brpc::StreamOptions request_stream_options;
    ASSERT_EQ(0, StreamCreate(&request_stream, cntl, &request_stream_options));
    brpc::ScopedStream stream_guard(request_stream);
    test::EchoService_Stub stub(&channel);
    stub.Echo(&cntl, &request, &response, NULL);
    ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText() << " request_stream=" << request_stream;
    const int N = 1000;
    for (int i = 0; i < N; ++i) {
        int network = htonl(i);
        butil::IOBuf out;
        out.append(&network, sizeof(network));
        ASSERT_EQ(0, brpc::StreamWrite(request_stream, out)) << "i=" << i;
    }

    brpc::SocketUniquePtr host_socket_ptr;
    {
      brpc::SocketUniquePtr ptr;
      ASSERT_EQ(0, brpc::Socket::Address(request_stream, &ptr));
      brpc::Stream *s = (brpc::Stream *)ptr->conn();
      ASSERT_TRUE(s->_host_socket != NULL);
      s->_host_socket->ReAddress(&host_socket_ptr);
    }

    ASSERT_EQ(0, brpc::StreamClose(request_stream));
    server.Stop(0);
    server.Join();
    while (!handler.stopped()) {
        usleep(100);
    }
    const int64_t now_ms = butil::cpuwide_time_ms();
    host_socket_ptr->UpdateStatsEverySecond(now_ms);
    brpc::SocketStat stat;
    host_socket_ptr->GetStat(&stat);
    ASSERT_LT(N * sizeof(N), stat.out_num_messages_m);
    ASSERT_FALSE(handler.failed());
    ASSERT_EQ(0, handler.idle_times());
    ASSERT_EQ(N, handler._expected_next_value);
    GFLAGS_NAMESPACE::SetCommandLineOption("stream_write_max_segment_size", "536870912");
}
