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

#include <buildboxcommon_argvec.h>

using buildboxcommon::Argvec;

TEST(CasuploadArgs, HelpTest)
{
    auto argvec = Argvec({"casupload", "--help"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_FALSE(args.d_valid);
}

TEST(CasuploadArgs, NoRemoteTest)
{
    // Either --remote or --cas-server are required
    auto argvec = Argvec({"casupload", "a.txt", "b.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_FALSE(args.d_valid);
}

TEST(CasuploadArgs, DefaultsTest)
{
    auto argvec = Argvec({"casupload", "--remote=http://a", "a.txt", "b.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_FALSE(args.d_dryRunMode);
    ASSERT_EQ(args.d_casConnectionOptions.d_url, "http://a");
    ASSERT_EQ(args.d_logLevel, buildboxcommon::LogLevel::ERROR);
    ASSERT_FALSE(args.d_followSymlinks);
    ASSERT_EQ(args.d_paths.size(), 2);
    ASSERT_EQ(args.d_paths[0], "a.txt");
    ASSERT_EQ(args.d_paths[1], "b.txt");
    ASSERT_EQ(args.d_ignoreFile, "");
    ASSERT_EQ(args.d_outputRootDigestFile, "");
    ASSERT_TRUE(args.d_numUploadThreads <= 32);
    ASSERT_TRUE(args.d_numDigestThreads <= 16);
    ASSERT_FALSE(args.d_localCasOption.d_useLocalCas);
    ASSERT_FALSE(args.d_localCasOption.d_bypassLocalCache);
}

TEST(CasuploadArgs, CasServerFallback)
{
    auto argvec = Argvec({"casupload", "--cas-server=http://b", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_EQ(args.d_casConnectionOptions.d_url, "http://b");
}

TEST(CasuploadArgs, RemoteOverridesCasServer)
{
    auto argvec = Argvec(
        {"casupload", "--remote=http://a", "--cas-server=http://b", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_EQ(args.d_casConnectionOptions.d_url, "http://a");
}

TEST(CasuploadArgs, FollowSymlinksTest)
{
    auto argvec = Argvec(
        {"casupload", "--remote=http://a", "--follow-symlinks", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_TRUE(args.d_followSymlinks);
}

TEST(CasuploadArgs, DryRunModeTest)
{
    auto argvec =
        Argvec({"casupload", "--dry-run", "--remote=http://a", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_TRUE(args.d_dryRunMode);
}

TEST(CasuploadArgs, OutputRootDigestTest)
{
    auto argvec = Argvec({"casupload", "--output-digest-file=FILE",
                          "--remote=http://a", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_EQ(args.d_outputRootDigestFile, "FILE");
}

TEST(CasuploadArgs, OutputTreeDigestTest)
{
    auto argvec = Argvec({"casupload", "--output-tree-digest-file=FILE",
                          "--remote=http://a", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_EQ(args.d_outputTreeDigestFile, "FILE");
}

TEST(CasuploadArgs, IgnoreFileTest)
{
    auto argvec = Argvec({"casupload", "--ignore-file=ignorefile",
                          "--remote=http://a", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_EQ(args.d_ignoreFile, "ignorefile");
}

TEST(CasuploadArgs, LogLevelTest)
{
    auto argvec = Argvec(
        {"casupload", "--log-level=warning", "--remote=http://a", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_EQ(args.d_logLevel, buildboxcommon::LogLevel::WARNING);
}

TEST(CasuploadArgs, VerboseTest)
{
    auto argvec =
        Argvec({"casupload", "--verbose", "--remote=http://a", "a.txt"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    ASSERT_EQ(args.d_logLevel, buildboxcommon::LogLevel::DEBUG);
}

TEST(CasuploadArgs, CapturePropertiesTest)
{
    auto argvec = Argvec({"casupload", "--remote=http://a", "--capture-mtime",
                          "--capture-unix-mode", "--file-umask=07222",
                          "--node-property=SubtreeReadOnly=true", "foo"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    EXPECT_TRUE(args.d_captureMtime);
    EXPECT_TRUE(args.d_captureUnixMode);
    EXPECT_EQ(args.d_fileUmask, 07222);
    EXPECT_EQ(args.d_nodeProperties.size(), 1);
    EXPECT_EQ(args.d_nodeProperties.at("SubtreeReadOnly"), "true");
}

TEST(CasuploadArgs, CapturePropertiesInvalidUmaskTest)
{
    auto argvec = Argvec({"casupload", "--remote=http://a", "--capture-mtime",
                          "--capture-unix-mode", "--file-umask=07888", "foo"});
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_FALSE(args.d_valid);
}

TEST(CasuploadArgs, CaptureThreadedTest)
{
    auto argvec = Argvec({
        "casupload",
        "--remote=http://a",
        "--num-upload-threads=4",
        "--num-digest-threads=8",
        "foo",
    });
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    EXPECT_EQ(args.d_numUploadThreads, 4);
    EXPECT_EQ(args.d_numDigestThreads, 8);
}

TEST(CasuploadArgs, CaptureLocalCasTest)
{
    auto argvec = Argvec({
        "casupload",
        "--remote=http://a",
        "--use-localcas",
        "--bypass-local-cache",
        "foo",
    });
    auto args = casupload::processArgs(argvec.argc(), argvec.argv());
    ASSERT_TRUE(args.d_valid);
    EXPECT_TRUE(args.d_localCasOption.d_useLocalCas);
    EXPECT_TRUE(args.d_localCasOption.d_bypassLocalCache);
}
