// 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.

#include <gflags/gflags.h>
#include <gtest/gtest.h>
#include "bthread/bthread.h"
#include "bthread/condition_variable.h"
#include "bthread/countdown_event.h"
#include "bthread/mutex.h"

DECLARE_int32(task_group_ntags);

int main(int argc, char* argv[]) {
    FLAGS_task_group_ntags = 3;
    testing::InitGoogleTest(&argc, argv);
    GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true);
    return RUN_ALL_TESTS();
}

namespace {

std::vector<bthread_tag_t> butex_wake_return(2, 0);

void* butex_wake_func(void* arg) {
    auto mutex = static_cast<bthread::Mutex*>(arg);
    butex_wake_return.push_back(bthread_self_tag());
    mutex->lock();
    butex_wake_return.push_back(bthread_self_tag());
    mutex->unlock();
    return nullptr;
}

TEST(BthreadButexMultiTest, butex_wake) {
    bthread::Mutex mutex;
    mutex.lock();
    bthread_t tid1;
    bthread_attr_t attr = BTHREAD_ATTR_NORMAL;
    attr.tag = 1;
    bthread_start_urgent(&tid1, &attr, butex_wake_func, &mutex);
    mutex.unlock();
    bthread_join(tid1, nullptr);
    ASSERT_EQ(butex_wake_return[0], butex_wake_return[1]);
}

std::vector<bthread_tag_t> butex_wake_all_return1(2, 0);
std::vector<bthread_tag_t> butex_wake_all_return2(2, 0);

struct ButexWakeAllArgs {
    bthread::CountdownEvent* ev;
    bthread::CountdownEvent* ack;
};

void* butex_wake_all_func1(void* arg) {
    auto p = static_cast<ButexWakeAllArgs*>(arg);
    auto ev = p->ev;
    auto ack = p->ack;
    butex_wake_all_return1.push_back(bthread_self_tag());
    ack->signal();
    ev->wait();
    butex_wake_all_return1.push_back(bthread_self_tag());
    return nullptr;
}

void* butex_wake_all_func2(void* arg) {
    auto p = static_cast<ButexWakeAllArgs*>(arg);
    auto ev = p->ev;
    auto ack = p->ack;
    butex_wake_all_return2.push_back(bthread_self_tag());
    ack->signal();
    ev->wait();
    butex_wake_all_return2.push_back(bthread_self_tag());
    return nullptr;
}

TEST(BthreadButexMultiTest, butex_wake_all) {
    bthread::CountdownEvent ev(2);
    bthread::CountdownEvent ack(2);
    ButexWakeAllArgs args{&ev, &ack};
    bthread_t tid1, tid2;
    bthread_attr_t attr1 = BTHREAD_ATTR_NORMAL;
    attr1.tag = 1;
    bthread_start_background(&tid1, &attr1, butex_wake_all_func1, &args);
    bthread_attr_t attr2 = BTHREAD_ATTR_NORMAL;
    attr2.tag = 2;
    bthread_start_background(&tid2, &attr2, butex_wake_all_func2, &args);
    ack.wait();
    ev.signal(2);
    bthread_join(tid1, nullptr);
    bthread_join(tid2, nullptr);
    ASSERT_EQ(butex_wake_all_return1[0], butex_wake_all_return1[1]);
    ASSERT_EQ(butex_wake_all_return2[0], butex_wake_all_return2[1]);
}

std::vector<bthread_tag_t> butex_requeue_return1(2, 0);
std::vector<bthread_tag_t> butex_requeue_return2(2, 0);

struct ButexRequeueArgs {
    bthread::Mutex* mutex;
    bthread::ConditionVariable* cond;
    bthread::CountdownEvent* ack;
};

void* butex_requeue_func1(void* arg) {
    auto p = static_cast<ButexRequeueArgs*>(arg);
    auto mutex = p->mutex;
    auto cond = p->cond;
    auto ack = p->ack;
    butex_wake_all_return1.push_back(bthread_self_tag());
    std::unique_lock<bthread::Mutex> lk(*mutex);
    ack->signal();
    cond->wait(lk);
    butex_wake_all_return1.push_back(bthread_self_tag());
    return nullptr;
}

void* butex_requeue_func2(void* arg) {
    auto p = static_cast<ButexRequeueArgs*>(arg);
    auto mutex = p->mutex;
    auto cond = p->cond;
    auto ack = p->ack;
    butex_wake_all_return2.push_back(bthread_self_tag());
    std::unique_lock<bthread::Mutex> lk(*mutex);
    ack->signal();
    cond->wait(lk);
    butex_wake_all_return2.push_back(bthread_self_tag());
    return nullptr;
}

TEST(BthreadButexMultiTest, butex_requeue) {
    bthread::Mutex mutex;
    bthread::ConditionVariable cond;
    bthread::CountdownEvent ack(2);
    ButexRequeueArgs args{&mutex, &cond, &ack};

    bthread_t tid1, tid2;
    bthread_attr_t attr1 = BTHREAD_ATTR_NORMAL;
    attr1.tag = 1;
    bthread_start_background(&tid1, &attr1, butex_requeue_func1, &args);
    bthread_attr_t attr2 = BTHREAD_ATTR_NORMAL;
    attr2.tag = 2;
    bthread_start_background(&tid2, &attr2, butex_requeue_func2, &args);
    ack.wait();
    {
        std::unique_lock<bthread::Mutex> lk(mutex);
        cond.notify_all();
    }
    {
        std::unique_lock<bthread::Mutex> lk(mutex);
        cond.notify_all();
    }
    bthread_join(tid1, nullptr);
    bthread_join(tid2, nullptr);
    ASSERT_EQ(butex_wake_all_return1[0], butex_wake_all_return1[1]);
    ASSERT_EQ(butex_wake_all_return2[0], butex_wake_all_return2[1]);
}

}  // namespace
