Commit 86ef2a43 authored by Jacob Bogdanov's avatar Jacob Bogdanov

Upgrade to C++17 and use std::optional

Fixes #858

Replace `Pistache::Optional` with `std::optional`
parent 5b5e374d
......@@ -2,8 +2,8 @@ cmake_minimum_required (VERSION 3.11)
set(CMAKE_BUILD_TYPE_INIT Release)
# CMAKE Pin cxx compiler to CXX14 until update to CXX17
set(CMAKE_CXX_STANDARD 14)
# CMAKE Pin cxx compiler to CXX17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
......
......@@ -4,7 +4,7 @@
[![Build Status](https://travis-ci.org/pistacheio/pistache.svg?branch=master)](https://travis-ci.org/pistacheio/pistache)
Pistache is a modern and elegant HTTP and REST framework for C++. It is entirely written in pure-C++14 and provides a clear and pleasant API.
Pistache is a modern and elegant HTTP and REST framework for C++. It is entirely written in pure-C++17 and provides a clear and pleasant API.
## Documentation
......@@ -214,13 +214,13 @@ Be patient, async_test can take some time before completing. And that's it, now
Some other Meson options:
| Option | Default | Description |
|-------------------------------|-------------|------------------------------------------------|
| PISTACHE_USE_SSL | False | Build server with SSL support |
| PISTACHE_BUILD_TESTS | False | Build all of the unit tests |
| PISTACHE_ENABLE_NETWORK_TESTS | True | Run unit tests requiring remote network access |
| PISTACHE_BUILD_EXAMPLES | False | Build all of the example apps |
| PISTACHE_BUILD_DOCS | False | Build Doxygen docs |
| Option | Default | Description |
| ----------------------------- | ------- | ---------------------------------------------- |
| PISTACHE_USE_SSL | False | Build server with SSL support |
| PISTACHE_BUILD_TESTS | False | Build all of the unit tests |
| PISTACHE_ENABLE_NETWORK_TESTS | True | Run unit tests requiring remote network access |
| PISTACHE_BUILD_EXAMPLES | False | Build all of the example apps |
| PISTACHE_BUILD_DOCS | False | Build Doxygen docs |
## Continuous Integration Testing
......
......@@ -32,7 +32,7 @@ Depends:
rapidjson-dev (>= 1.1.0)
Description: elegant C++ REST framework
Pistache is a C++ REST framework originally written by Mathieu Stefani at
Datacratic, since maintained by other volunteers. It is written in pure C++14
Datacratic, since maintained by other volunteers. It is written in pure C++17
with no external dependency and provides a low-level HTTP abstraction.
.
Pistache provides both an HTTP client and server that can be used to create and
......@@ -51,7 +51,7 @@ Depends:
${shlibs:Depends}
Description: elegant C++ REST framework
Pistache is a C++ REST framework originally written by Mathieu Stefani at
Datacratic, since maintained by other volunteers. It is written in pure C++14
Datacratic, since maintained by other volunteers. It is written in pure C++17
with no external dependency and provides a low-level HTTP abstraction.
.
Pistache provides both an HTTP client and server that can be used to create and
......
......@@ -9,12 +9,12 @@
#include <ctime>
#include <list>
#include <map>
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <pistache/http_defs.h>
#include <pistache/optional.h>
namespace Pistache
{
......@@ -30,11 +30,11 @@ namespace Pistache
std::string name;
std::string value;
Optional<std::string> path;
Optional<std::string> domain;
Optional<FullDate> expires;
std::optional<std::string> path;
std::optional<std::string> domain;
std::optional<FullDate> expires;
Optional<int> maxAge;
std::optional<int> maxAge;
bool secure;
bool httpOnly;
......
......@@ -9,6 +9,7 @@
#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <vector>
......@@ -16,7 +17,6 @@
#include <pistache/http_defs.h>
#include <pistache/iterator_adapter.h>
#include <pistache/mime.h>
#include <pistache/optional.h>
#include <pistache/router.h>
namespace Pistache
......@@ -154,8 +154,8 @@ namespace Pistache
std::string description;
std::string termsOfService;
Optional<Contact> contact;
Optional<License> license;
std::optional<Contact> contact;
std::optional<License> license;
};
struct InfoBuilder
......@@ -305,7 +305,7 @@ namespace Pistache
{ }
Group paths(const std::string& name) const;
Optional<Path> path(const std::string& name, Http::Method method) const;
std::optional<Path> path(const std::string& name, Http::Method method) const;
group_iterator add(Path path);
......
......@@ -125,7 +125,7 @@ namespace Pistache
std::initializer_list<std::pair<const std::string, std::string>> params);
void add(std::string name, std::string value);
Optional<std::string> get(const std::string& name) const;
std::optional<std::string> get(const std::string& name) const;
bool has(const std::string& name) const;
// Return empty string or "?key1=value1&key2=value2" if query exist
std::string as_str() const;
......
......@@ -101,7 +101,7 @@ namespace Pistache
std::shared_ptr<const Header> tryGet(const std::string& name) const;
std::shared_ptr<Header> tryGet(const std::string& name);
Optional<Raw> tryGetRaw(const std::string& name) const;
std::optional<Raw> tryGetRaw(const std::string& name) const;
template <typename H>
typename std::enable_if<IsHeader<H>::value, bool>::type has() const
......
......@@ -8,12 +8,11 @@
#include <cassert>
#include <cmath>
#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <pistache/optional.h>
namespace Pistache
{
namespace Http
......@@ -197,10 +196,10 @@ namespace Pistache
std::string raw() const { return raw_; }
const Optional<Q>& q() const { return q_; }
const std::optional<Q>& q() const { return q_; }
void setQuality(Q quality);
Optional<std::string> getParam(const std::string& name) const;
std::optional<std::string> getParam(const std::string& name) const;
void setParam(const std::string& name, std::string value);
std::string toString() const;
......@@ -234,7 +233,7 @@ namespace Pistache
std::unordered_map<std::string, std::string> params;
Optional<Q> q_;
std::optional<Q> q_;
};
inline bool operator==(const MediaType& lhs, const MediaType& rhs)
......
This diff is collapsed.
......@@ -3323,13 +3323,13 @@ namespace date
static CONSTDATA classify value = std::is_convertible<Duration, std::chrono::hours>::value
? classify::hour
: std::is_convertible<Duration, std::chrono::minutes>::value
? classify::minute
: std::is_convertible<Duration, std::chrono::seconds>::value
? classify::second
: std::chrono::treat_as_floating_point<
typename Duration::rep>::value
? classify::not_valid
: classify::subsecond;
? classify::minute
: std::is_convertible<Duration, std::chrono::seconds>::value
? classify::second
: std::chrono::treat_as_floating_point<
typename Duration::rep>::value
? classify::not_valid
: classify::subsecond;
};
template <class Rep, class Period>
......
......@@ -8,7 +8,6 @@
#include <pistache/async.h>
#include <pistache/mailbox.h>
#include <pistache/optional.h>
#include <pistache/reactor.h>
#include <pistache/stream.h>
......@@ -16,6 +15,7 @@
#include <deque>
#include <memory>
#include <mutex>
#include <optional>
#include <unordered_map>
namespace Pistache
......
......@@ -9,6 +9,7 @@
#include <pistache/stream.h>
#include <iterator>
#include <optional>
#include <unordered_map>
namespace Pistache
......@@ -38,21 +39,21 @@ namespace Pistache
struct AttributeMatcher;
template <>
struct AttributeMatcher<Optional<std::string>>
struct AttributeMatcher<std::optional<std::string>>
{
static void match(StreamCursor& cursor, Cookie* obj,
Optional<std::string> Cookie::*attr)
std::optional<std::string> Cookie::*attr)
{
auto token = matchValue(cursor);
obj->*attr = Some(token.text());
obj->*attr = token.text();
}
};
template <>
struct AttributeMatcher<Optional<int>>
struct AttributeMatcher<std::optional<int>>
{
static void match(StreamCursor& cursor, Cookie* obj,
Optional<int> Cookie::*attr)
std::optional<int> Cookie::*attr)
{
auto token = matchValue(cursor);
......@@ -70,7 +71,7 @@ namespace Pistache
return ret;
};
obj->*attr = Some(strntol(token.rawText(), token.size()));
obj->*attr = strntol(token.rawText(), token.size());
}
};
......@@ -85,13 +86,13 @@ namespace Pistache
};
template <>
struct AttributeMatcher<Optional<FullDate>>
struct AttributeMatcher<std::optional<FullDate>>
{
static void match(StreamCursor& cursor, Cookie* obj,
Optional<FullDate> Cookie::*attr)
std::optional<FullDate> Cookie::*attr)
{
auto token = matchValue(cursor);
obj->*attr = Some(FullDate::fromString(token.text()));
obj->*attr = FullDate::fromString(token.text());
}
};
......@@ -202,23 +203,31 @@ namespace Pistache
void Cookie::write(std::ostream& os) const
{
os << name << "=" << value;
optionally_do(path, [&](const std::string& value) {
if (path.has_value())
{
const std::string& value = *path;
os << "; ";
os << "Path=" << value;
});
optionally_do(domain, [&](const std::string& value) {
}
if (domain.has_value())
{
const std::string& value = *domain;
os << "; ";
os << "Domain=" << value;
});
optionally_do(maxAge, [&](int value) {
}
if (maxAge.has_value())
{
int value = *maxAge;
os << "; ";
os << "Max-Age=" << value;
});
optionally_do(expires, [&](const FullDate& value) {
}
if (expires.has_value())
{
const FullDate& value = *expires;
os << "; ";
os << "Expires=";
value.write(os);
});
}
if (secure)
os << "; Secure";
if (httpOnly)
......
......@@ -158,8 +158,8 @@ namespace Pistache
return it->second;
}
Optional<Path> PathGroup::path(const std::string& name,
Http::Method method) const
std::optional<Path> PathGroup::path(const std::string& name,
Http::Method method) const
{
auto group = paths(name);
auto it = std::find_if(std::begin(group), std::end(group),
......@@ -167,9 +167,9 @@ namespace Pistache
if (it != std::end(group))
{
return Optional<Path>(Some(*it));
return std::optional<Path>(*it);
}
return Optional<Path>(None());
return std::nullopt;
}
PathGroup::group_iterator PathGroup::add(Path path)
......@@ -258,13 +258,13 @@ namespace Pistache
InfoBuilder& InfoBuilder::contact(std::string name, std::string url,
std::string email)
{
info_->contact = Some(Contact(std::move(name), std::move(url), std::move(email)));
info_->contact = Contact(std::move(name), std::move(url), std::move(email));
return *this;
}
InfoBuilder& InfoBuilder::license(std::string name, std::string url)
{
info_->license = Some(License(std::move(name), std::move(url)));
info_->license = License(std::move(name), std::move(url));
return *this;
}
......
......@@ -586,13 +586,13 @@ namespace Pistache
params.insert(std::make_pair(std::move(name), std::move(value)));
}
Optional<std::string> Query::get(const std::string& name) const
std::optional<std::string> Query::get(const std::string& name) const
{
auto it = params.find(name);
if (it == std::end(params))
return Optional<std::string>(None());
return std::nullopt;
return Optional<std::string>(Some(it->second));
return std::optional<std::string>(it->second);
}
std::string Query::as_str() const
......
......@@ -170,15 +170,15 @@ namespace Pistache
return header.second;
}
Optional<Raw> Collection::tryGetRaw(const std::string& name) const
std::optional<Raw> Collection::tryGetRaw(const std::string& name) const
{
auto it = rawHeaders.find(name);
if (it == std::end(rawHeaders))
{
return Optional<Raw>(None());
return std::nullopt;
}
return Optional<Raw>(Some(it->second));
return std::optional<Raw>(it->second);
}
bool Collection::has(const std::string& name) const
......
......@@ -240,7 +240,7 @@ namespace Pistache
double val;
if (!match_double(&val, cursor))
raise("Invalid quality factor");
q_ = Some(Q::fromFloat(val));
q_ = Q::fromFloat(val);
}
else
{
......@@ -266,17 +266,17 @@ namespace Pistache
}
}
void MediaType::setQuality(Q quality) { q_ = Some(quality); }
void MediaType::setQuality(Q quality) { q_ = quality; }
Optional<std::string> MediaType::getParam(const std::string& name) const
std::optional<std::string> MediaType::getParam(const std::string& name) const
{
auto it = params.find(name);
if (it == std::end(params))
{
return Optional<std::string>(None());
return std::nullopt;
}
return Optional<std::string>(Some(it->second));
return std::optional<std::string>(it->second);
}
void MediaType::setParam(const std::string& name, std::string value)
......@@ -339,10 +339,12 @@ namespace Pistache
res += suffixString(suffix_);
}
optionally_do(q_, [&res](Q quality) {
if (q_.has_value())
{
Q quality = *q_;
res += "; ";
res += quality.toString();
});
}
for (const auto& param : params)
{
......
......@@ -36,7 +36,6 @@ pistache_test(mailbox_test)
pistache_test(stream_test)
pistache_test(reactor_test)
pistache_test(threadname_test)
pistache_test(optional_test)
pistache_test(log_api_test)
pistache_test(string_logger_test)
......
......@@ -28,29 +28,29 @@ TEST(cookie_test, attributes_test)
parse("SID=31d4d96e407aad42; Path=/", [](const Cookie& c) {
ASSERT_EQ(c.name, "SID");
ASSERT_EQ(c.value, "31d4d96e407aad42");
ASSERT_EQ(c.path.getOrElse(""), "/");
ASSERT_EQ(c.path.value_or(""), "/");
});
parse("SID=31d4d96e407aad42; Path=/; Domain=example.com",
[](const Cookie& c) {
ASSERT_EQ(c.path.getOrElse(""), "/");
ASSERT_EQ(c.domain.getOrElse(""), "example.com");
ASSERT_EQ(c.path.value_or(""), "/");
ASSERT_EQ(c.domain.value_or(""), "example.com");
});
parse("lang=en-US; Path=/; Domain=example.com; Max-Age=10",
[](const Cookie& c) {
ASSERT_EQ(c.name, "lang");
ASSERT_EQ(c.value, "en-US");
ASSERT_EQ(c.path.getOrElse(""), "/");
ASSERT_EQ(c.domain.getOrElse(""), "example.com");
ASSERT_EQ(c.maxAge.getOrElse(0), 10);
ASSERT_EQ(c.path.value_or(""), "/");
ASSERT_EQ(c.domain.value_or(""), "example.com");
ASSERT_EQ(c.maxAge.value_or(0), 10);
});
parse("lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT",
[](const Cookie& c) {
ASSERT_EQ(c.name, "lang");
ASSERT_EQ(c.value, "en-US");
auto expires = c.expires.getOrElse(FullDate());
auto expires = c.expires.value_or(FullDate());
auto date = expires.date();
using namespace std::chrono;
......@@ -61,7 +61,7 @@ TEST(cookie_test, attributes_test)
parse("lang=en-US; Path=/; Domain=example.com;", [](const Cookie& c) {
ASSERT_EQ(c.name, "lang");
ASSERT_EQ(c.value, "en-US");
ASSERT_EQ(c.domain.getOrElse(""), "example.com");
ASSERT_EQ(c.domain.value_or(""), "example.com");
});
}
......@@ -70,7 +70,7 @@ TEST(cookie_test, bool_test)
parse("SID=31d4d96e407aad42; Path=/; Secure", [](const Cookie& c) {
ASSERT_EQ(c.name, "SID");
ASSERT_EQ(c.value, "31d4d96e407aad42");
ASSERT_EQ(c.path.getOrElse(""), "/");
ASSERT_EQ(c.path.value_or(""), "/");
ASSERT_TRUE(c.secure);
ASSERT_FALSE(c.httpOnly);
});
......@@ -78,7 +78,7 @@ TEST(cookie_test, bool_test)
parse("SID=31d4d96e407aad42; Path=/; Secure; HttpOnly", [](const Cookie& c) {
ASSERT_EQ(c.name, "SID");
ASSERT_EQ(c.value, "31d4d96e407aad42");
ASSERT_EQ(c.path.getOrElse(""), "/");
ASSERT_EQ(c.path.value_or(""), "/");
ASSERT_TRUE(c.secure);
ASSERT_TRUE(c.httpOnly);
});
......@@ -89,7 +89,7 @@ TEST(cookie_test, ext_test)
parse("lang=en-US; Path=/; Scope=Private", [](const Cookie& c) {
ASSERT_EQ(c.name, "lang");
ASSERT_EQ(c.value, "en-US");
ASSERT_EQ(c.path.getOrElse(""), "/");
ASSERT_EQ(c.path.value_or(""), "/");
auto fooIt = c.ext.find("Scope");
ASSERT_TRUE(fooIt != std::end(c.ext));
ASSERT_EQ(fooIt->second, "Private");
......@@ -99,8 +99,8 @@ TEST(cookie_test, ext_test)
TEST(cookie_test, write_test)
{
Cookie c1("lang", "fr-FR");
c1.path = Some(std::string("/"));
c1.domain = Some(std::string("example.com"));
c1.path = std::string("/");
c1.domain = std::string("example.com");
std::ostringstream oss;
oss << c1;
......@@ -112,8 +112,8 @@ TEST(cookie_test, write_test)
FullDate::time_point expires = date::sys_days(date::year { 118 } / 2 / 16) + hours(17);
c2.path = Some(std::string("/"));
c2.expires = Some(FullDate(expires));
c2.path = std::string("/");
c2.expires = FullDate(expires);
oss.str("");
oss << c2;
......
......@@ -18,7 +18,7 @@ TEST(headers_test, accept)
const auto& mime = media[0];
ASSERT_TRUE(mime == MIME(Audio, Star));
ASSERT_TRUE(mime.q().getOrElse(Pistache::Http::Mime::Q(0)) == Pistache::Http::Mime::Q(20));
ASSERT_TRUE(mime.q().value_or(Pistache::Http::Mime::Q(0)) == Pistache::Http::Mime::Q(20));
}
Pistache::Http::Header::Accept a2;
......@@ -35,7 +35,7 @@ TEST(headers_test, accept)
const auto& m3 = media[2];
ASSERT_TRUE(m3 == MIME(Text, Html));
auto level = m3.getParam("level");
ASSERT_TRUE(level.getOrElse("") == "1");
ASSERT_TRUE(level.value_or("") == "1");
const auto& m4 = media[3];
ASSERT_TRUE(m4 == MIME(Star, Star));
}
......@@ -49,13 +49,13 @@ TEST(headers_test, accept)
ASSERT_TRUE(media.size() == 5U);
ASSERT_TRUE(media[0] == MIME(Text, Star));
ASSERT_TRUE(media[0].q().getOrElse(Pistache::Http::Mime::Q(0)) == Pistache::Http::Mime::Q(30));
ASSERT_TRUE(media[0].q().value_or(Pistache::Http::Mime::Q(0)) == Pistache::Http::Mime::Q(30));
ASSERT_TRUE(media[1] == MIME(Text, Html));
ASSERT_TRUE(media[2] == MIME(Text, Html));
ASSERT_TRUE(media[3] == MIME(Text, Html));
ASSERT_TRUE(media[4] == MIME(Star, Star));
ASSERT_TRUE(media[4].q().getOrElse(Pistache::Http::Mime::Q(0)) == Pistache::Http::Mime::Q::fromFloat(0.5));
ASSERT_TRUE(media[4].q().value_or(Pistache::Http::Mime::Q(0)) == Pistache::Http::Mime::Q::fromFloat(0.5));
}
Pistache::Http::Header::Accept a4;
......@@ -574,7 +574,7 @@ TEST(headers_test, content_type)
ASSERT_TRUE("text/html; charset=ISO-8859-4" == oss.str());
const auto& mime = ct.mime();
ASSERT_TRUE(mime == MIME(Text, Html));
ASSERT_TRUE(mime.getParam("charset").getOrElse("") == "ISO-8859-4");
ASSERT_TRUE(mime.getParam("charset").value_or("") == "ISO-8859-4");
}
TEST(headers_test, access_control_allow_origin_test)
......@@ -821,10 +821,10 @@ TEST(headers_test, raw_headers_are_case_insensitive)
step.apply(cursor);
// or the header you try and get, it should work:
ASSERT_FALSE(request.headers().tryGetRaw("Custom-Header").isEmpty());
ASSERT_FALSE(request.headers().tryGetRaw("CUSTOM-HEADER").isEmpty());
ASSERT_FALSE(request.headers().tryGetRaw("custom-header").isEmpty());
ASSERT_FALSE(request.headers().tryGetRaw("CuStOm-HeAdEr").isEmpty());
ASSERT_FALSE(request.headers().tryGetRaw("Custom-Header").has_value());
ASSERT_FALSE(request.headers().tryGetRaw("CUSTOM-HEADER").has_value());
ASSERT_FALSE(request.headers().tryGetRaw("custom-header").has_value());
ASSERT_FALSE(request.headers().tryGetRaw("CuStOm-HeAdEr").has_value());
}
}
......
......@@ -489,7 +489,7 @@ TEST(http_client_test, client_sends_query)
for (auto entry : results)
{
ASSERT_TRUE(query.has(entry.first));
EXPECT_EQ(entry.second, query.get(entry.first).get());
EXPECT_EQ(entry.second, query.get(entry.first).value());
}
}
......
......@@ -21,9 +21,9 @@ TEST(mime_test, basic_test)
ASSERT_TRUE(m2.toString() == "application/xhtml+xml");
auto m3 = MIME(Text, Plain);
ASSERT_TRUE(m3.q().isEmpty());
ASSERT_TRUE(m3.q().has_value());
m3.setQuality(Q::fromFloat(0.7));
ASSERT_TRUE(m3.q().getOrElse(Q(0)) == Q(70));
ASSERT_TRUE(m3.q().value_or(Q(0)) == Q(70));
ASSERT_TRUE(m3.toString() == "text/plain; q=0.7");
......@@ -54,28 +54,28 @@ TEST(mime_test, valid_parsing_test)
{
parse("application/json", [](const MediaType& m1) {
ASSERT_TRUE(m1 == MIME(Application, Json));
ASSERT_TRUE(m1.q().isEmpty());
ASSERT_TRUE(m1.q().has_value());
});
parse("application/xhtml+xml", [](const MediaType& m2) {
ASSERT_TRUE(m2 == MediaType(Type::Application, Subtype::Xhtml, Suffix::Xml));
ASSERT_TRUE(m2.q().isEmpty());
ASSERT_TRUE(m2.q().has_value());
});
parse("application/json; q=0.3", [](const MediaType& m3) {
ASSERT_TRUE(m3 == MIME(Application, Json));
ASSERT_TRUE(m3.q().getOrElse(Q(0)) == Q::fromFloat(0.3));
ASSERT_TRUE(m3.q().value_or(Q(0)) == Q::fromFloat(0.3));
});
parse("application/xhtml+xml; q=0.7", [](const MediaType& m4) {
ASSERT_TRUE(m4.top() == Type::Application);
ASSERT_TRUE(m4.sub() == Subtype::Xhtml);
ASSERT_TRUE(m4.suffix() == Suffix::Xml);
ASSERT_TRUE(m4.q().getOrElse(Q(0)) == Q(70));
ASSERT_TRUE(m4.q().value_or(Q(0)) == Q(70));
});
parse("application/xhtml+xml; q=0.78", [](const MediaType& m5) {
ASSERT_TRUE(m5.q().getOrElse(Q(0)) == Q(78));
ASSERT_TRUE(m5.q().value_or(Q(0)) == Q(78));
});
parse("application/vnd.adobe.flash-movie", [](const MediaType& m6) {
......@@ -108,15 +108,15 @@ TEST(mime_test, valid_parsing_test)
parse("text/html; charset=ISO-8859-4", [](const MediaType& m10) {
ASSERT_TRUE(m10 == MIME(Text, Html));
ASSERT_TRUE(m10.q().isEmpty());
ASSERT_TRUE(m10.q().has_value());
auto charset = m10.getParam("charset");
ASSERT_TRUE(charset.getOrElse("") == "ISO-8859-4");
ASSERT_TRUE(charset.value_or("") == "ISO-8859-4");
});
parse("text/html; q=0.83; charset=ISO-8859-4", [](const MediaType& m11) {
ASSERT_TRUE(m11 == MIME(Text, Html));
ASSERT_TRUE(m11.q().getOrElse(Q(0)) == Q(83));
ASSERT_TRUE(m11.getParam("charset").getOrElse("") == "ISO-8859-4");
ASSERT_TRUE(m11.q().value_or(Q(0)) == Q(83));
ASSERT_TRUE(m11.getParam("charset").value_or("") == "ISO-8859-4");
});
}
......@@ -150,15 +150,15 @@ TEST(mime_test, should_parse_case_insensitive_issue_179)
{
parse("Application/Json", [](const Mime::MediaType& mime) {
ASSERT_TRUE(mime == MIME(Application, Json));
ASSERT_TRUE(mime.q().isEmpty());
ASSERT_TRUE(mime.q().has_value());
});
parse("aPpliCAtion/Xhtml+XML", [](const MediaType& mime) {
ASSERT_TRUE(mime == MediaType(Type::Application, Subtype::Xhtml, Suffix::Xml));
ASSERT_TRUE(mime.q().isEmpty());
ASSERT_TRUE(mime.q().has_value());
});
parse("Application/Xhtml+XML; q=0.78", [](const MediaType& mime) {
ASSERT_TRUE(mime.q().getOrElse(Q(0)) == Q(78));
ASSERT_TRUE(mime.q().value_or(Q(0)) == Q(78));
});
}
#include "gtest/gtest.h"
#include <pistache/optional.h>
using Pistache::Optional;
TEST(optional, constructor)
{
Optional<bool> value(Pistache::Some(true));
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
}
TEST(optional, copy_constructor)
{
Optional<bool> value(Pistache::Some(true));
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
Optional<bool> copy_constructed(value);
ASSERT_FALSE(copy_constructed.isEmpty());
EXPECT_TRUE(copy_constructed.get());
}
TEST(optional, copy_assignment_operator)
{
Optional<bool> value(Pistache::Some(true));
ASSERT_FALSE(value.isEmpty());
Optional<bool> other;
EXPECT_TRUE(other.isEmpty());
other = value;
ASSERT_FALSE(other.isEmpty());
EXPECT_TRUE(other.get());
}
TEST(optional, copy_assignment_operator_for_convertible_type)
{
Optional<bool> value;
EXPECT_TRUE(value.isEmpty());
value = Pistache::Some(true);
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
}
TEST(optional, copy_assignment_operator_for_self_assignment)
{
Optional<bool> value(Pistache::Some(true));
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
value = value;
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
}
TEST(optional, move_constructor)
{
Optional<bool> value(Pistache::Some(true));
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
Optional<bool> value_from_move(std::move(value));
ASSERT_FALSE(value_from_move.isEmpty());
EXPECT_TRUE(value_from_move.get());
}
TEST(optional, move_assignment_operator)
{
Optional<bool> value(Pistache::Some(true));
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
Optional<bool> move_assigned;
move_assigned = std::move(value);
ASSERT_FALSE(move_assigned.isEmpty());
EXPECT_TRUE(move_assigned.get());
}
TEST(optional, integer)
{
Optional<int32_t> value(Pistache::Some(1));
ASSERT_FALSE(value.isEmpty());
EXPECT_TRUE(value.get());
}
TEST(optional, constructor_none)
{
Optional<bool> value(Pistache::None());
EXPECT_TRUE(value.isEmpty());
}
TEST(optional, copy_constructor_none)
{
Optional<bool> value(Pistache::None());
EXPECT_TRUE(value.isEmpty());
Optional<bool> copy_constructed(value);
EXPECT_TRUE(value.isEmpty());
}
TEST(optional, copy_assignment_operator_none)
{
Optional<bool> value(Pistache::None());
EXPECT_TRUE(value.isEmpty());
Optional<bool> assigned = Pistache::None();
EXPECT_TRUE(assigned.isEmpty());
}
TEST(optional, move_constructor_none)
{
Optional<bool> value(Pistache::None());
EXPECT_TRUE(value.isEmpty());
Optional<bool> move_constructed(std::move(value));
EXPECT_TRUE(move_constructed.isEmpty());
}
TEST(optional, move_assignment_operator_none)
{
Optional<bool> value(Pistache::None());
EXPECT_TRUE(value.isEmpty());
Optional<bool> move_assigned(std::move(value));
EXPECT_TRUE(move_assigned.isEmpty());
}
TEST(optional, integer_none)
{
Optional<int32_t> value(Pistache::None());
EXPECT_TRUE(value.isEmpty());
}
TEST(optional, equal_operator_empty_equalto_empty)
{
Optional<int32_t> value(Pistache::None());
Optional<int32_t> value2(Pistache::None());
EXPECT_EQ(value, value2);
}
TEST(optional, equal_operator_value_equalto_value)
{
Optional<int32_t> value(Pistache::Some(1));
Optional<int32_t> value2(Pistache::Some(1));
EXPECT_EQ(value, value2);
}
TEST(optional, equal_operator_empty_notequalto_value)
{
Optional<int32_t> value(Pistache::None());
Optional<int32_t> value2(Pistache::Some(2));
EXPECT_NE(value, value2);
}
TEST(optional, equal_operator_value_notequalto_value)
{
Optional<int32_t> value(Pistache::Some(1));
Optional<int32_t> value2(Pistache::Some(2));
EXPECT_NE(value, value2);
}
struct not_comparable
{
bool operator==(const not_comparable& other) const = delete;
};
TEST(has_equalto_operator, is_comparable_type)
{
using Pistache::types::has_equalto_operator;
EXPECT_FALSE(has_equalto_operator<not_comparable>::value);
EXPECT_TRUE(has_equalto_operator<int>::value);
EXPECT_TRUE(has_equalto_operator<double>::value);
EXPECT_TRUE(has_equalto_operator<std::string>::value);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment