// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/async/cpp/receiver.h>

#include <lib/async-testutils/async_stub.h>
#include <unittest/unittest.h>

namespace {

class MockAsync : public async::AsyncStub {
public:
    enum class Op {
        NONE,
        QUEUE_PACKET
    };

    zx_status_t QueuePacket(async_receiver_t* receiver,
                            const zx_packet_user_t* data) override {
        last_op = Op::QUEUE_PACKET;
        last_receiver = receiver;
        last_data = data;
        return next_status;
    }

    Op last_op = Op::NONE;
    async_receiver_t* last_receiver = nullptr;
    const zx_packet_user_t* last_data = nullptr;
    zx_status_t next_status = ZX_OK;
};

class Harness {
public:
    Harness() { Reset(); }

    void Reset() {
        handler_ran = false;
        last_receiver = nullptr;
        last_status = ZX_ERR_INTERNAL;
        last_data = nullptr;
    }

    void Handler(async_t* async, async::ReceiverBase* receiver,
                 zx_status_t status, const zx_packet_user_t* data) {
        handler_ran = true;
        last_receiver = receiver;
        last_status = status;
        last_data = data;
    }

    virtual async::ReceiverBase& receiver() = 0;

    bool handler_ran;
    async::ReceiverBase* last_receiver;
    zx_status_t last_status;
    const zx_packet_user_t* last_data;
};

class LambdaHarness : public Harness {
public:
    async::ReceiverBase& receiver() override { return receiver_; }

private:
    async::Receiver receiver_{[this](async_t* async, async::Receiver* receiver,
                                     zx_status_t status, const zx_packet_user_t* data) {
        Handler(async, receiver, status, data);
    }};
};

class MethodHarness : public Harness {
public:
    async::ReceiverBase& receiver() override { return receiver_; }

private:
    async::ReceiverMethod<Harness, &Harness::Handler> receiver_{this};
};

bool receiver_set_handler_test() {
    BEGIN_TEST;

    {
        async::Receiver receiver;
        EXPECT_FALSE(receiver.has_handler());

        receiver.set_handler([](async_t* async, async::Receiver* receiver,
                                zx_status_t status, const zx_packet_user_t* data) {});
        EXPECT_TRUE(receiver.has_handler());
    }

    {
        async::Receiver receiver([](async_t* async, async::Receiver* receiver,
                                    zx_status_t status, const zx_packet_user_t* data) {});
        EXPECT_TRUE(receiver.has_handler());
    }

    END_TEST;
}

template <typename Harness>
bool receiver_queue_packet_test() {
    BEGIN_TEST;

    const zx_packet_user_t dummy_data{};
    MockAsync async;
    Harness harness;

    harness.Reset();
    async.next_status = ZX_OK;
    EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&async, nullptr), "queue, null data");
    EXPECT_EQ(MockAsync::Op::QUEUE_PACKET, async.last_op);
    EXPECT_NULL(async.last_data);
    EXPECT_FALSE(harness.handler_ran);

    harness.Reset();
    async.next_status = ZX_ERR_BAD_STATE;
    EXPECT_EQ(ZX_ERR_BAD_STATE, harness.receiver().QueuePacket(&async, nullptr), "queue, null data");
    EXPECT_EQ(MockAsync::Op::QUEUE_PACKET, async.last_op);
    EXPECT_NULL(async.last_data);
    EXPECT_FALSE(harness.handler_ran);

    harness.Reset();
    async.next_status = ZX_OK;
    EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&async, &dummy_data), "queue, non-null data");
    EXPECT_EQ(MockAsync::Op::QUEUE_PACKET, async.last_op);
    EXPECT_EQ(&dummy_data, async.last_data);
    EXPECT_FALSE(harness.handler_ran);

    harness.Reset();
    async.next_status = ZX_ERR_BAD_STATE;
    EXPECT_EQ(ZX_ERR_BAD_STATE, harness.receiver().QueuePacket(&async, &dummy_data), "queue, non-null data");
    EXPECT_EQ(MockAsync::Op::QUEUE_PACKET, async.last_op);
    EXPECT_EQ(&dummy_data, async.last_data);
    EXPECT_FALSE(harness.handler_ran);

    END_TEST;
}

template <typename Harness>
bool receiver_run_handler_test() {
    BEGIN_TEST;

    const zx_packet_user_t dummy_data{};
    MockAsync async;
    Harness harness;

    EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&async, nullptr));
    EXPECT_EQ(ZX_OK, harness.receiver().QueuePacket(&async, &dummy_data));

    harness.Reset();
    async.last_receiver->handler(&async, async.last_receiver, ZX_OK, nullptr);
    EXPECT_TRUE(harness.handler_ran);
    EXPECT_EQ(&harness.receiver(), harness.last_receiver);
    EXPECT_EQ(ZX_OK, harness.last_status);
    EXPECT_NULL(harness.last_data);

    harness.Reset();
    async.last_receiver->handler(&async, async.last_receiver, ZX_OK, &dummy_data);
    EXPECT_TRUE(harness.handler_ran);
    EXPECT_EQ(&harness.receiver(), harness.last_receiver);
    EXPECT_EQ(ZX_OK, harness.last_status);
    EXPECT_EQ(&dummy_data, harness.last_data);

    END_TEST;
}

bool unsupported_queue_packet_test() {
    BEGIN_TEST;

    async::AsyncStub async;
    async_receiver_t receiver{};
    EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_queue_packet(&async, &receiver, nullptr), "valid args without data");
    zx_packet_user_t data;
    EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_queue_packet(&async, &receiver, &data), "valid args with data");

    END_TEST;
}

} // namespace

BEGIN_TEST_CASE(receiver_tests)
RUN_TEST(receiver_set_handler_test)
RUN_TEST((receiver_queue_packet_test<LambdaHarness>))
RUN_TEST((receiver_queue_packet_test<MethodHarness>))
RUN_TEST((receiver_run_handler_test<LambdaHarness>))
RUN_TEST((receiver_run_handler_test<MethodHarness>))
RUN_TEST(unsupported_queue_packet_test)
END_TEST_CASE(receiver_tests)
