/*
 * Copyright (C) 2016 Canonical Ltd.
 * Copyright (C) 2026 UBports Foundation.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../../src/item_id.h"

#include <lomiri/storage/provider/Exceptions.h>
#include <gtest/gtest.h>

using namespace std;
using namespace lomiri::storage::provider;

TEST(ItemId, id_to_remote_path)
{
    EXPECT_EQ("", id_to_remote_path("."));
    EXPECT_EQ("file", id_to_remote_path("file"));
    EXPECT_EQ("folder/file", id_to_remote_path("folder/file"));
    // IDs carry a trailing slash to denote folders.
    EXPECT_EQ("folder", id_to_remote_path("folder/"));
    EXPECT_EQ("folder/sub", id_to_remote_path("folder/sub/"));
    // Percent-escapes are decoded.
    EXPECT_EQ("hello world", id_to_remote_path("hello%20world"));
    EXPECT_EQ("naïve", id_to_remote_path("na%C3%AFve"));

    // IDs escaping the remote root are rejected.
    EXPECT_THROW(id_to_remote_path(""), InvalidArgumentException);
    EXPECT_THROW(id_to_remote_path("/etc/passwd"), InvalidArgumentException);
    EXPECT_THROW(id_to_remote_path(".."), InvalidArgumentException);
    EXPECT_THROW(id_to_remote_path("folder/../../file"), InvalidArgumentException);
    EXPECT_THROW(id_to_remote_path("folder/./file"), InvalidArgumentException);

    EXPECT_THROW(id_to_remote_path("%2Fetc%2Fpasswd"), InvalidArgumentException);
    EXPECT_THROW(id_to_remote_path("%2E%2E%2F%2E%2E%2Fetc%2Fpasswd"),
                 InvalidArgumentException);
}

TEST(ItemId, parent_of)
{
    EXPECT_EQ(".", parent_of("file"));
    EXPECT_EQ(".", parent_of("folder/"));
    EXPECT_EQ("folder/", parent_of("folder/file"));
    EXPECT_EQ("folder/", parent_of("folder/sub/"));
    EXPECT_EQ("a/b/", parent_of("a/b/c"));
}

TEST(ItemId, name_of)
{
    EXPECT_EQ("file", name_of("file"));
    EXPECT_EQ("folder", name_of("folder/"));
    EXPECT_EQ("file", name_of("folder/file"));
    EXPECT_EQ("sub", name_of("folder/sub/"));
    // Percent-escapes are decoded.
    EXPECT_EQ("hello world?", name_of("foo/hello%20world%3F"));
    EXPECT_EQ("naïve", name_of("foo/na%C3%AFve"));
}

TEST(ItemId, make_child_id)
{
    EXPECT_EQ("foo", make_child_id(".", "foo"));
    EXPECT_EQ("foo/bar", make_child_id("foo", "bar"));
    EXPECT_EQ("foo/bar", make_child_id("foo/", "bar"));

    // Constructing a folder-type child ID
    EXPECT_EQ("foo/", make_child_id(".", "foo", true));
    EXPECT_EQ("foo/bar/", make_child_id("foo/", "bar", true));

    EXPECT_EQ("foo/hello%20world%3F", make_child_id("foo/", "hello world?"));
    EXPECT_EQ("foo/na%C3%AFve", make_child_id("foo/", "naïve"));

    EXPECT_THROW(make_child_id("foo/", "."), InvalidArgumentException);
    EXPECT_THROW(make_child_id("foo/", ".."), InvalidArgumentException);
}

TEST(ItemId, is_folder)
{
    EXPECT_TRUE(is_folder("."));
    EXPECT_TRUE(is_folder("foo/"));
    EXPECT_TRUE(is_folder("foo/bar/"));

    EXPECT_FALSE(is_folder("foo"));
    EXPECT_FALSE(is_folder("foo/bar"));

    EXPECT_THROW(is_folder(""), InvalidArgumentException);
}

int main(int argc, char**argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
