diff --git a/.gitignore b/.gitignore index 2abfab1..aa7d5bc 100644 --- a/.gitignore +++ b/.gitignore @@ -15,25 +15,12 @@ build/ build-windows/Debug/ build-windows/Release/ build-windows/libpEpAdapter.vcxproj.user -/test/test_adapter.dSYM/Contents/Info.plist -/test/test_adapter_cxx.dSYM/Contents/Info.plist -/test/test_ensure_passphrase.dSYM/Contents/Info.plist -/test/test_leave_device_group.dSYM/Contents/Info.plist -/test/test_library.dSYM/Contents/Info.plist -/test/test_message_cache.dSYM/Contents/Info.plist -/test/test_passphrase_cache.dSYM/Contents/Info.plist -/test/test_semaphore.dSYM/Contents/Info.plist -/test/test_adapter_cxx.dSYM/Contents/Resources/DWARF/test_adapter_cxx -/test/test_adapter_cxx -/test/test_ensure_passphrase.dSYM/Contents/Resources/DWARF/test_ensure_passphrase -/test/test_ensure_passphrase -/test/test_leave_device_group.dSYM/Contents/Resources/DWARF/test_leave_device_group -/test/test_leave_device_group -/test/test_library.dSYM/Contents/Resources/DWARF/test_library -/test/test_library -/test/test_message_cache.dSYM/Contents/Resources/DWARF/test_message_cache -/test/test_message_cache -/test/test_passphrase_cache.dSYM/Contents/Resources/DWARF/test_passphrase_cache -/test/test_passphrase_cache -/test/test_semaphore.dSYM/Contents/Resources/DWARF/test_semaphore -/test/test_semaphore +*.dSYM +test_group +test_adapter_cxx +test_ensure_passphrase +test_leave_device_group +test_library +test_message_cache +test_passphrase_cache +test_semaphore diff --git a/Makefile.conf b/Makefile.conf index ad57f57..bdb0226 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -7,16 +7,18 @@ HERE:=$(dir $(lastword $(MAKEFILE_LIST))) TARGET=libpEpAdapter.a +# Build config # Defaults DEBUG=1 PREFIX?=$(HOME) -ENGINE_LIB_PATH=$(PREFIX)/lib -ENGINE_INC_PATH=$(PREFIX)/include -CXXFLAGS+=-std=c++14 -fPIC +# Overrides +-include $(HERE)local.conf -# Build target -BUILD_FOR:=$(shell uname) +# Constants +CXXFLAGS+=-std=c++11 -fPIC +CXXFLAGS+=-I$(PREFIX)/include +LDFLAGS+=-L$(PREFIX)/lib ifneq (,$(findstring g++,$(CXX))) CXXFLAGS+=-fdiagnostics-color=always @@ -24,27 +26,12 @@ else ifneq (,$(findstring clang,$(CXX))) CXXFLAGS+=-fcolor-diagnostics endif - -######### Overrides ######### --include $(HERE)local.conf - ifeq ($(DEBUG),1) CXXFLAGS+=-g -O0 else CXXFLAGS+=-DNDEBUG=1 -O3 endif -# Add -L Prefixes to LIB/INC paths, -# if not already explicitly set in local.conf -ifndef ENGINE_LIB - ENGINE_LIB=-L$(ENGINE_LIB_PATH) -endif -ifndef ENGINE_INC - ENGINE_INC=-I$(ENGINE_INC_PATH) -endif - -CXXFLAGS += $(ENGINE_INC) - ifndef ENGINE_TEST ENGINE_TEST = \"$(HOME)/dev/pEpEngine/test\" endif diff --git a/src/Makefile b/src/Makefile index 2b3b74b..1efb480 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ include ../Makefile.conf SOURCE=$(wildcard *.cc) -HEADERS=$(wildcard *.hh *.hxx) +HEADERS=$(wildcard *.hh *.hxx *.h) OBJECTS=$(subst .cc,.o,$(SOURCE)) DEPENDS=$(subst .cc,.d,$(SOURCE)) CXXFLAGS+= -MMD -MP @@ -15,7 +15,8 @@ ifneq ($(MAKECMDGOALS),clean) -include $(DEPENDS) endif -.PHONY: install uninstall clean +.PHONY: all install uninstall clean +.DEFAULT_GOAL := all all: $(TARGET) diff --git a/src/adapter_group.cc b/src/adapter_group.cc new file mode 100644 index 0000000..3c96ff0 --- /dev/null +++ b/src/adapter_group.cc @@ -0,0 +1,96 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt +#include + +#include "adapter_group.h" +#include "pEpLog.hh" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************************* +* Group management functions +*************************************************************************************************/ + +DYNAMIC_API PEP_STATUS adapter_group_create( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *manager, + identity_list *memberlist, + pEp_group **group) +{ + pEpLog("called"); + return ::group_create(session, group_identity, manager, memberlist, group); +} + +DYNAMIC_API PEP_STATUS +adapter_group_join(PEP_SESSION session, pEp_identity *group_identity, pEp_identity *as_member) +{ + pEpLog("called"); + return ::group_join(session, group_identity, as_member); +} + +DYNAMIC_API PEP_STATUS +adapter_group_dissolve(PEP_SESSION session, pEp_identity *group_identity, pEp_identity *manager) +{ + pEpLog("called"); + return ::group_dissolve(session, group_identity, manager); +} + +DYNAMIC_API PEP_STATUS adapter_group_invite_member( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *group_member) +{ + pEpLog("called"); + return ::group_invite_member(session, group_identity, group_member); +} + +PEP_STATUS adapter_group_remove_member( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *group_member) +{ + pEpLog("called"); + return ::group_remove_member(session, group_identity, group_member); +} + +DYNAMIC_API PEP_STATUS adapter_group_rating( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *manager, + PEP_rating *rating) +{ + pEpLog("called"); + return ::group_rating(session, group_identity, manager, rating); +} + +/************************************************************************************************* + * Group query functions + *************************************************************************************************/ + + +//DYNAMIC_API PEP_STATUS group_query_groups(PEP_SESSION session, identity_list **groups) +//{ +// pEpLog("called"); +// return PEP_STATUS_OK; +//} +// +//DYNAMIC_API PEP_STATUS +//group_query_manager(PEP_SESSION session, const pEp_identity *const group, pEp_identity **manager) +//{ +// pEpLog("called"); +// return PEP_STATUS_OK; +//} +// +//DYNAMIC_API PEP_STATUS +//group_query_members(PEP_SESSION session, const pEp_identity *const group, identity_list **members) +//{ +// pEpLog("called"); +// return PEP_STATUS_OK; +//} + +#ifdef __cplusplus +} +#endif diff --git a/src/adapter_group.h b/src/adapter_group.h new file mode 100644 index 0000000..e11a046 --- /dev/null +++ b/src/adapter_group.h @@ -0,0 +1,276 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#ifndef LIBPEPADAPTER_GROUP_HH +#define LIBPEPADAPTER_GROUP_HH + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************************************* + * Group management functions + *************************************************************************************************/ + +/** + * + * + * @brief Create a group in the database with the input group_identity and manager and invite new members to the group + * if this is an own group (for the external API, this is always the case). + * + * This function sets up the actual database structures for a group and invites new members to the group. + * + * For the external API, it is used when creating an own group. The group is represented by the + * incoming group_identity, which contains the user_id and address for the group. + * If no key is present for the former, it will be generated - if there is already + * a default key for the group_identity in the database, that will be used instead. + * The manager + * + * @param[in] session associated session object + * @param[in,out] group_identity the pEp_identity object representing the group. Must contain at least + * a user_id and address + * @param[in,out] manager the pEp_identity object representing the group's manager. Must contain + * a user_id and address, and there must be a default key for the manager + * present in the database + * @param[in,out] member_ident_list list of group member identities + * @param[in,out] group Optional reference for pointer to group object + * representing the created group. + * (When input is NULL, no object is created) + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership All input values stay with the caller + * + * @warning starts a DB transaction - do not call from within a function which + * is already in the middle of another one. + * + * @note in,out fields are labelled as such because they get updated by update_identity()/myself() + * and have group flags added. group_identity may have its user_id freed and replaced + * with the canonical own user id. + * + */ +DYNAMIC_API PEP_STATUS adapter_group_create( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *manager, + identity_list *memberlist, + pEp_group **group +); + + +/** + * + * + * @brief Join a group for which we have received an invitation, marking + * our own membership in the database for the group and sending the manager + * a confirmation of the acceptance of the invitation + * + * @param[in] session associated session object + * @param[in] group_identity the pEp_identity object representing the group. Must contain at least + * a user_id and address + * @param[in] as_member the pEp_identity object representing the own identity we want to use to + * join the group. This must match the identity which was invited to the group. + * Must contain a user_id and address. + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership FIXME + * + * + */ +DYNAMIC_API PEP_STATUS adapter_group_join( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *as_member +); + +/** + * + * + * @brief Dissolve a group, revoke its key, notify all members of the dissolution and + * revocation, and mark the group as inactive in the database + * + * @param[in] session associated session object + * @param[in] group_identity the pEp_identity object representing the group. Must contain at least + * a user_id and address + * @param[in] manager the pEp_identity object representing the group's manager. Must contain + * a user_id and address, and there must be a default key for the manager + * present in the database + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership FIXME + * + * @warning For recipients to accept the dissolution, the sender/manager key used must be a key that they + * have a trust entry for. + */ +DYNAMIC_API PEP_STATUS adapter_group_dissolve( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *manager +); + +/** + * + * + * @brief Invite a member to an extant group, marking the member as invited in the database and + * sending out an invitation to said member + * + * @param[in] session associated session object + * @param[in] group_identity the pEp_identity object representing the group. Must contain at least + * a user_id and address + * @param[in] group_member the pEp_identity object representing the member to invite. Must contain + * a user_id and address, and there must be a default key for the member + * present in the database + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership FIXME + * + * @note This generates a GroupCreate message even though the group already exists - this is because + * this is the accepted message format for invitations to potential members + * + */ +DYNAMIC_API PEP_STATUS adapter_group_invite_member( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *group_member +); + +/** + * + * + * @brief Remove a member from a group, deleting the member from the member list and executing a key + * reset on the group identity + * + * @param[in] session associated session object + * @param[in] group_identity the pEp_identity object representing the group. Must contain at least + * a user_id and address + * @param[in] group_member the pEp_identity object representing the member to remove. Must contain + * a user_id and address + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership FIXME + * + * @todo Revamp implementation and execute key reset + * + */ +PEP_STATUS adapter_group_remove_member( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *group_member +); + +/** + * + * + * @brief Get the rating for this group - if the caller is the manager, this will return the aggregate rating + * of group members. For members, this will return the rating of the group_identity + * + * @param[in] session associated session object + * @param[in] group_identity the pEp_identity object representing the group. Must contain at least + * a user_id and address + * @param[in] manager the pEp_identity object representing the member to remove. Must contain + * a user_id and address + * @param[out] rating the group rating + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership FIXME + * + */ +DYNAMIC_API PEP_STATUS adapter_group_rating( + PEP_SESSION session, + pEp_identity *group_identity, + pEp_identity *manager, + PEP_rating *rating +); + + + +/************************************************************************************************* + * Group query functions + *************************************************************************************************/ + +/** + * + * + * @brief queries the list manager which groups currently exist. + * + * @param[in] session associated session object + * @param[out] groups list of pEp_identity representing + * all group identities that currently exist. + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership ownership of all parameters goes to the caller + * + */ + +//DYNAMIC_API PEP_STATUS group_query_groups( +// PEP_SESSION session, +// identity_list **groups +//); + +/** + * + * + * @brief queries the list manager for the group manager of a given group. + * + * @param[in] session associated session object + * @param[in] group pEp_Identity representing the group identity in question + * @param[out] manager pEp_identity representing the group manager for "group" + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership ownership of all parameters goes to the caller + * + */ + +//DYNAMIC_API PEP_STATUS group_query_manager( +// PEP_SESSION session, +// const pEp_identity *const group, +// pEp_identity **manager +//); + +/** + * + * + * @brief queries the list manager for all members of a given group. + * + * @param[in] session associated session object + * @param[in] group pEp_Identity representing the group identity in question + * @param[out] members list of pEp_identity representing all the members of "group" + * + * @retval PEP_STATUS_OK on success + * error on failure + * + * @ownership ownership of all parameters goes to the caller + * + */ + +//DYNAMIC_API PEP_STATUS group_query_members( +// PEP_SESSION session, +// const pEp_identity *const group, +// identity_list **members +//); + + +#ifdef __cplusplus +}; +#endif + +#endif //LIBPEPADAPTER_GROUP_HH \ No newline at end of file diff --git a/test/Makefile b/test/Makefile index 7f6045f..759c5cc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,23 +1,41 @@ include ../Makefile.conf -LDFLAGS=-L../src $(ENGINE_LIB) +LDFLAGS:=-L../src $(LDFLAGS) LDLIBS=-lstdc++ -lpEpEngine -lpEpAdapter CXXFLAGS:=-I../src -DENGINE_TEST=$(ENGINE_TEST) $(CXXFLAGS) -SRC=$(wildcard test_*.cc) -TST=$(subst .cc,,$(SRC)) -all: $(TST) +# Test +SRC_TEST=$(wildcard test_*.cc) +BIN_TEST=$(subst .cc,,$(SRC_TEST)) -$(TST): framework.o +# Framework +SRC_FRAMEWORK=$(wildcard framework/*.cc) +OBJ_FRAMEWORK=$(subst .cc,.o,$(SRC_FRAMEWORK)) -.PHONY: clean rmtestdata +# Depends +#DEP_TEST=$(subst .cc,.d,$(SRC_TEST)) +#DEP_FRAMEWORK=$(subst .cc,.d,$(SRC_FRAMEWORK)) +#DEPENDS+=$(DEP_TEST)$(DEP_FRAMEWORK) +#CXXFLAGS+= -MMD -MP +# +#ifneq ($(MAKECMDGOALS),clean) +# -include $(DEPENDS) +#endif + +.PHONY: all clean rmtestdata +.DEFAULT_GOAL := all + +all: $(BIN_TEST) + +$(BIN_TEST): $(OBJ_FRAMEWORK) clean: - rm -f $(TST) + rm -f $(BIN_TEST) + rm -f $(OBJ_FRAMEWORK) rm -Rf *.dSYM + rm -f *.d rm -f *.o rm -Rf /tmp/test_pEp.* rmtestdata: rm -Rf /tmp/test_pEp.* - diff --git a/test/framework.cc b/test/framework/framework.cc similarity index 91% rename from test/framework.cc rename to test/framework/framework.cc index 70bb0a1..51b1618 100644 --- a/test/framework.cc +++ b/test/framework/framework.cc @@ -8,7 +8,6 @@ #include #include #include - #include #include #include @@ -22,16 +21,17 @@ #include #include -#include +#include "../../src/Adapter.hh" pEp::Test::Transport pEp::Test::transport; std::string pEp::Test::path; extern std::thread pEp::Adapter::_sync_thread; +using namespace pEp; +using namespace std; + namespace pEp { namespace Test { - using namespace Adapter; - void setup(vector &args) { #ifdef WIN32 @@ -74,8 +74,9 @@ namespace pEp { void setup(int argc, char **argv) { vector args{ (size_t)argc }; - for (int i = 0; i < argc; ++i) + for (int i = 0; i < argc; ++i) { args[i] = argv[i]; + } setup(args); } @@ -87,7 +88,7 @@ namespace pEp { ::identity_list *il = NULL; cout << key.c_str() << endl; cout << key.length() << endl; - ::PEP_STATUS status = ::import_key(session(), key.c_str(), key.length(), &il); + ::PEP_STATUS status = ::import_key(Adapter::session(), key.c_str(), key.length(), &il); throw_status(status); assert(status == PEP_KEY_IMPORTED); ::free_identity_list(il); @@ -134,7 +135,7 @@ namespace pEp { stringlist_t *keylist; ::PEP_rating rating; ::PEP_decrypt_flags_t flags = 0; - ::PEP_STATUS status = ::decrypt_message(session(), msg.get(), &_dst, &keylist, &rating, &flags); + ::PEP_STATUS status = ::decrypt_message(Adapter::session(), msg.get(), &_dst, &keylist, &rating, &flags); throw_status(status); Message dst; @@ -168,8 +169,9 @@ namespace pEp { void join_sync_thread() { - if (_sync_thread.joinable()) - _sync_thread.join(); + if (Adapter::_sync_thread.joinable()) { + Adapter::_sync_thread.join(); + } } Message Transport::recv() diff --git a/test/framework.hh b/test/framework/framework.hh similarity index 70% rename from test/framework.hh rename to test/framework/framework.hh index 9b04a6b..1bc3a37 100644 --- a/test/framework.hh +++ b/test/framework/framework.hh @@ -12,18 +12,16 @@ namespace pEp { namespace Test { - using namespace std; - // manually set up test - void setup(vector &args); + void setup(std::vector &args); // call this in main() for auto set up void setup(int argc = 1, char **argv = nullptr); - void import_key_from_file(string filename); + void import_key_from_file(std::string filename); - using Message = shared_ptr<::message>; - using Identity = shared_ptr<::pEp_identity>; + using Message = std::shared_ptr<::message>; + using Identity = std::shared_ptr<::pEp_identity>; // use this instead of constructor to auto assign ::free_message as // deleter @@ -34,20 +32,20 @@ namespace pEp { Identity make_identity(::pEp_identity *ident); // MIME parser - Message mime_parse(string text); + Message mime_parse(std::string text); // MIME composer - string mime_compose(Message msg); + std::string mime_compose(Message msg); // Sync and Distribution decoder - string make_pEp_msg(Message msg); + std::string make_pEp_msg(Message msg); // wait until Sync has shut down void join_sync_thread(); struct Transport { - string inbox_path = "inbox"; - string outbox_path = "outbox"; + std::string inbox_path = "inbox"; + std::string outbox_path = "outbox"; // reads next message from inbox Message recv(); @@ -57,7 +55,7 @@ namespace pEp { }; extern Transport transport; - extern string path; + extern std::string path; }; // namespace Test }; // namespace pEp diff --git a/test/framework/utils.cc b/test/framework/utils.cc new file mode 100644 index 0000000..c9df5e7 --- /dev/null +++ b/test/framework/utils.cc @@ -0,0 +1,165 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "utils.hh" + +#include + +#include + +#include "../../src/Adapter.hh" +#include "../../src/adapter_group.h" + +using namespace std; +using namespace pEp; + +namespace pEp { + namespace Test { + namespace Log { + void logH1(string msg) + { + char decoration{ '=' }; + cout << endl + << endl + << std::string(30, decoration) << ' ' << msg << ' ' + << std::string(30, decoration) << endl; + } + + void logH2(string msg) + { + char decoration{ '-' }; + cout << endl + << std::string(10, decoration) << ' ' << msg << ' ' + << std::string(10, decoration) << endl; + } + } // namespace Log + + namespace Utils { + string identity_to_string(::pEp_identity* ident, bool full, int indent) + { + + stringstream builder; + if (ident != nullptr) { + if (full) { + builder << endl; + builder << std::string(indent, '\t') << "{" << endl; + indent++; + builder << std::string(indent, '\t') << "address: " + << (ident->address != nullptr ? ident->address : "NULL") << endl; + builder << std::string(indent, '\t') << "user_id: " + << (ident->user_id != nullptr ? ident->user_id : "NULL") << endl; + builder << std::string(indent, '\t') << "username: " + << (ident->username != nullptr ? ident->username : "NULL") << endl; + builder << std::string(indent, '\t') + << "fpr: " << (ident->fpr != nullptr ? ident->fpr : "NULL") << endl; + builder << std::string(indent, '\t') << "comm_type: " << ident->comm_type + << endl; + builder << std::string(indent, '\t') + << "lang: " << static_cast(ident->lang) << endl; + builder << std::string(indent, '\t') << "me: " << ident->me << endl; + builder << std::string(indent, '\t') << "major_ver: " << ident->major_ver + << endl; + builder << std::string(indent, '\t') << "minor_ver: " << ident->minor_ver + << endl; + builder << std::string(indent, '\t') << "enc_format: " << ident->enc_format + << endl; + builder << std::string(indent, '\t') << "flags: " << ident->flags << endl; + indent--; + builder << std::string(indent, '\t') << "}"; + } else { + builder << "{ " << (ident->address != nullptr ? ident->address : "NULL") + << "/" << (ident->user_id != nullptr ? ident->user_id : "NULL") + << "/" << (ident->username != nullptr ? ident->username : "NULL") + << "/" << (ident->fpr != nullptr ? ident->fpr : "NULL") << " }"; + } + } else { + builder << "NULL"; + } + + return builder.str(); + } + + std::string identitylist_to_string(::identity_list* idl, bool full, int indent) + { + stringstream builder; + if (idl != nullptr) { + builder << endl; + builder << std::string(indent, '\t') << "[" << endl; + indent++; + for (::identity_list* curr = idl; curr != nullptr; curr = curr->next) { + builder << identity_to_string(curr->ident, full, indent) << endl; + } + indent--; + builder << std::string(indent, '\t') << "]"; + } else { + builder << "NULL"; + } + + return builder.str(); + } + + string member_to_string(::pEp_member* member, bool full, int indent) + { + stringstream builder; + if (member != nullptr) { + builder << std::string(indent, '\t') << "{" << endl; + indent++; + builder << std::string(indent, '\t') + << "ident: " << identity_to_string(member->ident, full, indent) << endl; + builder << std::string(indent, '\t') << "joined: " << member->joined << endl; + indent--; + builder << std::string(indent, '\t') << "}"; + } else { + builder << "NULL"; + } + + return builder.str(); + } + + string memberlist_to_string(::member_list* mbl, bool full, int indent) + { + stringstream builder; + if (mbl != nullptr) { + builder << endl; + builder << std::string(indent, '\t') << "[" << endl; + indent++; + for (member_list* curr_member = mbl; curr_member != nullptr; + curr_member = curr_member->next) { + builder << member_to_string(curr_member->member, full, indent) << endl; + } + indent--; + builder << std::string(indent, '\t') << "]"; + } else { + builder << "NULL"; + } + + return builder.str(); + } + + string group_to_string(::pEp_group* group, bool full, int indent) + { + stringstream builder; + if (group != nullptr) { + builder << endl; + builder << std::string(indent, '\t') << "{" << endl; + indent++; + builder << std::string(indent, '\t') << "group_identity: " + << identity_to_string(group->group_identity, full, indent) << endl; + builder << std::string(indent, '\t') + << "manager: " << identity_to_string(group->manager, full, indent) + << endl; + builder << std::string(indent, '\t') << "active: " << group->active << endl; + builder << std::string(indent, '\t') + << "members: " << memberlist_to_string(group->members, full, indent) + << endl; + indent--; + builder << std::string(indent, '\t') << "]"; + } else { + builder << "NULL"; + } + + return builder.str(); + } + } // namespace Utils + } // namespace Test +} // namespace pEp diff --git a/test/framework/utils.hh b/test/framework/utils.hh new file mode 100644 index 0000000..ccbc7a9 --- /dev/null +++ b/test/framework/utils.hh @@ -0,0 +1,27 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#ifndef LIBPEPADAPTER_UTILS_HH +#define LIBPEPADAPTER_UTILS_HH + +#include +#include +#include +#include + +namespace pEp { + namespace Test { + namespace Log { + void logH1(std::string msg); + void logH2(std::string msg); + } + namespace Utils { + std::string identity_to_string(::pEp_identity* ident, bool full = true, int indent = 0); + std::string identitylist_to_string(::identity_list * idl, bool full = true, int indent = 0); + std::string member_to_string(::pEp_member* member, bool full = true, int indent = 0); + std::string memberlist_to_string(::member_list* mbl, bool full = true, int indent = 0); + std::string group_to_string(::pEp_group* group, bool full = true, int indent = 0); + } + } // namespace Test +} // namespace pEp +#endif \ No newline at end of file diff --git a/test/test_adapter.cc b/test/test_adapter.cc index ee0bd5e..b0e8954 100644 --- a/test/test_adapter.cc +++ b/test/test_adapter.cc @@ -1,18 +1,19 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt -#include "framework.hh" +#include "framework/framework.hh" #include #include #include #include -#include -#include #include #include #include +#include "../src/pEpLog.hh" +#include "../src/Adapter.hh" + using namespace std; using namespace pEp; diff --git a/test/test_adapter_cxx.cc b/test/test_adapter_cxx.cc index 9091abf..758c894 100644 --- a/test/test_adapter_cxx.cc +++ b/test/test_adapter_cxx.cc @@ -1,16 +1,16 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt -#include "framework.hh" +#include "framework/framework.hh" #include #include #include #include -#include #include -#include +#include "../src/Adapter.hh" +#include "../src/pEpLog.hh" using namespace pEp; diff --git a/test/test_ensure_passphrase.cc b/test/test_ensure_passphrase.cc index a4cfa9f..c1cda6d 100644 --- a/test/test_ensure_passphrase.cc +++ b/test/test_ensure_passphrase.cc @@ -1,6 +1,8 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt +#include "framework/framework.hh" + #include #include #include @@ -10,16 +12,14 @@ #include #include -#include "framework.hh" - -#include -#include -#include - #include #include #include +#include "../src/passphrase_cache.hh" +#include "../src/status_to_string.hh" +#include "../src/Adapter.hh" + using namespace pEp; using namespace std; diff --git a/test/test_group.cc b/test/test_group.cc new file mode 100644 index 0000000..b9bc917 --- /dev/null +++ b/test/test_group.cc @@ -0,0 +1,221 @@ +// This file is under GNU General Public License 3.0 +// see LICENSE.txt + +#include "framework/framework.hh" +#include "framework/utils.hh" + +#include + +#include "../src/Adapter.hh" +#include "../src/adapter_group.h" +#include "../src/status_to_string.hh" + +using namespace std; +using namespace pEp; +using namespace pEp::Test::Log; + +bool debug_info_full = true; +::pEp_identity* alice = nullptr; +::pEp_identity* bob = nullptr; +::pEp_identity* carol = nullptr; +::pEp_identity* grp_ident = nullptr; +::PEP_STATUS status; + +/* + * Callbacks + */ + +::PEP_STATUS test_messageToSend(::message* _msg) +{ + cout << "called" << endl; + cout << Test::make_pEp_msg(Test::make_message(_msg)); + return PEP_STATUS_OK; +} + +::PEP_STATUS test_notifyHandshake(::pEp_identity* _me, ::pEp_identity* _partner, sync_handshake_signal signal) +{ + cout << "called" << endl; + cout << "me: " << Test::Utils::identity_to_string(_me, false) << endl; + cout << "partner: " << Test::Utils::identity_to_string(_partner, false) << endl; + cout << "Signal: " << signal << endl; + + return PEP_STATUS_OK; +} + +/* + * Test Units + */ + +void test_create_alice_me() +{ + logH2("test_create_alice_me"); + alice = ::new_identity("alice@peptest.ch", NULL, "23", "Alice"); + assert(alice); + alice->lang[0] = 'e'; + alice->lang[1] = 'n'; + status = ::myself(Adapter::session(), alice); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); + cout << "Alice:" << Test::Utils::identity_to_string(alice, debug_info_full) << endl; +} + +void test_create_bob_partner() +{ + logH2("test_create_bob_partner"); + bob = ::new_identity("bob@peptest.ch", NULL, PEP_OWN_USERID, "Bob"); + assert(bob); + bob->lang[0] = 'c'; + bob->lang[1] = 'r'; + status = ::update_identity(Adapter::session(), bob); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); + cout << "Bob:" << Test::Utils::identity_to_string(bob, debug_info_full) << endl; +} + +void test_create_carol_partner() +{ + logH2("test_create_carol_partner"); + carol = ::new_identity("carol@peptest.ch", NULL, PEP_OWN_USERID, "Carol"); + assert(carol); + carol->lang[0] = 'f'; + carol->lang[1] = 'n'; + status = ::update_identity(Adapter::session(), carol); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); + cout << "Carol:" << Test::Utils::identity_to_string(carol, debug_info_full) << endl; +} + +void test_setup_and_start_sync() +{ + logH2("test_setup_and_start_sync"); + Adapter::sync_initialize(Adapter::SyncModes::Async, &test_messageToSend, &test_notifyHandshake, false); +} + +void test_group_create(::identity_list* idl) +{ + logH2("test_group_create"); + cout << "IDL: " << Test::Utils::identitylist_to_string(idl, debug_info_full) << endl; + + cout << "create group identity" << endl; + grp_ident = ::new_identity("group1@peptest.ch", NULL, "432", "group1"); + assert(grp_ident); + status = ::myself(Adapter::session(), grp_ident); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); + cout << "grp_ident:" << Test::Utils::identity_to_string(grp_ident, debug_info_full) << endl; + + cout << "adapter_group_create()" << endl; + ::pEp_group* pep_grp1 = nullptr; + status = ::adapter_group_create(Adapter::session(), grp_ident, alice, idl, &pep_grp1); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); + assert(pep_grp1); + cout << "GRP: " << Test::Utils::group_to_string(pep_grp1, debug_info_full) << endl; +} + +void test_group_invite_member(::pEp_identity* ident) +{ + logH2("test_group_invite_member"); + status = ::adapter_group_invite_member(Adapter::session(), grp_ident, ident); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); +} + +void test_group_join(::pEp_identity* ident) +{ + logH2("test_group_join"); + status = ::adapter_group_join(Adapter::session(), grp_ident, ident); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); +} + +void test_group_remove_member(::pEp_identity* ident) +{ + logH2("test_group_remove_member"); + status = ::adapter_group_remove_member(Adapter::session(), grp_ident, ident); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); +} + +void test_group_rating() +{ + logH2("test_group_rating"); + // Rating + ::PEP_rating* rating = nullptr; + cout << "adapter_group_rating()" << endl; + status = ::group_rating(Adapter::session(), grp_ident, alice, rating); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); + cout << "Rating: " << rating << endl; +} + +void test_group_dissolve() +{ + logH2("test_group_dissolve"); + status = ::adapter_group_dissolve(Adapter::session(), grp_ident, alice); + cout << "STATUS: " << status_to_string(status) << endl; + assert(!status); +} + +/* + * Update functions + * ---------------- + * Test procedure: + * 1. Create group + * - group_create(Alice) + * 2. Add Bob + * - group_invite_member(Bob) + * - group_join(Bob) + * 3. Add Carol + * - group_invite_member(Carol) + * - group_join(Carol) + * 4. Remove Carol + * - group_remove_member(Carol) + * 5. Rating + * - group_rating() (Just test once, to see it is generally working) + * 6. Dissolve + * - group_dissolve() + * + * Query functions + * --------------- + * Always test all the query functions for correctness between every step above. + * group_query_groups() + * group_query_manager() + * group_query_members + */ + + +int main(int argc, char** argv) +{ + Test::setup(argc, argv); + Adapter::pEpLog::set_enabled(false); + debug_info_full = true; + + // Setup Test Context + test_create_alice_me(); + test_create_bob_partner(); + test_create_carol_partner(); + test_setup_and_start_sync(); + + + logH1("1. Create group"); + ::identity_list* initial_memberlist = nullptr; + initial_memberlist = new_identity_list(bob); + ::identity_list_add(initial_memberlist, carol); + test_group_create(initial_memberlist); + logH1("2. Add Bob"); + // test_group_invite_member(bob); // Fails + // test_group_join(bob); // Fails + logH1("3. Add Carol"); + // test_group_invite_member(carol); + // test_group_join(carol); + logH1("4. Remove Carol"); + // test_group_remove_member(carol); + logH1("5. Rating"); + // test_group_rating(); // Failing + logH1("6. Dissolve"); + test_group_dissolve(); + + Adapter::shutdown(); + return 0; +} diff --git a/test/test_leave_device_group.cc b/test/test_leave_device_group.cc index 33bdac5..6cfcf71 100644 --- a/test/test_leave_device_group.cc +++ b/test/test_leave_device_group.cc @@ -1,16 +1,17 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt +#include "framework/framework.hh" + #include #include #include -#include "framework.hh" -#include -#include - #include +#include "../src/callback_dispatcher.hh" +#include "../src/passphrase_cache.hh" + using namespace std; using namespace pEp; diff --git a/test/test_message_cache.cc b/test/test_message_cache.cc index 6c35b1b..fc240f9 100644 --- a/test/test_message_cache.cc +++ b/test/test_message_cache.cc @@ -1,13 +1,15 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt -#include "framework.hh" +#include "framework/framework.hh" + #include #include #include #include -#include -#include + +#include "../src/message_cache.hh" +#include "../src/Adapter.hh" using namespace std; using namespace pEp; diff --git a/test/test_passphrase_cache.cc b/test/test_passphrase_cache.cc index 32ca34e..016ea84 100644 --- a/test/test_passphrase_cache.cc +++ b/test/test_passphrase_cache.cc @@ -1,16 +1,16 @@ // This file is under GNU General Public License 3.0 // see LICENSE.txt -#include "framework.hh" +#include "framework/framework.hh" #include #include #include - #include -#include -#include -#include + +#include "../src/passphrase_cache.hh" +#include "../src/status_to_string.hh" +#include "../src/Adapter.hh" using namespace pEp; diff --git a/test/test_semaphore.cc b/test/test_semaphore.cc index 55196b6..1a5eafb 100644 --- a/test/test_semaphore.cc +++ b/test/test_semaphore.cc @@ -4,7 +4,8 @@ #include #include #include -#include "Semaphore.hh" + +#include "../src/Semaphore.hh" using namespace std; using namespace pEp;