[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/expresscpp/expresscpp/master/test/basic.cpp [Back]  [Original]

#include "expresscpp/console.hpp"
#include "expresscpp/expresscpp.hpp"
#include "expresscpp/fetch.hpp"
#include "expresscpp/impl/routing_stack.hpp"
#include "gtest/gtest.h"
#include "nlohmann/json.hpp"
#include "test_utils.hpp"

using namespace expresscpp;
using namespace std::string_literals;

constexpr std::size_t port = 8081u;

std::shared_ptr RoutePath(ExpressCpp &app, std::string_view path, std::string_view test_data,
                                    HttpMethod method) {
  auto req = std::make_shared(path, method);
  auto res = std::make_shared(nullptr);
  std::string name = "special_header";
  req->setHeader(name, test_data.data());
  app.HandleRequest(req, res, nullptr);
  return res;
}

TEST(BasicTests, RunAndStop) {
  ExpressCpp expresscpp;
  std::thread runner([&expresscpp]() { expresscpp.Run(); });
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  expresscpp.Stop();
  runner.join();
}

TEST(BasicTests, DumpStack) {
  {
    ExpressCpp app;
    app.Get("/", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/"); });
    const auto rs = app.Stack();
    auto contains = [&]() {
      for (const auto &r : rs) {
        Console::Debug(fmt::format(R"(contains "{}")", r.path));
        if (r.path == "/") {
          return true;
        }
      }
      return false;
    }();
    EXPECT_TRUE(contains);
  }
  {
    ExpressCpp app;
    app.Get("/a", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/"); });
    app.Get("/b", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/"); });
    const auto rs = app.Stack();
    auto contains_a = [&]() {
      for (const auto &r : rs) {
        if (r.path == "/a") {
          EXPECT_EQ(r.method, HttpMethod::Get);
          return true;
        }
      }
      return false;
    }();
    EXPECT_TRUE(contains_a);
    auto contains_b = [&]() {
      for (const auto &r : rs) {
        if (r.path == "/b") {
          EXPECT_EQ(r.method, HttpMethod::Get);
          return true;
        }
      }
      return false;
    }();
    EXPECT_TRUE(contains_b);
  }
}

TEST(BasicTests, DumpStackWithMiddleware) {
  ExpressCpp app;
  auto logger = [](auto /*req*/, auto /*res*/, auto next) {
    Console::Debug("function called");
    next();
  };
  app.Use(logger);

  app.Get("/", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/"); });
  const auto rs = app.Stack();
  std::size_t number_of_root_routes = 0;

  auto contains_routes_in_stack = [&]() {
    for (const auto &r : rs) {
      if (r.path == "/") {
        number_of_root_routes++;
        // logger has method all, route has method get
        EXPECT_TRUE(r.method == HttpMethod::Get || r.method == HttpMethod::All);
      }
    }

    if (number_of_root_routes == 2) {
      return true;
    }

    return false;
  }();

  EXPECT_TRUE(contains_routes_in_stack);
}

TEST(BasicTests, SingleRouteWithParams) {
  ExpressCpp app;
  app.Get("/:id", [](auto req, auto res, auto /*next*/) {
    EXPECT_EQ(req->GetParams().size(), 1);
    EXPECT_EQ(req->GetParams().at("id"), "10");
    res->Json(R"({"status": 1 })");
  });
  app.Listen(port, [=](auto ec) {
    EXPECT_FALSE(ec);
    auto r = fetch(fmt::format("localhost:{}/10", port), { HttpMethod::Get});
    const auto expected = nlohmann::json::parse(r);
    EXPECT_EQ(expected["status"], 1);
  });
}

TEST(BasicTests, SingleRouteWithRangeParams) {
  ExpressCpp app;
  app.Get("/things/:from-:to", [](auto req, auto res, auto /*next*/) {
    EXPECT_EQ(req->GetParams().size(), 2);
    EXPECT_EQ(req->GetParams().at("from"), "157");
    EXPECT_EQ(req->GetParams().at("to"), "2158");
    res->Json(R"({"status": 1 })");
  });
  app.Listen(8081, [](auto ec) {
    EXPECT_FALSE(ec);
    auto r = fetch(fmt::format("http://localhost:{}/things/157-2158", port), { HttpMethod::Get});
    const auto expected = nlohmann::json::parse(r);
    EXPECT_EQ(expected["status"], 1);
  });
}

TEST(BasicTests, SingleRouteWithParamsAndQueryParams) {
  ExpressCpp app;
  app.Get("/things/:id", [](auto req, auto res, auto /*next*/) {
    EXPECT_EQ(req->GetParams().size(), 1);
    EXPECT_EQ(req->GetParams().at("id"), "1234");
    EXPECT_EQ(req->GetQueryParams().size(), 1);
    EXPECT_EQ(req->GetQueryParams().at("key1"), "value1");
    res->Json(R"({"status": 1 })");
  });
  app.Listen(8081, [](auto ec) {
    EXPECT_FALSE(ec);
    auto r = fetch(fmt::format("http://localhost:{}/things/1234?key1=value1", port), { HttpMethod::Get});
    const auto expected = nlohmann::json::parse(r);
    EXPECT_EQ(expected["status"], 1);
  });
}

TEST(BasicTests, SingleRouteWithQueryParams) {
  ExpressCpp app;
  app.Get("/", [](auto req, auto res, auto /*next*/) {
    EXPECT_EQ(req->GetParams().size(), 0);
    EXPECT_EQ(req->GetQueryParams().size(), 1);
    EXPECT_EQ(req->GetQueryParams().at("key1"), "value1");
    res->Json(R"({"status": 1 })");
  });
  app.Listen(8081, [](auto ec) {
    EXPECT_FALSE(ec);
    auto r = fetch(fmt::format("http://localhost:{}/?key1=value1", port), { HttpMethod::Get});
    const auto expected = nlohmann::json::parse(r);
    EXPECT_EQ(expected["status"], 1);
  });
}

TEST(BasicTests, SingleRouteJson) {
  TestCallSleeper sleeper(1);
  ExpressCpp app;
  app.Get("/", [&](auto /*req*/, auto res, auto /*next*/) {
    sleeper.Call();
    res->Json(R"({"status": 1 })");
  });
  app.Listen(port, [](auto ec) {
    EXPECT_FALSE(ec);
    auto r = fetch(fmt::format("localhost:{}/", port), { HttpMethod::Get});
    const auto expected = nlohmann::json::parse(r);
    EXPECT_EQ(expected["status"], 1);
  });
  EXPECT_TRUE(sleeper.Wait());
}

TEST(BasicTests, SingleRouteWithoutBeast) {
  {
    ExpressCpp app;

    app.Get("/", [](auto req, auto res, auto /*next*/) {
      auto headers = req->getHeaders();
      EXPECT_NE(headers.find("special_header"), headers.end());

      auto value = headers.at("special_header");
      EXPECT_EQ(value, "special_header_value");

      EXPECT_ANY_THROW(res->Json(R"({"status": 1 })"););
    });

    auto res = RoutePath(app, "/", "special_header_value", HttpMethod::Get);
    EXPECT_EQ(res->response_sent_, true);
  }

  {
    ExpressCpp app;

    app.Get("/aaa", [](auto req, auto res, auto /*next*/) {
      auto headers = req->getHeaders();
      EXPECT_NE(headers.find("special_header"), headers.end());

      auto value = headers.at("special_header");
      EXPECT_EQ(value, "special_header_value");

      EXPECT_ANY_THROW(res->Json(R"({"status": 1 })"););
    });

    auto res = RoutePath(app, "/aaa", "special_header_value", HttpMethod::Get);
    EXPECT_EQ(res->response_sent_, true);
  }

  {
    ExpressCpp app;

    app.Post("/aaa", [](auto req, auto res, auto /*next*/) {
      auto headers = req->getHeaders();
      EXPECT_NE(headers.find("special_header"), headers.end());

      auto value = headers.at("special_header");
      EXPECT_EQ(value, "special_header_value");

      EXPECT_ANY_THROW(res->Json(R"({"status": 1 })"););
    });

    auto res = RoutePath(app, "/aaa", "special_header_value", HttpMethod::Post);
    EXPECT_EQ(res->response_sent_, true);
  }
}

TEST(BasicTests, PostRouteWithoutBeast) {
  ExpressCpp app;

  app.Post("/aaa", [](auto req, auto res, auto /*next*/) {
    auto headers = req->getHeaders();
    EXPECT_NE(headers.find("special_header"), headers.end());

    auto value = headers.at("special_header");
    EXPECT_EQ(value, "special_header_value");

    EXPECT_ANY_THROW(res->Json(R"({"status": 1 })"););
  });

  auto res = RoutePath(app, "/aaa", "special_header_value", HttpMethod::Post);
  EXPECT_EQ(res->response_sent_, true);
}

TEST(BasicTests, MultiRoute) {
  ExpressCpp app;
  app.Get("/", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/"); });
  app.Get("/b", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/b"); });
  app.Listen(8081, [](auto ec) {
    EXPECT_FALSE(ec);
    auto r = fetch(fmt::format("localhost:{}/", port), { HttpMethod::Get});
    auto rb = fetch(fmt::format("localhost:{}/b", port), { HttpMethod::Get});
    EXPECT_EQ(r, "/");
    EXPECT_EQ(rb, "/b");
  });
}

TEST(BasicTests, MultipleListenCalls) {
  ExpressCpp app;
  app.Get("/a", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/a"); });
  app.Listen(port, [](const auto ec) { EXPECT_EQ(ec.value(), 0); });
  app.Listen(port, [](const auto ec) { EXPECT_EQ(ec, std::errc::already_connected); });
}

TEST(BasicTests, StartMultipleApps) {
  {
    ExpressCpp app1;
    constexpr std::size_t port1 = 8081u;
    app1.Get("/a", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/1"); });
    app1.Listen(port1, [&](std::error_code ec) {
      EXPECT_EQ(ec.value(), 0);
      auto r1 = fetch(fmt::format("localhost:{}/a", port1), { HttpMethod::Get});
      EXPECT_EQ(r1, "/1");
    });

    ExpressCpp app2;
    constexpr std::size_t port2 = 8082u;
    app2.Get("/a", [](auto /*req*/, auto res, auto /*next*/) { res->Send("/2"); });
    app2.Listen(port2, [&](std::error_code ec) {
      EXPECT_EQ(ec.value(), 0);
      auto r2 = fetch(fmt::format("localhost:{}/a", port2), { HttpMethod::Get});
      EXPECT_EQ(r2, "/2");
    });
  }
}

Web Proxy Viewer  |  New URL  |  Original Page