From eaa77767a73540b3386628bb316157c74dcc5c5c Mon Sep 17 00:00:00 2001 From: heck Date: Mon, 14 Feb 2022 15:25:55 +0100 Subject: [PATCH] add .clang-format / reformat If you dont like reformatting of complete codebases, the solution is to USE this. --- .clang-format | 45 ++++ src/bloblist.cc | 23 +- src/bloblist.hh | 114 ++++++---- src/crlf.cc | 36 ++-- src/crlf.hh | 3 +- src/identity.cc | 48 ++--- src/stringlist.cc | 42 ++-- src/types.cc | 87 ++++---- src/types.hh | 14 +- src/wrapper.hh | 404 ++++++++++++++++++++---------------- test/unittest_identity.cc | 32 +-- test/unittest_message.cc | 239 +++++++++++---------- test/unittest_nfc.cc | 134 ++++++------ test/unittest_nfc16.cc | 106 +++++----- test/unittest_nfcstring.cc | 101 +++++---- test/unittest_stringlist.cc | 64 +++--- test/unittest_stringpair.cc | 60 +++--- 17 files changed, 825 insertions(+), 727 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..d1d8de9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,45 @@ +BasedOnStyle: LLVM +Language: Cpp +Standard: c++17 +DerivePointerAlignment: true +SortIncludes: Never +ReflowComments: false +PointerAlignment: Left +AlignAfterOpenBracket: AlwaysBreak +AlignOperands: AlignAfterOperator +BreakConstructorInitializers: AfterColon +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +ExperimentalAutoDetectBinPacking: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true +ColumnLimit: 100 +AllowAllConstructorInitializersOnNextLine: false +#BreakConstructorInitializersBeforeComma: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +PenaltyBreakBeforeFirstCallParameter: 0 +PenaltyReturnTypeOnItsOwnLine: 1000000 +PenaltyBreakAssignment: 1000000 +PenaltyExcessCharacter: 10 +IndentCaseLabels: true +IndentWidth: 4 +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +SpaceAfterTemplateKeyword: false +AccessModifierOffset: -4 +AllowShortBlocksOnASingleLine: Always +IndentPPDirectives: BeforeHash +IndentExternBlock: Indent +Cpp11BracedListStyle: false +BreakStringLiterals: false \ No newline at end of file diff --git a/src/bloblist.cc b/src/bloblist.cc index 6cc9ccb..57868f4 100644 --- a/src/bloblist.cc +++ b/src/bloblist.cc @@ -2,44 +2,43 @@ #include -namespace pEp -{ +namespace pEp { template<> void Wrapper<::bloblist_t*>::_free(::bloblist_t* bl) { ::free_bloblist(bl); } - -// template<> + + // template<> int BlobList::size() const { return bloblist_length(value); } // faster than .size()==0 because it's not necessary to iterate throgh the whole list -// template<> + // template<> bool BlobList::empty() const { return !(value && value->value); } - -// template<> + + // template<> void BlobList::clear() { free_bloblist(value); value = nullptr; } - -// template<> + + // template<> void BlobList::push_back(Blob&& s) { // TODO } -//////////////// + //////////////// -// no explicit instantiation noecessary, because of fully specialized class template. Okay. :-D -// template class ListWrapper<::bloblist_t*, void>; + // no explicit instantiation noecessary, because of fully specialized class template. Okay. :-D + // template class ListWrapper<::bloblist_t*, void>; } // end of namespace pEp diff --git a/src/bloblist.hh b/src/bloblist.hh index 857ec9e..caade8c 100644 --- a/src/bloblist.hh +++ b/src/bloblist.hh @@ -7,55 +7,79 @@ #include "wrapper.hh" #include -namespace pEp -{ +namespace pEp { -template<> -class ListWrapper<::bloblist_t*, void> : public Wrapper<::bloblist_t*> -{ -public: - typedef ::bloblist_t Blob; - typedef Wrapper Base; - typedef ListWrapper LW; - - // does not own the *value - class iterator - { + template<> + class ListWrapper<::bloblist_t*, void> : public Wrapper<::bloblist_t*> { public: - iterator() = default; - - iterator operator++() { return (value ? value = value->next : value); } - Blob& operator*() { return *value; } - Blob* operator->() { return value; } - const Blob& operator*() const { return *value; } - const Blob* operator->() const { return value; } - bool operator==(const iterator& other) const { return value == other.value; } - bool operator!=(const iterator& other) const { return value != other.value; } - - private: - iterator(::bloblist_t* _t) : value{_t} {} - ::bloblist_t* value = nullptr; - friend class ListWrapper<::bloblist_t*, void>; + typedef ::bloblist_t Blob; + typedef Wrapper Base; + typedef ListWrapper LW; + + // does not own the *value + class iterator { + public: + iterator() = default; + + iterator operator++() + { + return (value ? value = value->next : value); + } + Blob& operator*() + { + return *value; + } + Blob* operator->() + { + return value; + } + const Blob& operator*() const + { + return *value; + } + const Blob* operator->() const + { + return value; + } + bool operator==(const iterator& other) const + { + return value == other.value; + } + bool operator!=(const iterator& other) const + { + return value != other.value; + } + + private: + iterator(::bloblist_t* _t) : value{ _t } {} + ::bloblist_t* value = nullptr; + friend class ListWrapper<::bloblist_t*, void>; + }; + + + using Base::value; + + ListWrapper() : Base() {} + + + iterator begin() + { + return iterator{ value }; + } + iterator end() const + { + return iterator{}; + } + int size() const; + bool empty() const; + + void clear(); + void push_back(Blob&&); + void emplace_back(char* data, size_t size, const char* mime_type, const char* filename); }; - - - using Base::value; - - ListWrapper() : Base() {} - - - iterator begin() { return iterator{value}; } - iterator end() const { return iterator{}; } - int size() const; - bool empty() const; - - void clear(); - void push_back(Blob&&); - void emplace_back(char* data, size_t size, const char* mime_type, const char* filename); -}; - - using BlobList = ListWrapper<::bloblist_t*, void>; + + using BlobList = ListWrapper<::bloblist_t*, void>; } // end of namespace pEp diff --git a/src/crlf.cc b/src/crlf.cc index 1d9a3a9..4515edd 100644 --- a/src/crlf.cc +++ b/src/crlf.cc @@ -1,26 +1,24 @@ #include "crlf.hh" -namespace pEp -{ +namespace pEp { -std::string operator""_CRLF(const char* str, size_t length) -{ - static const std::string CRLF{"\r\n"}; - - std::string ret; - ret.reserve(length + ((length+29)/30) + 2 ); // rough guess for average line length of 30. - const char* end = str + length; - - // N.B.: Loop could be more optimized, but not necessary because it is only used for string literals. - for(; str != end; ++str) + std::string operator""_CRLF(const char* str, size_t length) { - if(*str == '\n') - ret += CRLF; - else - ret += *str; + static const std::string CRLF{ "\r\n" }; + + std::string ret; + ret.reserve(length + ((length + 29) / 30) + 2); // rough guess for average line length of 30. + const char* end = str + length; + + // N.B.: Loop could be more optimized, but not necessary because it is only used for string literals. + for (; str != end; ++str) { + if (*str == '\n') + ret += CRLF; + else + ret += *str; + } + + return ret; } - - return ret; -} } // end of namespace pEp diff --git a/src/crlf.hh b/src/crlf.hh index bd4771a..40940fd 100644 --- a/src/crlf.hh +++ b/src/crlf.hh @@ -6,8 +6,7 @@ #include -namespace pEp -{ +namespace pEp { // creates a string where \n ("linefeed" a.k.a. LF) are replaced // by \r\n ("carriage return + linefeed" a.k.a. CRLF). // Useful to define strings in NET-ASCII or Net-Unicode (RFC5198) format diff --git a/src/identity.cc b/src/identity.cc index 7cf9990..ae61984 100644 --- a/src/identity.cc +++ b/src/identity.cc @@ -4,15 +4,14 @@ #include -namespace pEp -{ +namespace pEp { template<> template<> - ::pEp_identity* Wrapper<::pEp_identity*>::_new - ( - const char *address, const char *fpr, const char *user_id, - const char *username - ) + ::pEp_identity* Wrapper<::pEp_identity*>::_new( + const char* address, + const char* fpr, + const char* user_id, + const char* username) { return ::new_identity(address, fpr, user_id, username); } @@ -22,14 +21,14 @@ namespace pEp { ::free_identity(id); } - + template<> ::pEp_identity* Wrapper<::pEp_identity*>::copy_out() const { return identity_dup(value); } -////////////// + ////////////// template<> void Wrapper<::identity_list*>::_free(::identity_list* sl) @@ -44,8 +43,8 @@ namespace pEp } template<> - ::pEp_identity* identity_list::* const ListWrapper<::identity_list*, ::pEp_identity*>::Value - = &identity_list::ident; + ::pEp_identity* identity_list::*const + ListWrapper<::identity_list*, ::pEp_identity*>::Value = &identity_list::ident; template<> int IdentityList::size() const @@ -59,41 +58,40 @@ namespace pEp { return !(value && value->ident); } - + template<> void IdentityList::clear() { free_identity_list(value); value = nullptr; } - + template<> void IdentityList::push_back(pEp_identity*&& id) { auto last = identity_list_add(value, id); - if(value==nullptr) + if (value == nullptr) value = last; } - - + + template<> - ListWrapper<::identity_list*, pEp_identity*>::ListWrapper(const std::initializer_list>& il) - : Base{} + ListWrapper<::identity_list*, pEp_identity*>::ListWrapper( + const std::initializer_list>& il) : + Base{} { - ::identity_list* last = nullptr; - for(const Wrapper& id : il) - { + ::identity_list* last = nullptr; + for (const Wrapper& id : il) { last = identity_list_add(last, identity_dup(id.get())); - if(last==nullptr) - { + if (last == nullptr) { throw std::runtime_error("Cannot create StringPairList from {}: Out Of Memory."); } - if(value==nullptr) + if (value == nullptr) value = last; // save the head of linked list. } } -//////////////// + //////////////// template class ListWrapper<::identity_list*, ::pEp_identity*>; diff --git a/src/stringlist.cc b/src/stringlist.cc index 645c5c8..438c599 100644 --- a/src/stringlist.cc +++ b/src/stringlist.cc @@ -5,17 +5,16 @@ #include -namespace pEp -{ +namespace pEp { template<> void Wrapper<::stringlist_t*>::_free(::stringlist_t* sl) { ::free_stringlist(sl); } - + template<> - const char* stringlist_t::* const ListWrapper::Value - = const_cast(&stringlist_t::value); + const char* stringlist_t::*const ListWrapper::Value = + const_cast(&stringlist_t::value); template<> int StringList::size() const @@ -29,50 +28,47 @@ namespace pEp { return !(value && value->value); } - + template<> - void StringList::erase( const StringList::iterator& it) + void StringList::erase(const StringList::iterator& it) { - if(it.value && it.value->value) - { + if (it.value && it.value->value) { value = stringlist_delete(value, it.value->value); } } - + template<> void StringList::clear() { free_stringlist(value); value = nullptr; } - + template<> void StringList::push_back(const char*&& s) { auto last = stringlist_add(value, s); - if(value==nullptr) + if (value == nullptr) value = last; } - - + + template<> - ListWrapper<::stringlist_t*, const char*>::ListWrapper(const std::initializer_list& il) - : StringList{} + ListWrapper<::stringlist_t*, const char*>::ListWrapper(const std::initializer_list& il) : + StringList{} { - ::stringlist_t* last = nullptr; - for(const char* s : il) - { + ::stringlist_t* last = nullptr; + for (const char* s : il) { last = stringlist_add(last, s); - if(last==nullptr) - { + if (last == nullptr) { throw std::runtime_error("Cannot create StringPairList from {}: Out Of Memory."); } - if(value==nullptr) + if (value == nullptr) value = last; // save the head of linked list. } } -//////////////// + //////////////// template class ListWrapper<::stringlist_t*, const char*>; diff --git a/src/types.cc b/src/types.cc index 64f3529..66be112 100644 --- a/src/types.cc +++ b/src/types.cc @@ -13,31 +13,31 @@ #include #include -namespace pEp -{ - EngineError::EngineError(PEP_STATUS status, const char* message) - : std::runtime_error( - std::string{"EngineError: "} - + (message ? '"' + std::string{message} + "\" " : std::string{} ) - + status_to_string(status) - ) - {} +namespace pEp { + EngineError::EngineError(PEP_STATUS status, const char* message) : + std::runtime_error( + std::string{ "EngineError: " } + + (message ? '"' + std::string{ message } + "\" " : std::string{}) + + status_to_string(status)) + { + } -//////////////// + //////////////// template<> template<> - message* Wrapper<::message*>::_new(PEP_msg_direction dir, const char* src) + message* Wrapper<::message*>::_new( + PEP_msg_direction dir, + const char* src) { message* m = nullptr; bool pep_msg = false; - + PEP_STATUS status = mime_decode_message(src, strlen(src), &m, &pep_msg); - if(status != PEP_STATUS_OK) - { + if (status != PEP_STATUS_OK) { throw EngineError(status, "mime_decode_message()"); } - + m->dir = dir; return m; } @@ -54,30 +54,28 @@ namespace pEp return ::message_dup(value); } -//////////////// + //////////////// template<> template<> ::stringpair_t* Wrapper<::stringpair_t*>::_new(const char* key, const char* value) { stringpair_t* sp = new_stringpair(key, value); - if(!sp) - { + if (!sp) { throw EngineError(PEP_OUT_OF_MEMORY, "new_stringpair()"); } return sp; } - + template<> template<> ::stringpair_t* Wrapper<::stringpair_t*>::_new(char* key, char* value) { return _new( - const_cast(key), - const_cast(value) - ); + const_cast(key), + const_cast(value)); } - + template<> template<> ::stringpair_t* Wrapper<::stringpair_t*>::_new(const std::string& key, const std::string& value) @@ -102,9 +100,10 @@ namespace pEp { free_stringpair_list(spl); } - + template<> - stringpair_t* stringpair_list_t::* const ListWrapper::Value = &stringpair_list_t::value; + stringpair_t* stringpair_list_t::*const + ListWrapper::Value = &stringpair_list_t::value; template<> int StringPairList::size() const @@ -118,59 +117,57 @@ namespace pEp { return !(value && value->value); } - + template<> - void StringPairList::erase( const StringPairList::iterator& it) + void StringPairList::erase(const StringPairList::iterator& it) { - if(it.value && it.value->value && it.value->value->key) - { + if (it.value && it.value->value && it.value->value->key) { value = stringpair_list_delete_by_key(value, it.value->value->key); } } - + template<> void StringPairList::clear() { free_stringpair_list(value); value = nullptr; } - + template<> void StringPairList::push_back(::stringpair_t*&& sp) { auto last = stringpair_list_add(value, sp); - if(value==nullptr) + if (value == nullptr) value = last; - + sp = nullptr; } - + template<> void StringPairList::push_back(StringPair&& sp) { auto last = stringpair_list_add(value, sp.move_out()); - if(value==nullptr) + if (value == nullptr) value = last; } - + template<> - ListWrapper<::stringpair_list_t*, stringpair_t*>::ListWrapper(const std::initializer_list& il) - : StringPairList{} + ListWrapper<::stringpair_list_t*, stringpair_t*>::ListWrapper( + const std::initializer_list& il) : + StringPairList{} { - ::stringpair_list_t* last = nullptr; - for(const StringPair& sp : il) - { + ::stringpair_list_t* last = nullptr; + for (const StringPair& sp : il) { last = stringpair_list_add(last, stringpair_dup(sp.get())); - if(last==nullptr) - { + if (last == nullptr) { throw std::runtime_error("Cannot create StringPairList from {}: Out Of Memory."); } - if(value==nullptr) + if (value == nullptr) value = last; // save the head of linked list. } } -//////////////// + //////////////// template class Wrapper<::pEp_identity*>; template class Wrapper<::stringpair_t*>; diff --git a/src/types.hh b/src/types.hh index fca55e8..803592f 100644 --- a/src/types.hh +++ b/src/types.hh @@ -12,23 +12,21 @@ #include #include -namespace pEp -{ - class EngineError : std::runtime_error - { +namespace pEp { + class EngineError : std::runtime_error { public: EngineError(PEP_STATUS status, const char* message = nullptr); }; using Identity = Wrapper<::pEp_identity*>; using IdentityList = ListWrapper<::identity_list*, ::pEp_identity*>; - + using StringPair = Wrapper<::stringpair_t*>; using StringPairList = ListWrapper<::stringpair_list_t*, ::stringpair_t*>; - + using StringList = ListWrapper<::stringlist_t*, const char*>; - using BlobList = ListWrapper<::bloblist_t*, void>; - + using BlobList = ListWrapper<::bloblist_t*, void>; + using Message = Wrapper<::message*>; } // end of namespace pEp diff --git a/src/wrapper.hh b/src/wrapper.hh index 9a8597a..8e7725b 100644 --- a/src/wrapper.hh +++ b/src/wrapper.hh @@ -7,193 +7,231 @@ #include #include -namespace pEp -{ - -/// A generalized wrapper around pEpEngine's datatypes. -template -class Wrapper -{ -public: - typedef T c_type; - - template - Wrapper(Args... args) : value{ this->_new(args...) } {} - - // no implicit copying... (yet?) - Wrapper(const Wrapper&) = delete; - void operator=(const Wrapper&) = delete; - - // must be implemented separately for each T - Wrapper(Wrapper&& victim); - Wrapper& operator=(Wrapper&& victim); - - ~Wrapper(); - - Wrapper copy() const; - - bool operator==(const Wrapper& b) const - { - return value==b.value; - } - - bool operator!=(const Wrapper& b) const - { - return value!=b.value; - } - -private: - // must be defined for each wrapped type: - template - T _new(Args...); - - T value; -}; - - -// many wrapped datatypes are pointers, we can generalize a lot for them: -template -class Wrapper -{ -public: - typedef T* c_type; - - Wrapper() : value{nullptr} {} - - template - Wrapper(Args... args) : value{ this->_new(args...) } {} - - // move is easy, efficient and generic: - Wrapper(Wrapper&& victim) noexcept - : value{ victim.value} - { - victim.value = nullptr; - } - - Wrapper& operator=(Wrapper&& victim) noexcept - { - _free(value); - value = victim.value; - victim.value = nullptr; - return *this; - } - - Wrapper(const Wrapper& orig) - : value{ orig.copy_out() } - {} - - Wrapper& operator=(const Wrapper& orig) - { - if(&orig == this) return *this; - _free(value); - value = orig.copy_out(); - return *this; - } - - ~Wrapper() - { - _free(value); - } - - bool operator==(const Wrapper& b) const - { - return value==b.value; - } - - bool operator!=(const Wrapper& b) const - { - return value!=b.value; - } - - // Get read-only access to the value itself - // Beware: 'const' is not transitive in C, so the 2nd indirect data - // allows r/w access! - const T* operator->() const { return value; } - const T* get() const { return value; } - - // Dangerous: Get R/W access to the value! - T* operator->() { return value; } - T* get() { return value;} - - // Releases ownership of the value. Wrapper becomes valueless. - T* move_out() { T* r = value; value=nullptr; return r;} - - // only implemented for the datatypes where necessay. - // other implementations can follow if necessary. - T* copy_out() const; - -protected: - - Wrapper(T* _value) : value{_value} {} - - // must be defined for each wrapped type: - template - T* _new(Args...); - - void _free(T*); - - T* value; -}; - - - -// Wraps single-linked lists and provides an interface compatible -// to std::forward_list -template -class ListWrapper; - - -template -class ListWrapper : public Wrapper -{ -public: - typedef Wrapper Base; - typedef ListWrapper LW; - - static Element T::* const Value; // to access the current value - - // does not own the *value - class iterator : public std::iterator< std::forward_iterator_tag, Element, ptrdiff_t> - { +namespace pEp { + + /// A generalized wrapper around pEpEngine's datatypes. + template + class Wrapper { public: - - iterator() = default; - - iterator operator++() { return (value ? value = value->next : value); } - Element operator*() { return value->*LW::Value; } - Element operator->() { return value->*LW::Value; } - bool operator==(const iterator& other) const { return value == other.value; } - bool operator!=(const iterator& other) const { return value != other.value; } + typedef T c_type; + + template + Wrapper(Args... args) : value{ this->_new(args...) } + { + } + + // no implicit copying... (yet?) + Wrapper(const Wrapper&) = delete; + void operator=(const Wrapper&) = delete; + + // must be implemented separately for each T + Wrapper(Wrapper&& victim); + Wrapper& operator=(Wrapper&& victim); + + ~Wrapper(); + + Wrapper copy() const; + + bool operator==(const Wrapper& b) const + { + return value == b.value; + } + + bool operator!=(const Wrapper& b) const + { + return value != b.value; + } private: - iterator(T* _t) : value{_t} {} - T* value = nullptr; - friend class ListWrapper; + // must be defined for each wrapped type: + template + T _new(Args...); + + T value; + }; + + + // many wrapped datatypes are pointers, we can generalize a lot for them: + template + class Wrapper { + public: + typedef T* c_type; + + Wrapper() : value{ nullptr } {} + + template + Wrapper(Args... args) : value{ this->_new(args...) } + { + } + + // move is easy, efficient and generic: + Wrapper(Wrapper&& victim) noexcept : value{ victim.value } + { + victim.value = nullptr; + } + + Wrapper& operator=(Wrapper&& victim) noexcept + { + _free(value); + value = victim.value; + victim.value = nullptr; + return *this; + } + + Wrapper(const Wrapper& orig) : value{ orig.copy_out() } {} + + Wrapper& operator=(const Wrapper& orig) + { + if (&orig == this) + return *this; + _free(value); + value = orig.copy_out(); + return *this; + } + + ~Wrapper() + { + _free(value); + } + + bool operator==(const Wrapper& b) const + { + return value == b.value; + } + + bool operator!=(const Wrapper& b) const + { + return value != b.value; + } + + // Get read-only access to the value itself + // Beware: 'const' is not transitive in C, so the 2nd indirect data + // allows r/w access! + const T* operator->() const + { + return value; + } + const T* get() const + { + return value; + } + + // Dangerous: Get R/W access to the value! + T* operator->() + { + return value; + } + T* get() + { + return value; + } + + // Releases ownership of the value. Wrapper becomes valueless. + T* move_out() + { + T* r = value; + value = nullptr; + return r; + } + + // only implemented for the datatypes where necessay. + // other implementations can follow if necessary. + T* copy_out() const; + + protected: + Wrapper(T* _value) : value{ _value } {} + + // must be defined for each wrapped type: + template + T* _new(Args...); + + void _free(T*); + + T* value; + }; + + + // Wraps single-linked lists and provides an interface compatible + // to std::forward_list + template + class ListWrapper; + + + template + class ListWrapper : public Wrapper { + public: + typedef Wrapper Base; + typedef ListWrapper LW; + + static Element T::*const Value; // to access the current value + + // does not own the *value + class iterator : public std::iterator { + public: + iterator() = default; + + iterator operator++() + { + return (value ? value = value->next : value); + } + Element operator*() + { + return value->*LW::Value; + } + Element operator->() + { + return value->*LW::Value; + } + bool operator==(const iterator& other) const + { + return value == other.value; + } + bool operator!=(const iterator& other) const + { + return value != other.value; + } + + private: + iterator(T* _t) : value{ _t } {} + T* value = nullptr; + friend class ListWrapper; + }; + + typedef const iterator const_iterator; + + + using Base::value; + + ListWrapper() : Base() {} + + ListWrapper(const std::initializer_list>& i); + ListWrapper(const std::initializer_list& i); + + iterator begin() + { + return iterator{ value }; + } + iterator end() const + { + return iterator{}; + } + const_iterator cbegin() const + { + return const_iterator{ value }; + } + const_iterator cend() const + { + return const_iterator{}; + } + + int size() const; + bool empty() const; + + void erase(const iterator& it); + void clear(); + void push_back(Element&&); + void push_back(Wrapper&&); }; - - typedef const iterator const_iterator; - - - using Base::value; - - ListWrapper() : Base() {} - - ListWrapper(const std::initializer_list>& i); - ListWrapper(const std::initializer_list& i); - - iterator begin() { return iterator{value}; } - iterator end() const { return iterator{}; } - const_iterator cbegin() const { return const_iterator{value}; } - const_iterator cend() const { return const_iterator{}; } - - int size() const; - bool empty() const; - - void erase(const iterator& it); - void clear(); - void push_back(Element&&); - void push_back(Wrapper&&); -}; } // end of namespace pEp diff --git a/test/unittest_identity.cc b/test/unittest_identity.cc index 152b7eb..45b467e 100644 --- a/test/unittest_identity.cc +++ b/test/unittest_identity.cc @@ -3,32 +3,38 @@ #include "../src/types.hh" -TEST( PepIdentity, Simple ) +TEST(PepIdentity, Simple) { - pEp::Identity id{"test1@pEpdatatypes.lol", "FF00112233445566778899AABBCCDDEEFF001122", "Test User ID", "Test User Name"}; + pEp::Identity id{ "test1@pEpdatatypes.lol", + "FF00112233445566778899AABBCCDDEEFF001122", + "Test User ID", + "Test User Name" }; } -TEST( IdentityList, Simple ) +TEST(IdentityList, Simple) { pEp::IdentityList il; EXPECT_TRUE(il.empty()); EXPECT_EQ(il.size(), 0); } -TEST( IdentityList, InitList ) +TEST(IdentityList, InitList) { - pEp::IdentityList il( - { - pEp::Identity{"test-init1@pEpdatatypes.lol", "0100112233445566778899AABBCCDDEEFF001122", "Test User ID1", "Test User 1 Name"}, - pEp::Identity{"test-init2@pEpdatatypes.lol", "0200112233445566778899AABBCCDDEEFF001122", "Test User ID2", "Test User 2 Name"} - } ); - - EXPECT_EQ( il.size(), 2); - + pEp::IdentityList il({ pEp::Identity{ "test-init1@pEpdatatypes.lol", + "0100112233445566778899AABBCCDDEEFF001122", + "Test User ID1", + "Test User 1 Name" }, + pEp::Identity{ "test-init2@pEpdatatypes.lol", + "0200112233445566778899AABBCCDDEEFF001122", + "Test User ID2", + "Test User 2 Name" } }); + + EXPECT_EQ(il.size(), 2); + il.clear(); EXPECT_EQ(il.size(), 0); - EXPECT_TRUE( il.empty() ); + EXPECT_TRUE(il.empty()); } diff --git a/test/unittest_message.cc b/test/unittest_message.cc index 82d9849..1d135ee 100644 --- a/test/unittest_message.cc +++ b/test/unittest_message.cc @@ -2,113 +2,112 @@ #include "../src/types.hh" -namespace -{ - static const char* mail1_eml = - "Return-Path: \r\n" - "X-Original-To: alice@pep-project.org\r\n" - "Delivered-To: alice@pep-project.org\r\n" - "Received: from localhost (localhost [127.0.0.1])\r\n" - "\tby dragon.pibit.ch (Postfix) with ESMTP id B84AF171C06F\r\n" - "\tfor ; Wed, 16 Jan 2019 16:29:39 +0100 (CET)\r\n" - "Received: from dragon.pibit.ch ([127.0.0.1])\r\n" - "\tby localhost (dragon.pibit.ch [127.0.0.1]) (amavisd-new, port 10024)\r\n" - "\twith ESMTP id q0wZqHMoT1gS for ;\r\n" - "\tWed, 16 Jan 2019 16:29:37 +0100 (CET)\r\n" - "Received: from Alice-PC.local (unknown [192.168.128.20])\r\n" - "\tby dragon.pibit.ch (Postfix) with ESMTPSA id 563DD171C06A\r\n" - "\tfor ; Wed, 16 Jan 2019 16:29:37 +0100 (CET)\r\n" - "To: Bob \r\n" - "From: Alice \r\n" - "Cc: Carol Couscous , Dave Doe (III) \r\n" - " Dexter , dodo@pep.lol, \"Eve @ Evil\" , \r\n" - " Mallory =?UTF-8?B?TcO2bGxlcg==?= (private) <\"mallory @ moeller\"@sinister.aq>\r\n" - "Subject: =?UTF-8?B?UsO4ZGdyw7hkIG1lZCBmbMO4ZGU=?=\r\n" - "Openpgp: preference=signencrypt\r\n" - "Organization: =?UTF-8?B?8J+Ukg==?=\r\n" - "Message-ID: <65a2df2c-ddc8-0875-a142-21acf62ed467@pep-project.org>\r\n" - "References: \r\n" - " \r\n" - "In-Reply-To: \r\n" - "Date: Wed, 16 Jan 2019 16:29:30 +0100\r\n" - "User-Agent: B\r\n" - "MIME-Version: 1.0\r\n" - "Content-Type: multipart/mixed;\r\n" - " boundary=\"==pEp_01==\"\r\n" - "\r\n" - "This is a Multipart MIME message.\r\n" - "--==pEp_01==\r\n" - "Content-Type: multipart/alternative; boundary=\"==pEp_02==\";\r\n" - " protected-headers=\"v1\"\r\n" - "\r\n" - "--==pEp_02==\r\n" - "Content-Type: text/plain; charset=\"utf-8\"\r\n" - "Content-Language: en-US\r\n" - "Content-Transfer-Encoding: quoted-printable\r\n" - "\r\n" - "R=C3=B8dgr=C3=B8d med fl=C3=B8de?\r\n" - "\r\n" - "--==pEp_02==\r\n" - "Content-Type: multipart/related; boundary=\"==pEp_LoL==\";\r\n" - "\r\n" - "--==pEp_LoL==\r\n" - "Content-Type: text/html; charset=\"ISO-8859-1\";\r\n" - "Content-Transfer-Encoding: quoted-printable\r\n" - "\r\n" - "=DCbergr=F6=DFen=E4nderung: 1=\r\n" - "0=80.\r\n" - "\r\n" - "--==pEp_LoL==\r\n" - "Content-Type: image/png; name=\"rebeccapurple-circle.png\"\r\n" - "Content-Language: en-US\r\n" - "Content-ID: \r\n" - "Content-Transfer-Encoding: base64\r\n" - "Content-Disposition: inline;\r\n" - " filename*0*=utf-8'en-US'rebeccapurple;\r\n" - " filename*1*=%2Dcircle.png;\r\n" - "\r\n" - "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEVmM5n///9dvR/iAAAA\r\n" - "H0lEQVQIHWP4Ic/wgJ3hADNDAyMIYQKIOFABUNkPeQC4LQeH3BOsvgAAAABJRU5ErkJggg==\r\n" - "\r\n" - "--==pEp_LoL==--\r\n" // end of multipart/related - "\r\n" - "--==pEp_02==--\r\n" // end of multipart/alternative - "\r\n" - "--==pEp_01==\r\n" // first "real" attachment, 2nd in bloblist - "Content-Type: application/octet-stream; name=\"This is a long\r\n" - " file name so it is split to multiple\r\n" - " physical lines.bin\"\r\n" - "Content-Language: en-US\r\n" - "Content-Transfer-Encoding: base64\r\n" - "Content-Disposition: attachment;\r\n" - " filename*0=\"This is a long file name so it is split to\";\r\n" - " filename*1=\" multiple physical lines.bin\";\r\n" - "\r\n" - "w5xiZXJncsO2w59lbsOkbmRlcnVuZyEK\r\n" - "\r\n" - "--==pEp_01==\r\n" // another text/plain part, 3rd in bloblist - "Content-Type: text/plain; charset=\"ISO-8859-15\";\r\n" - "Content-Transfer-Encoding: quoted-printable\r\n" - "\r\n" - "=DCbergr=F6=DFen=E4nderung: 10=A4.\r\n" - "--==pEp_01==\r\n" // an attached PNG image with bizarre filename as 4th and last element in bloblist - "Content-Type: image/png; name=\"=?UTF-8?B?8J+SqSDwn5iAIPCf?=" - " =?UTF-8?B?kqkg8J+YgCDwn5KpIPCfmIAg8J+SqSDwn5iAIPCfkqkg8J+YgCDwn5KpIPCfm?=" - " =?UTF-8?B?IAg8J+SqSDwn5iAIPCfkqkg8J+YgC5wbmc=?=\"\r\n" - "Content-Language: en-US\r\n" - "Content-Transfer-Encoding: base64\r\n" - "Content-Disposition: attachment;\r\n" - " filename*0*=utf-8''%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0;\r\n" - " filename*1*=%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9;\r\n" - " filename*2*=%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F;\r\n" - " filename*3*=%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20;\r\n" - " filename*4*=%F0%9F%92%A9%20%F0%9F%98%80.png\r\n" - "\r\n" - "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEVmM5n///9dvR/iAAAA\r\n" - " H0lEQVQIHWP4Ic/wgJ3hADN\r\n" - "DAyMIYQKIOFABUNkPeQC4LQeH3BOsvgAAAABJRU5ErkJggg==\r\n" - "--==pEp_01==--\r\n" - "\r\n"; +namespace { + static const char* + mail1_eml = "Return-Path: \r\n" + "X-Original-To: alice@pep-project.org\r\n" + "Delivered-To: alice@pep-project.org\r\n" + "Received: from localhost (localhost [127.0.0.1])\r\n" + "\tby dragon.pibit.ch (Postfix) with ESMTP id B84AF171C06F\r\n" + "\tfor ; Wed, 16 Jan 2019 16:29:39 +0100 (CET)\r\n" + "Received: from dragon.pibit.ch ([127.0.0.1])\r\n" + "\tby localhost (dragon.pibit.ch [127.0.0.1]) (amavisd-new, port 10024)\r\n" + "\twith ESMTP id q0wZqHMoT1gS for ;\r\n" + "\tWed, 16 Jan 2019 16:29:37 +0100 (CET)\r\n" + "Received: from Alice-PC.local (unknown [192.168.128.20])\r\n" + "\tby dragon.pibit.ch (Postfix) with ESMTPSA id 563DD171C06A\r\n" + "\tfor ; Wed, 16 Jan 2019 16:29:37 +0100 (CET)\r\n" + "To: Bob \r\n" + "From: Alice \r\n" + "Cc: Carol Couscous , Dave Doe (III) \r\n" + " Dexter , dodo@pep.lol, \"Eve @ Evil\" , \r\n" + " Mallory =?UTF-8?B?TcO2bGxlcg==?= (private) <\"mallory @ moeller\"@sinister.aq>\r\n" + "Subject: =?UTF-8?B?UsO4ZGdyw7hkIG1lZCBmbMO4ZGU=?=\r\n" + "Openpgp: preference=signencrypt\r\n" + "Organization: =?UTF-8?B?8J+Ukg==?=\r\n" + "Message-ID: <65a2df2c-ddc8-0875-a142-21acf62ed467@pep-project.org>\r\n" + "References: \r\n" + " \r\n" + "In-Reply-To: \r\n" + "Date: Wed, 16 Jan 2019 16:29:30 +0100\r\n" + "User-Agent: B\r\n" + "MIME-Version: 1.0\r\n" + "Content-Type: multipart/mixed;\r\n" + " boundary=\"==pEp_01==\"\r\n" + "\r\n" + "This is a Multipart MIME message.\r\n" + "--==pEp_01==\r\n" + "Content-Type: multipart/alternative; boundary=\"==pEp_02==\";\r\n" + " protected-headers=\"v1\"\r\n" + "\r\n" + "--==pEp_02==\r\n" + "Content-Type: text/plain; charset=\"utf-8\"\r\n" + "Content-Language: en-US\r\n" + "Content-Transfer-Encoding: quoted-printable\r\n" + "\r\n" + "R=C3=B8dgr=C3=B8d med fl=C3=B8de?\r\n" + "\r\n" + "--==pEp_02==\r\n" + "Content-Type: multipart/related; boundary=\"==pEp_LoL==\";\r\n" + "\r\n" + "--==pEp_LoL==\r\n" + "Content-Type: text/html; charset=\"ISO-8859-1\";\r\n" + "Content-Transfer-Encoding: quoted-printable\r\n" + "\r\n" + "=DCbergr=F6=DFen=E4nderung: 1=\r\n" + "0=80.\r\n" + "\r\n" + "--==pEp_LoL==\r\n" + "Content-Type: image/png; name=\"rebeccapurple-circle.png\"\r\n" + "Content-Language: en-US\r\n" + "Content-ID: \r\n" + "Content-Transfer-Encoding: base64\r\n" + "Content-Disposition: inline;\r\n" + " filename*0*=utf-8'en-US'rebeccapurple;\r\n" + " filename*1*=%2Dcircle.png;\r\n" + "\r\n" + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEVmM5n///9dvR/iAAAA\r\n" + "H0lEQVQIHWP4Ic/wgJ3hADNDAyMIYQKIOFABUNkPeQC4LQeH3BOsvgAAAABJRU5ErkJggg==\r\n" + "\r\n" + "--==pEp_LoL==--\r\n" // end of multipart/related + "\r\n" + "--==pEp_02==--\r\n" // end of multipart/alternative + "\r\n" + "--==pEp_01==\r\n" // first "real" attachment, 2nd in bloblist + "Content-Type: application/octet-stream; name=\"This is a long\r\n" + " file name so it is split to multiple\r\n" + " physical lines.bin\"\r\n" + "Content-Language: en-US\r\n" + "Content-Transfer-Encoding: base64\r\n" + "Content-Disposition: attachment;\r\n" + " filename*0=\"This is a long file name so it is split to\";\r\n" + " filename*1=\" multiple physical lines.bin\";\r\n" + "\r\n" + "w5xiZXJncsO2w59lbsOkbmRlcnVuZyEK\r\n" + "\r\n" + "--==pEp_01==\r\n" // another text/plain part, 3rd in bloblist + "Content-Type: text/plain; charset=\"ISO-8859-15\";\r\n" + "Content-Transfer-Encoding: quoted-printable\r\n" + "\r\n" + "=DCbergr=F6=DFen=E4nderung: 10=A4.\r\n" + "--==pEp_01==\r\n" // an attached PNG image with bizarre filename as 4th and last element in bloblist + "Content-Type: image/png; name=\"=?UTF-8?B?8J+SqSDwn5iAIPCf?=" + " =?UTF-8?B?kqkg8J+YgCDwn5KpIPCfmIAg8J+SqSDwn5iAIPCfkqkg8J+YgCDwn5KpIPCfm?=" + " =?UTF-8?B?IAg8J+SqSDwn5iAIPCfkqkg8J+YgC5wbmc=?=\"\r\n" + "Content-Language: en-US\r\n" + "Content-Transfer-Encoding: base64\r\n" + "Content-Disposition: attachment;\r\n" + " filename*0*=utf-8''%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0;\r\n" + " filename*1*=%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9;\r\n" + " filename*2*=%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F;\r\n" + " filename*3*=%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20;\r\n" + " filename*4*=%F0%9F%92%A9%20%F0%9F%98%80.png\r\n" + "\r\n" + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEVmM5n///9dvR/iAAAA\r\n" + " H0lEQVQIHWP4Ic/wgJ3hADN\r\n" + "DAyMIYQKIOFABUNkPeQC4LQeH3BOsvgAAAABJRU5ErkJggg==\r\n" + "--==pEp_01==--\r\n" + "\r\n"; PEP_STATUS dummy_message(::message* msg) @@ -120,21 +119,21 @@ namespace } // end of anonymous namespace -TEST( MessageTest, Simple ) +TEST(MessageTest, Simple) { - pEp::Message msg{PEP_dir_outgoing, mail1_eml}; - + pEp::Message msg{ PEP_dir_outgoing, mail1_eml }; + EXPECT_EQ(msg->dir, PEP_dir_outgoing); - EXPECT_STREQ( msg->shortmsg, "Rødgrød med fløde" ); - EXPECT_STREQ( msg->longmsg , "Rødgrød med fløde?\r\n" ); - EXPECT_EQ( identity_list_length(msg->to), 1 ); - EXPECT_EQ( identity_list_length(msg->cc), 5 ); - EXPECT_EQ( identity_list_length(msg->bcc), 0 ); - EXPECT_EQ( bloblist_length(msg->attachments), 4 ); + EXPECT_STREQ(msg->shortmsg, "Rødgrød med fløde"); + EXPECT_STREQ(msg->longmsg, "Rødgrød med fløde?\r\n"); + EXPECT_EQ(identity_list_length(msg->to), 1); + EXPECT_EQ(identity_list_length(msg->cc), 5); + EXPECT_EQ(identity_list_length(msg->bcc), 0); + EXPECT_EQ(bloblist_length(msg->attachments), 4); ASSERT_NE(msg->from, nullptr); - EXPECT_STREQ( msg->from->username, "Alice"); - - EXPECT_EQ( dummy_message(msg.get()), PEP_STATUS_OK); - EXPECT_STREQ( msg->shortmsg, "Hello World"); + EXPECT_STREQ(msg->from->username, "Alice"); + + EXPECT_EQ(dummy_message(msg.get()), PEP_STATUS_OK); + EXPECT_STREQ(msg->shortmsg, "Hello World"); } diff --git a/test/unittest_nfc.cc b/test/unittest_nfc.cc index 6147c49..14ff506 100644 --- a/test/unittest_nfc.cc +++ b/test/unittest_nfc.cc @@ -1,6 +1,6 @@ #include -#include "../src/nfc.hh" // for illegal_utf8 exception +#include "../src/nfc.hh" // for illegal_utf8 exception #include using namespace pEp; @@ -8,70 +8,82 @@ using std::string_view; namespace { -struct TestEntry -{ - string_view input; - bool is_nfc; - IsNFC quick; - string_view nfc; + struct TestEntry { + string_view input; + bool is_nfc; + IsNFC quick; + string_view nfc; + }; + + typedef TestEntry TE; + + + std::ostream& operator<<(std::ostream& o, const TestEntry& tt) + { + return o << "input=«" << tt.input << "», isNfc=" << tt.is_nfc << ", quick=" << tt.quick + << ". "; + } + + + const char nullo[4] = { 0, 0, 0, 0 }; + + const std::vector testValues = { + { "", true, IsNFC::Yes, "" }, // always start with the simple case ;-) + { "123", true, IsNFC::Yes, "123" }, // some ASCII digits. Still easy. + { "\n\\\b", true, IsNFC::Yes, "\n\\\b" }, // backslash escapes for ASCII and control chars + { "ä", true, IsNFC::Yes, "ä" }, // small a with diaeresis + { "\xc4\x85", true, IsNFC::Yes, "\xc4\x85" }, // small a with ogonek + + { "a\xcc\x88", false, IsNFC::Maybe, "ä" }, // a + combining diaresis + { "a\xcc\xa8", false, IsNFC::Maybe, "\xc4\x85" }, // a + combining ogonek + { "a\xcc\xa8\xcc\x88", + false, + IsNFC::Maybe, + "\xc4\x85\xcc\x88" }, // a + + (ogonek + diaeresis) + { "a\xcc\x88\xcc\xa8", + false, + IsNFC::Maybe, + "\xc4\x85\xcc\x88" }, // a + + (diaeresis + ogonek) + + { "\xc4\x85\xcc\x88", + true, + IsNFC::Maybe, + "\xc4\x85\xcc\x88" }, // small a with ogonek + combining diaeresis + { "ä\xcc\xa8", false, IsNFC::Maybe, "\xc4\x85\xcc\x88" }, // a diaeresis + combining ogonek + + // Already implemented, because and have neither "No" nor "Maybe" NFC class: + { "a\xcc\x85\xcc\xbc", + false, + IsNFC::No, + "a\xcc\xbc\xcc\x85" }, // a + + (overline + seagull_below) + { "a\xcc\xbc\xcc\x85", + true, + IsNFC::Yes, + "a\xcc\xbc\xcc\x85" }, // a + + (seagull_below + overline) + + { string_view(nullo, 1), true, IsNFC::Yes, string_view(nullo, 1) }, // Yeah, 1 NUL byte + { string_view(nullo, 4), true, IsNFC::Yes, string_view(nullo, 4) }, // Yeah, 4 NUL bytes + + { "EOF", true, IsNFC::Yes, "EOF" } + }; + +} // namespace + +class NfcTest : public ::testing::TestWithParam { + // intentionally left blank for now. }; -typedef TestEntry TE; - - -std::ostream& operator<<(std::ostream& o, const TestEntry& tt) -{ - return o << "input=«" << tt.input << "», isNfc=" << tt.is_nfc << ", quick=" << tt.quick << ". "; -} - - -const char nullo[4] = {0,0,0,0}; - -const std::vector testValues = - { - { "" , true, IsNFC::Yes, "" }, // always start with the simple case ;-) - { "123" , true, IsNFC::Yes, "123" }, // some ASCII digits. Still easy. - { "\n\\\b" , true, IsNFC::Yes, "\n\\\b" }, // backslash escapes for ASCII and control chars - { "ä" , true, IsNFC::Yes, "ä" }, // small a with diaeresis - { "\xc4\x85" , true, IsNFC::Yes, "\xc4\x85" }, // small a with ogonek +INSTANTIATE_TEST_SUITE_P(NfcTestInstance, NfcTest, testing::ValuesIn(testValues)); - { "a\xcc\x88", false, IsNFC::Maybe, "ä" }, // a + combining diaresis - { "a\xcc\xa8", false, IsNFC::Maybe, "\xc4\x85" }, // a + combining ogonek - { "a\xcc\xa8\xcc\x88", false, IsNFC::Maybe, "\xc4\x85\xcc\x88" }, // a + + (ogonek + diaeresis) - { "a\xcc\x88\xcc\xa8", false, IsNFC::Maybe, "\xc4\x85\xcc\x88" }, // a + + (diaeresis + ogonek) - - { "\xc4\x85\xcc\x88" , true, IsNFC::Maybe, "\xc4\x85\xcc\x88" }, // small a with ogonek + combining diaeresis - { "ä\xcc\xa8" , false, IsNFC::Maybe, "\xc4\x85\xcc\x88" }, // a diaeresis + combining ogonek - -// Already implemented, because and have neither "No" nor "Maybe" NFC class: - { "a\xcc\x85\xcc\xbc", false, IsNFC::No , "a\xcc\xbc\xcc\x85"}, // a + + (overline + seagull_below) - { "a\xcc\xbc\xcc\x85", true, IsNFC::Yes , "a\xcc\xbc\xcc\x85"}, // a + + (seagull_below + overline) - - { string_view(nullo, 1), true, IsNFC::Yes, string_view(nullo, 1) }, // Yeah, 1 NUL byte - { string_view(nullo, 4), true, IsNFC::Yes, string_view(nullo, 4) }, // Yeah, 4 NUL bytes - - { "EOF", true, IsNFC::Yes, "EOF" } - }; - -} - -class NfcTest : public ::testing::TestWithParam +TEST_P(NfcTest, Meh) { - // intentionally left blank for now. -}; + const auto& v = GetParam(); + EXPECT_EQ(v.quick, UTF8::isNFC_quick_check(v.input)); -INSTANTIATE_TEST_SUITE_P(NfcTestInstance, NfcTest, testing::ValuesIn(testValues) ); + EXPECT_EQ(v.is_nfc, UTF8::isNFC(v.input)); + EXPECT_EQ(v.nfc, UTF8::toNFC(v.input)); -TEST_P( NfcTest, Meh ) -{ - const auto& v = GetParam(); - EXPECT_EQ( v.quick, UTF8::isNFC_quick_check(v.input) ); - - EXPECT_EQ( v.is_nfc, UTF8::isNFC(v.input) ); - EXPECT_EQ( v.nfc , UTF8::toNFC(v.input) ); - - if(v.is_nfc) - { - EXPECT_EQ( v.input, UTF8::toNFC(v.input) ); - } + if (v.is_nfc) { + EXPECT_EQ(v.input, UTF8::toNFC(v.input)); + } } diff --git a/test/unittest_nfc16.cc b/test/unittest_nfc16.cc index c06dbdf..ccc8175 100644 --- a/test/unittest_nfc16.cc +++ b/test/unittest_nfc16.cc @@ -1,85 +1,81 @@ #include -#include "../src/nfc.hh" // for illegal_utf8 exception +#include "../src/nfc.hh" // for illegal_utf8 exception #include using namespace pEp; using std::u16string_view; -namespace pEp -{ - std::string escape_utf16(u16string_view s); +namespace pEp { + std::string escape_utf16(u16string_view s); } namespace { -struct TestEntry -{ - u16string_view input; - bool is_nfc; - IsNFC quick; - u16string_view nfc; -}; + struct TestEntry { + u16string_view input; + bool is_nfc; + IsNFC quick; + u16string_view nfc; + }; -typedef TestEntry TE; + typedef TestEntry TE; -std::ostream& operator<<(std::ostream& o, const TestEntry& tt) -{ - return o << "input=«" << pEp::escape_utf16(tt.input) << "», isNfc=" << tt.is_nfc << ", quick=" << tt.quick << ". "; -} + std::ostream& operator<<(std::ostream& o, const TestEntry& tt) + { + return o << "input=«" << pEp::escape_utf16(tt.input) << "», isNfc=" << tt.is_nfc + << ", quick=" << tt.quick << ". "; + } -const char16_t nullo[4] = {0,0,0,0}; + const char16_t nullo[4] = { 0, 0, 0, 0 }; -const std::vector testValues = - { - { u"" , true, IsNFC::Yes, u"" }, // always start with the simple case ;-) - { u"123" , true, IsNFC::Yes, u"123" }, // some ASCII digits. Still easy. - { u"\n\\\b" , true, IsNFC::Yes, u"\n\\\b" }, // backslash escapes for ASCII and control chars - { u"ä" , true, IsNFC::Yes, u"ä" }, // small a with diaeresis - { u"\u0105" , true, IsNFC::Yes, u"\u0105" }, // small a with ogonek + const std::vector testValues = { + { u"", true, IsNFC::Yes, u"" }, // always start with the simple case ;-) + { u"123", true, IsNFC::Yes, u"123" }, // some ASCII digits. Still easy. + { u"\n\\\b", true, IsNFC::Yes, u"\n\\\b" }, // backslash escapes for ASCII and control chars + { u"ä", true, IsNFC::Yes, u"ä" }, // small a with diaeresis + { u"\u0105", true, IsNFC::Yes, u"\u0105" }, // small a with ogonek - { u"a\u0308" , false, IsNFC::Maybe, u"ä" }, // a + combining diaresis - { u"a\u0328" , false, IsNFC::Maybe, u"\u0105" }, // a + combining ogonek - { u"a\u0328\u0308", false, IsNFC::Maybe, u"\u0105\u0308" }, // a + + (ogonek + diaeresis) - { u"a\u0308\u0328", false, IsNFC::Maybe, u"\u0105\u0308" }, // a + + (diaeresis + ogonek) + { u"a\u0308", false, IsNFC::Maybe, u"ä" }, // a + combining diaresis + { u"a\u0328", false, IsNFC::Maybe, u"\u0105" }, // a + combining ogonek + { u"a\u0328\u0308", false, IsNFC::Maybe, u"\u0105\u0308" }, // a + + (ogonek + diaeresis) + { u"a\u0308\u0328", false, IsNFC::Maybe, u"\u0105\u0308" }, // a + + (diaeresis + ogonek) - { u"\u0105\u0308" , true, IsNFC::Maybe, u"\u0105\u0308" }, // small a with ogonek + combining diaeresis - { u"ä\u0328" , false, IsNFC::Maybe, u"\u0105\u0308" }, // a diaeresis + combining ogonek + { u"\u0105\u0308", true, IsNFC::Maybe, u"\u0105\u0308" }, // small a with ogonek + combining diaeresis + { u"ä\u0328", false, IsNFC::Maybe, u"\u0105\u0308" }, // a diaeresis + combining ogonek -// Already implemented, because and have neither "No" nor "Maybe" NFC class: - { u"a\u0305\u033c", false, IsNFC::No , u"a\u033c\u0305"}, // a + + (overline + seagull_below) - { u"a\u033c\u0305", true, IsNFC::Yes , u"a\u033c\u0305"}, // a + + (seagull_below + overline) + // Already implemented, because and have neither "No" nor "Maybe" NFC class: + { u"a\u0305\u033c", false, IsNFC::No, u"a\u033c\u0305" }, // a + + (overline + seagull_below) + { u"a\u033c\u0305", true, IsNFC::Yes, u"a\u033c\u0305" }, // a + + (seagull_below + overline) - // MUSICAL SYMBOL SIXTEENTH NOTE -> will be decomposed and not re-composed according to Unicode data, for whatever reason. :-/ - { u"\U0001D161", false, IsNFC::No, u"\U0001d15f\U0001d16f" }, - { u16string_view(nullo, 1), true, IsNFC::Yes, u16string_view(nullo, 1) }, // Yeah, 1 NUL byte - { u16string_view(nullo, 4), true, IsNFC::Yes, u16string_view(nullo, 4) }, // Yeah, 4 NUL bytes - - { u"EOF", true, IsNFC::Yes, u"EOF" } - }; + // MUSICAL SYMBOL SIXTEENTH NOTE -> will be decomposed and not re-composed according to Unicode data, for whatever reason. :-/ + { u"\U0001D161", false, IsNFC::No, u"\U0001d15f\U0001d16f" }, + { u16string_view(nullo, 1), true, IsNFC::Yes, u16string_view(nullo, 1) }, // Yeah, 1 NUL byte + { u16string_view(nullo, 4), true, IsNFC::Yes, u16string_view(nullo, 4) }, // Yeah, 4 NUL bytes + + { u"EOF", true, IsNFC::Yes, u"EOF" } + }; } // end of anonymous namespace -class Nfc16Test : public ::testing::TestWithParam -{ - // intentionally left blank for now. +class Nfc16Test : public ::testing::TestWithParam { + // intentionally left blank for now. }; -INSTANTIATE_TEST_SUITE_P(Nfc16TestInstance, Nfc16Test, testing::ValuesIn(testValues) ); +INSTANTIATE_TEST_SUITE_P(Nfc16TestInstance, Nfc16Test, testing::ValuesIn(testValues)); -TEST_P( Nfc16Test, Meh ) +TEST_P(Nfc16Test, Meh) { - const auto& v = GetParam(); - EXPECT_EQ( v.quick, UTF16::isNFC_quick_check(v.input) ); - - EXPECT_EQ( v.is_nfc, UTF16::isNFC(v.input) ); - EXPECT_EQ( v.nfc , UTF16::toNFC(v.input) ); - - if(v.is_nfc) - { - EXPECT_EQ( v.input, UTF16::toNFC(v.input) ); - } + const auto& v = GetParam(); + EXPECT_EQ(v.quick, UTF16::isNFC_quick_check(v.input)); + + EXPECT_EQ(v.is_nfc, UTF16::isNFC(v.input)); + EXPECT_EQ(v.nfc, UTF16::toNFC(v.input)); + + if (v.is_nfc) { + EXPECT_EQ(v.input, UTF16::toNFC(v.input)); + } } diff --git a/test/unittest_nfcstring.cc b/test/unittest_nfcstring.cc index eb5b4f9..4e79bb0 100644 --- a/test/unittest_nfcstring.cc +++ b/test/unittest_nfcstring.cc @@ -1,6 +1,6 @@ #include -#include "../src/nfc.hh" // for illegal_utf8 exception +#include "../src/nfc.hh" // for illegal_utf8 exception #include using namespace pEp; @@ -8,67 +8,64 @@ using std::string_view; namespace { -struct TestEntry -{ - string_view input; - string_view nfc; -}; + struct TestEntry { + string_view input; + string_view nfc; + }; -typedef TestEntry TE; + typedef TestEntry TE; -std::ostream& operator<<(std::ostream& o, const TestEntry& tt) -{ - return o << "input=«" << tt.input << "», nfc=«" << tt.nfc << "» "; -} + std::ostream& operator<<(std::ostream& o, const TestEntry& tt) + { + return o << "input=«" << tt.input << "», nfc=«" << tt.nfc << "» "; + } } // end of anonymous namespace -TEST( NfcTestString, Simple ) +TEST(NfcTestString, Simple) { - pEp::nfc_string s; - EXPECT_TRUE( s.empty() ); - EXPECT_EQ( s.size(), 0 ); - - s.reserve(1000); - EXPECT_GE(s.capacity(), 1000); - - s = "Ha\u0308user"; // non-NFC input will be normalized. - EXPECT_NE( s.get(), std::string("Ha\u0308user") ); - EXPECT_EQ( s.get(), std::string("Häuser") ); - - s.insert(0, "U\u0308ber"); - EXPECT_EQ( s.get(), std::string("ÜberHäuser") ); - - s += "\u0328\u030c"; // COMBINING OGONEK (below), COMBINING CARON (above) - // r absorbs the caron into U+0159, the combining ogonek remains separate - EXPECT_EQ( s.get(), std::string("ÜberHäuse\u0159\u0328") ); - EXPECT_EQ( s.size(), 15); - - EXPECT_THROW( s.substr(1), pEp::illegal_utf ); - EXPECT_THROW( s.substr(2, 10), pEp::illegal_utf ); - - // removal of the r-with-caron let the remaining ogonek combine with the e to U+0119 (E WITH OGONEK) - EXPECT_EQ( s.erase(11, 2).get(), "ÜberHäus\u0119" ); - - EXPECT_TRUE ( s.starts_with("Üb") ); - EXPECT_FALSE( s.starts_with("Üx") ); - EXPECT_TRUE ( s.ends_with("s\u0119") ); - EXPECT_FALSE( s.ends_with("ss\u0119") ); - - EXPECT_EQ( s.find("Über"), 0u ); - EXPECT_EQ( s.find("ber") , 2u ); - EXPECT_EQ( s.find("über"), UTF8::nfc_string::npos ); - EXPECT_EQ( s.find("Übel"), UTF8::nfc_string::npos ); - + pEp::nfc_string s; + EXPECT_TRUE(s.empty()); + EXPECT_EQ(s.size(), 0); + + s.reserve(1000); + EXPECT_GE(s.capacity(), 1000); + + s = "Ha\u0308user"; // non-NFC input will be normalized. + EXPECT_NE(s.get(), std::string("Ha\u0308user")); + EXPECT_EQ(s.get(), std::string("Häuser")); + + s.insert(0, "U\u0308ber"); + EXPECT_EQ(s.get(), std::string("ÜberHäuser")); + + s += "\u0328\u030c"; // COMBINING OGONEK (below), COMBINING CARON (above) + // r absorbs the caron into U+0159, the combining ogonek remains separate + EXPECT_EQ(s.get(), std::string("ÜberHäuse\u0159\u0328")); + EXPECT_EQ(s.size(), 15); + + EXPECT_THROW(s.substr(1), pEp::illegal_utf); + EXPECT_THROW(s.substr(2, 10), pEp::illegal_utf); + + // removal of the r-with-caron let the remaining ogonek combine with the e to U+0119 (E WITH OGONEK) + EXPECT_EQ(s.erase(11, 2).get(), "ÜberHäus\u0119"); + + EXPECT_TRUE(s.starts_with("Üb")); + EXPECT_FALSE(s.starts_with("Üx")); + EXPECT_TRUE(s.ends_with("s\u0119")); + EXPECT_FALSE(s.ends_with("ss\u0119")); + + EXPECT_EQ(s.find("Über"), 0u); + EXPECT_EQ(s.find("ber"), 2u); + EXPECT_EQ(s.find("über"), UTF8::nfc_string::npos); + EXPECT_EQ(s.find("Übel"), UTF8::nfc_string::npos); } -TEST( NfcTestString, Exceptions ) +TEST(NfcTestString, Exceptions) { - pEp::nfc_string s; - EXPECT_THROW( s = "Meep\xc0\x80.", pEp::illegal_utf ); - EXPECT_THROW( s += '\377', pEp::illegal_utf ); - + pEp::nfc_string s; + EXPECT_THROW(s = "Meep\xc0\x80.", pEp::illegal_utf); + EXPECT_THROW(s += '\377', pEp::illegal_utf); } diff --git a/test/unittest_stringlist.cc b/test/unittest_stringlist.cc index 5234d5e..91b6c2a 100644 --- a/test/unittest_stringlist.cc +++ b/test/unittest_stringlist.cc @@ -3,70 +3,68 @@ #include "../src/types.hh" -TEST( StringList, Simple ) +TEST(StringList, Simple) { pEp::StringList sl; EXPECT_TRUE(sl.empty()); EXPECT_EQ(sl.size(), 0); } -TEST( StringList, InitList ) +TEST(StringList, InitList) { - pEp::StringList sl( {"Hello", "world"} ); - EXPECT_EQ( sl.size(), 2); - + pEp::StringList sl({ "Hello", "world" }); + EXPECT_EQ(sl.size(), 2); + sl.clear(); EXPECT_EQ(sl.size(), 0); - EXPECT_TRUE( sl.empty() ); + EXPECT_TRUE(sl.empty()); } -TEST( StringList, Algorithm ) +TEST(StringList, Algorithm) { - pEp::StringList sl( {"Alice", "Bob", "Carol", "Dave", "Eve", "Frank", "George", "Harry"} ); - + pEp::StringList sl({ "Alice", "Bob", "Carol", "Dave", "Eve", "Frank", "George", "Harry" }); + auto qe = std::find(sl.begin(), sl.end(), std::string("Santa Claus")); // not there! - EXPECT_EQ( qe, sl.end() ); + EXPECT_EQ(qe, sl.end()); -// BEWARE: DOES NOT WORK, because find() uses operator== on char* pointers. :-( -// auto q = std::find(sl.begin(), sl.end(), "Eve"); + // BEWARE: DOES NOT WORK, because find() uses operator== on char* pointers. :-( + // auto q = std::find(sl.begin(), sl.end(), "Eve"); auto q = std::find(sl.begin(), sl.end(), std::string("Eve")); - EXPECT_NE( q, sl.end() ); - EXPECT_STREQ( *q, "Eve" ); + EXPECT_NE(q, sl.end()); + EXPECT_STREQ(*q, "Eve"); } -TEST( StringList, Dynamic ) +TEST(StringList, Dynamic) { static const unsigned NumberOfElements = 17; pEp::StringList sl; EXPECT_EQ(sl.size(), 0); - EXPECT_TRUE( sl.empty() ); - + EXPECT_TRUE(sl.empty()); + char buffer[16]; - for(unsigned u=0; u il{ SP{"key0", "value0"}, SP{"key1", "value1"} }; - pEp::StringPairList spl( il ); - EXPECT_EQ( spl.size(), 2); - + const std::initializer_list il{ SP{ "key0", "value0" }, SP{ "key1", "value1" } }; + pEp::StringPairList spl(il); + EXPECT_EQ(spl.size(), 2); + spl.clear(); EXPECT_EQ(spl.size(), 0); - EXPECT_TRUE( spl.empty() ); + EXPECT_TRUE(spl.empty()); } -TEST( StringPair, Dynamic ) +TEST(StringPair, Dynamic) { static const unsigned NumberOfElements = 17; char key[16]; char value[16]; - + pEp::StringPairList spl; EXPECT_EQ(spl.size(), 0); - EXPECT_TRUE( spl.empty() ); - - for(unsigned u=0; ukey, key)==0; }; - + auto find_by_key = [&key](const ::stringpair_t* sp) { return strcmp(sp->key, key) == 0; }; + // delete random elements. - for(unsigned u=0; ukey, key); + for (unsigned u = 0; u < NumberOfElements; ++u) { + EXPECT_EQ(spl.size(), NumberOfElements - u); + snprintf(key, 15, "k%u", (u * 7) % NumberOfElements); // permutate keys order + auto q = std::find_if(spl.begin(), spl.end(), find_by_key); + + ASSERT_NE(q, spl.end()); // element with key is found + EXPECT_STREQ(q->key, key); spl.erase(q); - - q = std::find_if( spl.begin(), spl.end(), find_by_key ); - EXPECT_EQ( q, spl.end() ); // element with that key is no longer found + + q = std::find_if(spl.begin(), spl.end(), find_by_key); + EXPECT_EQ(q, spl.end()); // element with that key is no longer found } }