/*
 * Copyright 2024 Bloomberg LP
 *
 * 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.
 */

#include <buildboxcommon_connectionoptions.h>
#include <buildboxcommon_connectionoptions_toml.h>
#include <toml++/toml.h>

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

using namespace buildboxcommon;
using namespace testing;

TEST(ConnectionOptionsTOMLTest, ParseConfig)
{
    std::string configStr = R"([connection]
remote = "https://remote:50051"
instance = "dev"
server-cert = "path1"
client-key = "path2"
client-cert = "path3"
access-token = "path4"
token-reload-interval = 1
googleapi-auth = true
retry-limit = 2
retry-delay = 3
retry-on-code = ["UNKNOWN", "INTERNAL"]
request-timeout = 4
min-throughput = "100G"
keepalive-time = 5
load-balancing-policy = "round-robin")";

    toml::table config = toml::parse(configStr);

    ConnectionOptions options = ConnectionOptionsTOML::configureChannel(
        *config["connection"].as_table());

    ASSERT_EQ(options.d_url, "https://remote:50051");
    ASSERT_EQ(options.d_instanceName, "dev");
    ASSERT_EQ(options.d_serverCertPath, "path1");
    ASSERT_EQ(options.d_clientKeyPath, "path2");
    ASSERT_EQ(options.d_clientCertPath, "path3");
    ASSERT_EQ(options.d_accessTokenPath, "path4");
    ASSERT_EQ(options.d_tokenReloadInterval, "1");
    ASSERT_EQ(options.d_useGoogleApiAuth, true);
    ASSERT_EQ(options.d_retryLimit, "2");
    ASSERT_EQ(options.d_retryDelay, "3");
    ASSERT_EQ(options.d_retryOnCodes,
              std::set({grpc::UNKNOWN, grpc::INTERNAL}));
    ASSERT_EQ(options.d_requestTimeout, "4");
    ASSERT_EQ(options.d_minThroughput, 100 * 1000000000LL);
    ASSERT_EQ(options.d_keepaliveTime, "5");
    ASSERT_EQ(options.d_loadBalancingPolicy, "round-robin");
}

TEST(ConnectionOptionsTOMLTest, Update)
{
    std::string configStr = R"(
[connection]
remote = "https://remote:50051"
instance = "dev"
retry-limit = 2
retry-on-code = ["UNKNOWN"]

[connection2]
remote = "https://remote:50051"
instance = "prod"
retry-limit = 5
retry-on-code = ["INTERNAL"]
)";

    toml::table config = toml::parse(configStr);

    ConnectionOptions options = ConnectionOptionsTOML::configureChannel(
        *config["connection"].as_table());
    ConnectionOptionsTOML::updateChannel(*config["connection2"].as_table(),
                                         options);

    ASSERT_EQ(options.d_url, "https://remote:50051");
    ASSERT_EQ(options.d_instanceName, "prod");
    ASSERT_EQ(options.d_retryLimit, "5");
    ASSERT_EQ(options.d_retryOnCodes, std::set({grpc::INTERNAL}));
}

TEST(ConnectionOptionsTOMLTest, TypeError)
{
    std::string configStr = R"(
[connection]
remote = "https://remote:50051"
instance = 3
retry-limit = "foo"
)";

    toml::table config = toml::parse(configStr);
    EXPECT_THROW(ConnectionOptionsTOML::configureChannel(
                     *config["connection"].as_table()),
                 std::invalid_argument);
}

TEST(ConnectionOptionsTOMLTest, CredentialHelper)
{
    std::string configStr = R"(
[connection]
remote = "grpcs://example.com"
credential-helper = "/usr/bin/helper"
)";

    toml::table config = toml::parse(configStr);

    ConnectionOptions options = ConnectionOptionsTOML::configureChannel(
        *config["connection"].as_table());

    ASSERT_EQ(options.d_url, "grpcs://example.com");
    ASSERT_EQ(options.d_credentialHelperPath, "/usr/bin/helper");
}
