diff --git a/src/Makefile.am b/src/Makefile.am index 627a944e..99408894 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -174,7 +174,8 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \ nghttp2_gzip_test.c nghttp2_gzip_test.h \ nghttp2_gzip.c nghttp2_gzip.h \ buffer_test.cc buffer_test.h \ - memchunk_test.cc memchunk_test.h + memchunk_test.cc memchunk_test.h \ + template_test.cc template_test.h nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \ -DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\" nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @CUNIT_LIBS@ @TESTLDADD@ diff --git a/src/shrpx-unittest.cc b/src/shrpx-unittest.cc index 37a8e0ec..3e6d4a12 100644 --- a/src/shrpx-unittest.cc +++ b/src/shrpx-unittest.cc @@ -38,6 +38,7 @@ #include "nghttp2_gzip_test.h" #include "buffer_test.h" #include "memchunk_test.h" +#include "template_test.h" #include "shrpx_config.h" #include "ssl.h" @@ -178,7 +179,11 @@ int main(int argc, char *argv[]) { !CU_add_test(pSuite, "peek_memchunk_disable_peek_no_drain", nghttp2::test_peek_memchunks_disable_peek_no_drain) || !CU_add_test(pSuite, "peek_memchunk_reset", - nghttp2::test_peek_memchunks_reset)) { + nghttp2::test_peek_memchunks_reset) || + !CU_add_test(pSuite, "template_immutable_string", + nghttp2::test_template_immutable_string) || + !CU_add_test(pSuite, "template_string_ref", + nghttp2::test_template_string_ref)) { CU_cleanup_registry(); return CU_get_error(); } diff --git a/src/template.h b/src/template.h index 259a19e1..82286367 100644 --- a/src/template.h +++ b/src/template.h @@ -215,7 +215,10 @@ inline std::unique_ptr strcopy(const std::unique_ptr &val, // std::string. It has c_str() and size() functions to mimic // std::string. It manages buffer by itself. Just like std::string, // c_str() returns NULL-terminated string, but NULL character may -// appear before the final terminal NULL. +// appear before the final terminal NULL. The crucial difference +// between this and std::string is that when ImmutableString is +// default constructed, c_str() returns nullptr, whereas std::string +// will return non nullptr. Both size() returns 0. class ImmutableString { public: using traits_type = std::char_traits; @@ -232,13 +235,22 @@ public: ImmutableString(const char *s, size_t slen) : len(slen), base(strcopy(s, len)) {} ImmutableString(const char *s) : len(strlen(s)), base(strcopy(s, len)) {} + ImmutableString(std::unique_ptr s) + : len(strlen(s.get())), base(std::move(s)) {} + ImmutableString(std::unique_ptr s, size_t slen) + : len(slen), base(std::move(s)) {} ImmutableString(const std::string &s) : len(s.size()), base(strcopy(s)) {} template ImmutableString(InputIt first, InputIt last) : len(std::distance(first, last)), base(strcopy(first, last)) {} ImmutableString(const ImmutableString &other) : len(other.len), base(strcopy(other.base, other.len)) {} - ImmutableString(ImmutableString &&) = default; + ImmutableString(ImmutableString &&other) noexcept + : len(other.len), + base(std::move(other.base)) { + other.len = 0; + } + ImmutableString &operator=(const ImmutableString &other) { if (this == &other) { return *this; @@ -247,7 +259,15 @@ public: base = strcopy(other.base, other.len); return *this; } - ImmutableString &operator=(ImmutableString &&other) = default; + ImmutableString &operator=(ImmutableString &&other) noexcept { + if (this == &other) { + return *this; + } + len = other.len; + base = std::move(other.base); + other.len = 0; + return *this; + } template static ImmutableString from_lit(const char(&s)[N]) { return ImmutableString(s, N - 1); @@ -313,6 +333,15 @@ inline bool operator==(const std::string &lhs, const StringRef &rhs) { return rhs == lhs; } +inline bool operator==(const StringRef &lhs, const char *rhs) { + return lhs.size() == strlen(rhs) && + std::equal(std::begin(lhs), std::end(lhs), rhs); +} + +inline bool operator==(const char *lhs, const StringRef &rhs) { + return rhs == lhs; +} + inline int run_app(std::function app, int argc, char **argv) { try { diff --git a/src/template_test.cc b/src/template_test.cc new file mode 100644 index 00000000..df99c556 --- /dev/null +++ b/src/template_test.cc @@ -0,0 +1,136 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2016 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "template_test.h" + +#include +#include + +#include + +#include "template.h" + +namespace nghttp2 { + +void test_template_immutable_string(void) { + ImmutableString null; + + CU_ASSERT(nullptr == null.c_str()); + CU_ASSERT(0 == null.size()); + + ImmutableString from_cstr("alpha"); + + CU_ASSERT(0 == strcmp("alpha", from_cstr.c_str())); + CU_ASSERT(5 == from_cstr.size()); + CU_ASSERT("alpha" == from_cstr); + CU_ASSERT(from_cstr == "alpha"); + CU_ASSERT(std::string("alpha") == from_cstr); + CU_ASSERT(from_cstr == std::string("alpha")); + + ImmutableString from_uniq(strcopy("charlie")); + + CU_ASSERT("charlie" == from_uniq); + CU_ASSERT(7 == from_uniq.size()); + + // copy constructor + ImmutableString copy = from_uniq; + + CU_ASSERT("charlie" == copy); + CU_ASSERT(7 == copy.size()); + + // copy assignment + ImmutableString copy2; + copy2 = from_uniq; + + CU_ASSERT("charlie" == copy2); + CU_ASSERT(7 == copy2.size()); + + // move constructor + ImmutableString move = std::move(copy); + + CU_ASSERT("charlie" == move); + CU_ASSERT(7 == move.size()); + CU_ASSERT(nullptr == copy.c_str()); + CU_ASSERT(0 == copy.size()); + + // move assignment + move = std::move(from_cstr); + + CU_ASSERT("alpha" == move); + CU_ASSERT(5 == move.size()); + CU_ASSERT(nullptr == from_cstr.c_str()); + CU_ASSERT(0 == from_cstr.size()); + + // from string literal + auto from_lit = StringRef::from_lit("bravo"); + + CU_ASSERT("bravo" == from_lit); + CU_ASSERT(5 == from_lit.size()); +} + +void test_template_string_ref(void) { + StringRef empty; + + CU_ASSERT("" == empty); + CU_ASSERT(0 == empty.size()); + + // from std::string + std::string alpha = "alpha"; + + StringRef ref(alpha); + + CU_ASSERT("alpha" == ref); + CU_ASSERT(ref == "alpha"); + CU_ASSERT(alpha == ref); + CU_ASSERT(ref == alpha); + CU_ASSERT(5 == ref.size()); + + // from string literal + auto from_lit = StringRef::from_lit("alpha"); + + CU_ASSERT("alpha" == from_lit); + CU_ASSERT(5 == from_lit.size()); + + // from ImmutableString + ImmutableString im = "bravo"; + + StringRef imref(im); + + CU_ASSERT("bravo" == imref); + CU_ASSERT(5 == imref.size()); + + // from C-string + StringRef cstrref("charlie"); + + CU_ASSERT("charlie" == cstrref); + CU_ASSERT(7 == cstrref.size()); + + // from C-string and its length + StringRef cstrnref("delta", 5); + + CU_ASSERT("delta" == cstrnref); + CU_ASSERT(5 == cstrnref.size()); +} + +} // namespace nghttp2 diff --git a/src/template_test.h b/src/template_test.h new file mode 100644 index 00000000..1a5a85be --- /dev/null +++ b/src/template_test.h @@ -0,0 +1,39 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2016 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef TEMPLATE_TEST_H +#define TEMPLATE_TEST_H + +#ifdef HAVE_CONFIG_H +#include +#endif // HAVE_CONFIG_H + +namespace nghttp2 { + +void test_template_immutable_string(void); +void test_template_string_ref(void); + +} // namespace nghttp2 + +#endif // TEMPLATE_TEST_H