/*
 * Copyright 2021 The casbin Authors. All Rights Reserved.
 *
 * Licensed 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.
 *
 * This is a test file showcasing the workflow of casbin::SyncedEnforcer
 */

#include <casbin/casbin.h>
#include <gtest/gtest.h>

#include "config_path.h"

namespace {

std::string global_sub;
std::string global_obj;
std::string global_act;
std::string global_domain;

template <typename T>
std::shared_ptr<casbin::IEvaluator> InitializeParams(const std::string& sub, const std::string& obj, const std::string& act) {
    auto evaluator = std::make_shared<T>();
    evaluator->InitialObject("r");

    // Because of "Short String Optimization", these strings's data is in stack.
    // For MSVC compiler, when this stack frame return, these memory will can't access.
    // So we need keep this memory accessiable.
    global_sub = sub;
    global_obj = obj;
    global_act = act;

    evaluator->PushObjectString("r", "sub", global_sub);
    evaluator->PushObjectString("r", "obj", global_obj);
    evaluator->PushObjectString("r", "act", global_act);

    return evaluator;
}

template <typename T>
std::shared_ptr<casbin::IEvaluator> InitializeParamsWithoutUsers(const std::string& obj, const std::string& act) {
    auto evaluator = std::make_shared<T>();
    evaluator->InitialObject("r");

    global_obj = obj;
    global_act = act;
    evaluator->PushObjectString("r", "obj", global_obj);
    evaluator->PushObjectString("r", "act", global_act);
    return evaluator;
}

template <typename T>
std::shared_ptr<casbin::IEvaluator> InitializeParamsWithoutResources(const std::string& sub, const std::string& act) {
    auto evaluator = std::make_shared<T>();
    evaluator->InitialObject("r");

    global_sub = sub;
    global_act = act;
    evaluator->PushObjectString("r", "sub", global_sub);
    evaluator->PushObjectString("r", "act", global_act);
    return evaluator;
}

template <typename T>
std::shared_ptr<casbin::IEvaluator> InitializeParamsWithDomains(const std::string& sub, const std::string& domain, const std::string& obj, const std::string& act) {
    auto evaluator = std::make_shared<T>();
    evaluator->InitialObject("r");

    global_sub = sub;
    global_obj = obj;
    global_act = act;
    global_domain = domain;

    evaluator->PushObjectString("r", "sub", global_sub);
    evaluator->PushObjectString("r", "dom", global_domain);
    evaluator->PushObjectString("r", "obj", global_obj);
    evaluator->PushObjectString("r", "act", global_act);
    return evaluator;
}

void TestSyncFn(casbin::SyncedEnforcer& e, const std::string& sub, const std::string& obj, const std::string& act, bool control) {
    bool response = e.Enforce({sub, obj, act});
    ASSERT_EQ(response, control);
}

TEST(TestEnforcerSynced, TestSync) {
    casbin::SyncedEnforcer e(basic_model_path, basic_policy_path);

    using namespace std::literals::chrono_literals;
    auto time1 = 200ms;
    e.StartAutoLoadPolicy(time1);

    TestSyncFn(e, "alice", "data1", "read", true);
    TestSyncFn(e, "alice", "data1", "write", false);
    TestSyncFn(e, "alice", "data2", "read", false);
    TestSyncFn(e, "alice", "data2", "write", false);
    TestSyncFn(e, "bob", "data1", "read", false);
    TestSyncFn(e, "bob", "data1", "write", false);
    TestSyncFn(e, "bob", "data2", "read", false);
    TestSyncFn(e, "bob", "data2", "write", true);

    std::this_thread::sleep_for(200ms);
    e.StopAutoLoadPolicy();
}

TEST(TestEnforcerSynced, TestStopLoadPolicy) {
    casbin::SyncedEnforcer e(basic_model_path, basic_policy_path);

    using namespace std::literals::chrono_literals;
    std::chrono::duration<int64_t, std::nano> t = 5ms;

    e.StartAutoLoadPolicy(t);

    EXPECT_EQ(e.IsAutoLoadingRunning(), true);

    TestSyncFn(e, "alice", "data1", "read", true);
    TestSyncFn(e, "alice", "data1", "write", false);
    TestSyncFn(e, "alice", "data2", "read", false);
    TestSyncFn(e, "alice", "data2", "write", false);
    TestSyncFn(e, "bob", "data1", "read", false);
    TestSyncFn(e, "bob", "data1", "write", false);
    TestSyncFn(e, "bob", "data2", "read", false);
    TestSyncFn(e, "bob", "data2", "write", true);

    e.StopAutoLoadPolicy();
    std::this_thread::sleep_for(10ms);

    EXPECT_EQ(e.IsAutoLoadingRunning(), false);
}

TEST(TestEnforcerSynced, TestMultiThreadEnforce) {
    casbin::SyncedEnforcer e(basic_model_path, basic_policy_path);

    using namespace std::literals::chrono_literals;
    std::chrono::duration<int64_t, std::nano> t = 5ms;

    e.StartAutoLoadPolicy(t);

    EXPECT_EQ(e.IsAutoLoadingRunning(), true);

    for (int i = 0; i < 100; ++i) {
        std::thread t1([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"alice", "data1", "read"}), true); });
        std::thread t2([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"alice", "data1", "write"}), false); });
        std::thread t3([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"alice", "data2", "read"}), false); });
        std::thread t4([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"alice", "data2", "write"}), false); });
        std::thread t5([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"bob", "data1", "read"}), false); });
        std::thread t6([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"bob", "data1", "write"}), false); });
        std::thread t7([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"bob", "data2", "read"}), false); });
        std::thread t8([&] { ASSERT_EQ(e.Enforce(casbin::DataList{"bob", "data2", "write"}), true); });

        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
        t6.join();
        t7.join();
        t8.join();
    }

    for (int i = 0; i < 100; ++i) {
        std::thread t1([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"alice", "data1", "read"}), true); });
        std::thread t2([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"alice", "data1", "write"}), false); });
        std::thread t3([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"alice", "data2", "read"}), false); });
        std::thread t4([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"alice", "data2", "write"}), false); });
        std::thread t5([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"bob", "data1", "read"}), false); });
        std::thread t6([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"bob", "data1", "write"}), false); });
        std::thread t7([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"bob", "data2", "read"}), false); });
        std::thread t8([&] { ASSERT_EQ(e.Enforce(casbin::DataVector{"bob", "data2", "write"}), true); });

        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
        t6.join();
        t7.join();
        t8.join();
    }

    for (int i = 0; i < 100; ++i) {
        std::thread t1([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "alice"}, {"obj", "data1"}, {"act", "read"}}), true); });
        std::thread t2([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "alice"}, {"obj", "data1"}, {"act", "write"}}), false); });
        std::thread t3([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "alice"}, {"obj", "data2"}, {"act", "read"}}), false); });
        std::thread t4([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "alice"}, {"obj", "data2"}, {"act", "write"}}), false); });
        std::thread t5([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "bob"}, {"obj", "data1"}, {"act", "read"}}), false); });
        std::thread t6([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "bob"}, {"obj", "data1"}, {"act", "write"}}), false); });
        std::thread t7([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "bob"}, {"obj", "data2"}, {"act", "read"}}), false); });
        std::thread t8([&] { ASSERT_EQ(e.Enforce(casbin::DataMap{{"sub", "bob"}, {"obj", "data2"}, {"act", "write"}}), true); });

        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
        t6.join();
        t7.join();
        t8.join();
    }

    std::mutex mtx; // for evaluator
    for (int i = 0; i < 100; ++i) {
        std::thread t1([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("alice", "data1", "read");
            }
            ASSERT_EQ(e.Enforce(evaluator), true);
        });
        std::thread t2([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("alice", "data1", "write");
            }
            ASSERT_EQ(e.Enforce(evaluator), false);
        });
        std::thread t3([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("alice", "data2", "read");
            }
            ASSERT_EQ(e.Enforce(evaluator), false);
        });
        std::thread t4([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("alice", "data2", "write");
            }
            ASSERT_EQ(e.Enforce(evaluator), false);
        });
        std::thread t5([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("bob", "data1", "read");
            }
            ASSERT_EQ(e.Enforce(evaluator), false);
        });
        std::thread t6([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("bob", "data1", "write");
            }
            ASSERT_EQ(e.Enforce(evaluator), false);
        });
        std::thread t7([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("bob", "data2", "read");
            }
            ASSERT_EQ(e.Enforce(evaluator), false);
        });
        std::thread t8([&] {
            std::shared_ptr<casbin::IEvaluator> evaluator;
            {
                std::scoped_lock lock(mtx);
                evaluator = InitializeParams<casbin::ExprtkEvaluator>("bob", "data2", "write");
            }
            ASSERT_EQ(e.Enforce(evaluator), true);
        });

        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
        t6.join();
        t7.join();
        t8.join();
    }

    e.StopAutoLoadPolicy();
    std::this_thread::sleep_for(10ms);

    EXPECT_EQ(e.IsAutoLoadingRunning(), false);
}

TEST(TestEnforcerSynced, TestMultiThreadBatchEnforce) {
    casbin::SyncedEnforcer e(basic_model_path, basic_policy_path);

    using namespace std::literals::chrono_literals;
    std::chrono::duration<int64_t, std::nano> t = 5ms;

    e.StartAutoLoadPolicy(t);

    EXPECT_EQ(e.IsAutoLoadingRunning(), true);

    for (int i = 0; i < 100; ++i) {
        std::thread t1([&] {
            std::vector<bool> expect_result{true, false, false, false};
            ASSERT_EQ(e.BatchEnforce({{"alice", "data1", "read"}, {"alice", "data1", "write"}, {"alice", "data2", "read"}, {"alice", "data2", "write"}}), expect_result);
        });

        std::thread t2([&] {
            std::vector<bool> expect_result{false, false, false, true};
            ASSERT_EQ(e.BatchEnforce({{"bob", "data1", "read"}, {"bob", "data1", "write"}, {"bob", "data2", "read"}, {"bob", "data2", "write"}}), expect_result);
        });

        std::thread t3([&] {
            std::vector<bool> expect_result{true, false, false, false};
            ASSERT_EQ(e.BatchEnforce({{"alice", "data1", "read"}, {"alice", "data1", "write"}, {"bob", "data1", "read"}, {"bob", "data1", "write"}}), expect_result);
        });

        std::thread t4([&] {
            std::vector<bool> expect_result{false, false, false, true};
            ASSERT_EQ(e.BatchEnforce({{"alice", "data2", "read"}, {"alice", "data2", "write"}, {"bob", "data2", "read"}, {"bob", "data2", "write"}}), expect_result);
        });

        t1.join();
        t2.join();
        t3.join();
        t4.join();
    }

    e.StopAutoLoadPolicy();
    std::this_thread::sleep_for(10ms);

    EXPECT_EQ(e.IsAutoLoadingRunning(), false);
}

void testSyncedEnforcerGetPolicy(casbin::SyncedEnforcer& e, PoliciesVector expected) {
    auto myRes = e.GetPolicy();
    PoliciesVector actual;
    for (auto it = myRes.begin(); it != myRes.end(); ++it) {
        actual.push_back(*it);
    }
    std::sort(actual.begin(), actual.end());
    std::sort(expected.begin(), expected.end());
    ASSERT_EQ(expected, actual);
}

TEST(TestSyncedEnforcer, GetPolicy) {
    casbin::SyncedEnforcer e(basic_model_path, basic_policy_path);

    PoliciesVector expected_policy = {
        {"alice", "data1", "read"},
        {"bob", "data2", "write"},
    };

    testSyncedEnforcerGetPolicy(e, expected_policy);
}



} // namespace
