#include "expresscpp/expresscpp.hpp"
#include "expresscpp/fetch.hpp"
#include "expresscpp/impl/routing_stack.hpp"
#include "gtest/gtest.h"
#include "nlohmann/json.hpp"
using namespace expresscpp;
using namespace std::string_literals;
TEST(LayerTests, TestKeyFirst) {
auto layer = Layer("/:id");
auto req = std::make_shared("/12");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(layer.GetKeys().size(), 1);
EXPECT_EQ(layer.GetKeys()[0].name_, "id");
EXPECT_EQ(layer.GetKeys()[0].index_, 0);
EXPECT_EQ(req->GetParams().at("id"), "12");
}
TEST(LayerTests, TestIncompleteKey) {
EXPECT_ANY_THROW(Layer(":"));
EXPECT_ANY_THROW(Layer("/:"));
EXPECT_ANY_THROW(Layer("/a/b/:/c"));
EXPECT_ANY_THROW(Layer("/a/b/c/:"));
EXPECT_ANY_THROW(Layer("/a/:/c/:"));
}
TEST(LayerTests, TestWithSingleKey) {
auto layer = Layer("/:id/a");
auto req = std::make_shared("/12/a");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(layer.GetKeys().size(), 1);
EXPECT_EQ(layer.GetKeys()[0].name_, "id");
EXPECT_EQ(layer.GetKeys()[0].index_, 0);
EXPECT_EQ(req->GetParams().at("id"), "12");
}
TEST(LayerTests, TestWithMultipleKeys) {
auto layer = Layer("/:id1/a/:id2");
auto req = std::make_shared("/12/a/13");
EXPECT_EQ(layer.GetKeys().size(), 2);
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetParams().size(), 2);
EXPECT_EQ(layer.GetKeys()[0].name_, "id1");
EXPECT_EQ(layer.GetKeys()[0].index_, 0);
EXPECT_EQ(req->GetParams().at("id1"), "12");
EXPECT_EQ(layer.GetKeys()[1].name_, "id2");
EXPECT_EQ(layer.GetKeys()[1].index_, 1);
EXPECT_EQ(req->GetParams().at("id2"), "13");
}
TEST(LayerTests, TestWithRangesAtEnd) {
auto layer = Layer("/abc/:from-:to");
auto req = std::make_shared("/abc/100-200");
EXPECT_EQ(layer.GetKeys().size(), 2);
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetParams().size(), 2);
EXPECT_EQ(layer.GetKeys()[0].name_, "from");
EXPECT_EQ(layer.GetKeys()[0].index_, 0);
EXPECT_EQ(layer.GetKeys()[1].name_, "to");
EXPECT_EQ(layer.GetKeys()[1].index_, 1);
EXPECT_EQ(req->GetParams().at("from"), "100");
EXPECT_EQ(req->GetParams().at("to"), "200");
}
TEST(LayerTests, TestWithRangesInBetween) {
auto layer = Layer("/abc/:from-:to/a");
EXPECT_EQ(layer.GetKeys().size(), 2);
auto req = std::make_shared("/abc/100-200/a");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetParams().size(), 2);
EXPECT_EQ(layer.GetKeys()[0].name_, "from");
EXPECT_EQ(layer.GetKeys()[0].index_, 0);
EXPECT_EQ(layer.GetKeys()[1].name_, "to");
EXPECT_EQ(layer.GetKeys()[1].index_, 1);
EXPECT_EQ(req->GetParams().at("from"), "100");
EXPECT_EQ(req->GetParams().at("to"), "200");
}
TEST(LayerTests, TestWithMultipleRanges) {
auto layer = Layer("/abc/:from1-:to1/a/:from2-:to2/:from3-:to3/test/:from4-:to4/:from5-:to5");
EXPECT_EQ(layer.GetKeys().size(), 10);
auto req = std::make_shared("/abc/1-2/a/3-4/5-6/test/7-8/9-10");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetParams().size(), 10);
size_t name_index = 1;
for (size_t index = 0; index < req->GetParams().size();) {
const auto from = "from" + std::to_string(name_index);
const auto to = "to" + std::to_string(name_index);
EXPECT_EQ(layer.GetKeys()[index].name_, from);
EXPECT_EQ(layer.GetKeys()[index].index_, index);
EXPECT_EQ(layer.GetKeys()[index + 1].name_, to);
EXPECT_EQ(layer.GetKeys()[index + 1].index_, index + 1);
EXPECT_EQ(req->GetParams().at(from), std::to_string(index + 1));
EXPECT_EQ(req->GetParams().at(to), std::to_string(index + 2));
index += 2;
++name_index;
}
}
TEST(LayerTests, TestWithManyKeys) {
auto layer = Layer("/:id1/a/:id2/:id3/:id4/:id5/x/y/z/:id6");
EXPECT_EQ(layer.GetKeys().size(), 6);
auto req = std::make_shared("/1/a/2/3/4/5/x/y/z/6");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetParams().size(), 6);
for (size_t index = 0; index < 6; ++index) {
const auto name = "id" + std::to_string(index + 1);
EXPECT_EQ(layer.GetKeys()[index].name_, name);
EXPECT_EQ(layer.GetKeys()[index].index_, index);
EXPECT_EQ(req->GetParams().at(name), std::to_string(index + 1));
}
}
TEST(LayerTests, TestNonMatching) {
auto layer = Layer("/:id1/a/:id2/:id3/:id4/:id5/x/y/z/:id6");
auto req = std::make_shared("/1/abc/2/3/4/5/x/y/z/6");
EXPECT_FALSE(layer.Match(req));
EXPECT_EQ(req->GetParams().size(), 0);
}
TEST(LayerTests, TestMultiMatchings) {
auto layer = Layer("/:id1/a/:id2/:id3/:id4/:id5/x/y/z/:id6");
EXPECT_EQ(layer.GetKeys().size(), 6);
auto req = std::make_shared("/1/a/2/3/4/5/x/y/z/6");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetParams().size(), 6);
auto req2 = std::make_shared("/1/abc/2/3/4/5/x/y/z/6");
EXPECT_FALSE(layer.Match(req2));
EXPECT_EQ(req2->GetParams().size(), 0);
auto req3 = std::make_shared("/1/a/2/3/4/5/x/y/z/6");
EXPECT_TRUE(layer.Match(req3));
EXPECT_EQ(layer.GetKeys().size(), 6);
for (size_t index = 0; index < 6; ++index) {
const auto name = "id" + std::to_string(index + 1);
EXPECT_EQ(layer.GetKeys()[index].name_, name);
EXPECT_EQ(layer.GetKeys()[index].index_, index);
EXPECT_EQ(req3->GetParams().at(name), std::to_string(index + 1));
}
}
TEST(LayerTests, TestQueryParams) {
auto layer = Layer("/abc");
auto req = std::make_shared("/abc?key=value");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetQueryParams().size(), 1);
}
TEST(LayerTests, TestWithMoreQueryParams) {
auto layer = Layer("/abc");
auto req = std::make_shared("/abc?key1=value1&key2=value2&key3=value3");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetQueryParams().size(), 3);
}
TEST(LayerTests, TestWithParamsAndQueryParams) {
auto layer = Layer("/abc/:id");
auto req = std::make_shared("/abc/123?key1=value1&key2=value2&key3=value3");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetQueryParams().size(), 3);
EXPECT_EQ(req->GetParams().size(), 1);
for (size_t index = 0; index < req->GetQueryParams().size(); ++index) {
const auto key = "key" + std::to_string(index + 1);
const auto value = "value" + std::to_string(index + 1);
EXPECT_EQ(req->GetQueryParams().count(key), 1);
EXPECT_EQ(req->GetQueryParams().at(key), value);
}
}
TEST(LayerTests, TestWithInvalidQueryParams) {
auto layer = Layer("/abc");
auto req = std::make_shared("/abc?");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetQueryParams().size(), 0);
EXPECT_EQ(req->GetParams().size(), 0);
auto req1 = std::make_shared("/abc??");
EXPECT_TRUE(layer.Match(req1));
EXPECT_EQ(req1->GetQueryParams().size(), 0);
EXPECT_EQ(req1->GetParams().size(), 0);
auto req2 = std::make_shared("/abc&&");
EXPECT_FALSE(layer.Match(req2));
EXPECT_EQ(req2->GetQueryParams().size(), 0);
EXPECT_EQ(req2->GetParams().size(), 0);
auto req3 = std::make_shared("/abc?&&&&&??");
EXPECT_TRUE(layer.Match(req3));
EXPECT_EQ(req3->GetQueryParams().size(), 0);
EXPECT_EQ(req3->GetParams().size(), 0);
}
TEST(LayerTests, TestWithIncompleteQueryParams) {
auto layer = Layer("/abc/:id");
auto req = std::make_shared("/abc/123?key1=value1&key2&key3=value3");
EXPECT_TRUE(layer.Match(req));
EXPECT_EQ(req->GetQueryParams().size(), 1);
for (size_t index = 0; index < req->GetQueryParams().size(); ++index) {
const auto key = "key" + std::to_string(index + 1);
const auto value = "value" + std::to_string(index + 1);
EXPECT_EQ(req->GetQueryParams().count(key), 1);
EXPECT_EQ(req->GetQueryParams().at(key), value);
}
}