Introduce gtest

(Mostly copied from libpEpAdapter)
master
Gernot Kranz 2 weeks ago
parent b1ec67877a
commit 68b28e6cfd

@ -10,10 +10,12 @@ src-debug:
test: src-debug
$(MAKE) -C test
$(MAKE) -C test-suite
clean:
$(MAKE) -C src clean
$(MAKE) -C test clean
$(MAKE) -C test-suite clean
install:
$(MAKE) -C src install

@ -30,15 +30,25 @@ CFLAGS+=-std=c17 -fPIC
# Constants
CFLAGS+=-I$(PREFIX)/include
LDFLAGS+=-L$(PREFIX)/lib
CFLAGS+=-I$(SYS_PREFIX)/include
CFLAGS+=-fPIC -pthread -DSQLITE_THREADSAFE=1
LDFLAGS+=-L$(PREFIX)/lib
LDFLAGS+=-L$(SYS_PREFIX)/lib
CXXFLAGS+=-std=c++11 -fPIC
CXXFLAGS+=-Wall -pedantic-errors -Wno-unused-parameter -Wno-reorder-ctor
CXXFLAGS+=-isystem $(PREFIX)/include
ifneq (,$(findstring g++,$(CC)))
CFLAGS+=-fdiagnostics-color=always
else ifneq (,$(findstring clang,$(CC)))
CFLAGS+=-fcolor-diagnostics
endif
ifeq ($(DEBUG),1)
CXXFLAGS+=-g -O0
CFLAGS+=-g -O0
else
CXXFLAGS+=-DNDEBUG=1 -O3
CFLAGS+=-DNDEBUG=1 -O3
endif

@ -1,6 +1,10 @@
#ifndef PEPUDPTRANSPORT_H
#define PEPUDPTRANSPORT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <errno.h>
#include <signal.h>
#include <stdio.h>
@ -53,4 +57,7 @@ signal_incoming_message_t cb_incoming_message;
bool allCallbacksRegistered();
#ifdef __cplusplus
}
#endif
#endif // PEPUDPTRANSPORT_H

@ -0,0 +1,30 @@
include ../Makefile.conf
LDFLAGS:=-L../src $(LDFLAGS)
LDLIBS=-lstdc++ -lpEpEngine -lpEpAdapter -lpEpCxx11 -lPityTest11 -lpthread -ldl -lm -lpEpTransportUDP
CXXFLAGS:=-I../src -I$(PREFIX)/include $(CXXFLAGS) -Wc++11-extensions
# Test
SRC_TEST=$(wildcard test_*.cc)
BIN_TEST=$(subst .cc,,$(SRC_TEST))
# Framework
SRC_FRAMEWORK=$(wildcard framework/*.cc)
OBJ_FRAMEWORK=$(subst .cc,.o,$(SRC_FRAMEWORK))
.PHONY: all clean
.DEFAULT_GOAL := all
all: $(BIN_TEST)
$(BIN_TEST): $(OBJ_FRAMEWORK)
clean:
rm -f $(BIN_TEST)
rm -f $(OBJ_FRAMEWORK)
rm -Rf *.dSYM
rm -f *.d
rm -f *.o
rm -rf pitytest_data/

@ -0,0 +1,208 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "framework.hh"
#include <iostream>
#include <fstream>
#include <sstream>
#include <utility>
#include <exception>
#include <thread>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sys/param.h>
#include <sys/stat.h>
#include <pEp/pEpLog.hh>
#include <pEp/keymanagement.h>
#include <pEp/mime.h>
#include <pEp/message_api.h>
#include <pEp/sync_codec.h>
#include <pEp/distribution_codec.h>
#include <pEp/Adapter.hh>
pEp::Test::Transport pEp::Test::transport;
using namespace pEp;
namespace pEp {
namespace Test {
std::string per_user_dir{};
std::string resource_dir{};
void setup(std::vector<std::string> &args)
{
std::string dir{};
resource_dir = Utils::path_get_abs("resource/");
#ifdef WIN32
dir = getenv("TEMP");
dir += "\\test_pEp.XXXXXXXXXXXX";
#endif
if (args.size() > 1) {
if (args[1] == "--help") {
#ifdef WIN32
std::cout << "usage: " << args[0] << " [--dir LOCALAPPDATA]" << std::endl;
#else
std::cout << "usage: " << args[0] << " [--dir HOME]" << std::endl;
#endif
exit(0);
} else if (args[1] == "--dir" && args.size() == 3) {
dir = args[2];
} else {
std::cerr << "illegal parameter" << std::endl;
exit(1);
}
}
#ifdef WIN32
char _path[MAXPATHLEN + 1];
const char *templ = dir.c_str();
strcpy(_path, templ);
mkdtemp(_path);
chdir(_path);
setenv("LOCALAPPDATA", _path, 1);
per_user_dir = _path;
#else
dir = Utils::path_get_abs("testdata");
Utils::dir_recreate(dir);
setenv("HOME", dir.c_str(), 1);
Utils::dir_set_cwd(dir);
pEpLog("$HOME set to:" + dir);
per_user_dir = dir;
#endif
std::cerr << "test directory: " << per_user_dir << std::endl;
}
void setup(int argc, char **argv)
{
std::vector<std::string> args{ (size_t)argc };
for (int i = 0; i < argc; ++i) {
args[i] = argv[i];
}
setup(args);
}
std::string get_resource_abs(const std::string &name)
{
return Utils::path_get_abs(resource_dir + name);
}
void import_key_from_file(const std::string &filename)
{
std::string key = Utils::file_read(filename);
// ifstream f(filename, ifstream::in);
// string key{ istreambuf_iterator<char>(f), istreambuf_iterator<char>() };
::identity_list *il = nullptr;
std::cout << key.c_str() << std::endl;
std::cout << key.length() << std::endl;
::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);
}
Message make_message(::message *msg)
{
return std::shared_ptr<::message>(msg, ::free_message);
}
Identity make_identity(::pEp_identity *ident)
{
return std::shared_ptr<::pEp_identity>(ident, ::free_identity);
}
Message mime_parse(std::string text)
{
::message *msg = nullptr;
bool has_possible_pEp_msg = false;
::PEP_STATUS status = ::mime_decode_message(
text.c_str(),
text.length(),
&msg,
&has_possible_pEp_msg);
throw_status(status);
return make_message(msg);
}
std::string mime_compose(Message msg)
{
char *mimetext = nullptr;
PEP_STATUS status = ::mime_encode_message(msg.get(), false, &mimetext, false);
throw_status(status);
std::string text = mimetext;
free(mimetext);
return text;
}
std::string make_pEp_msg(Message msg)
{
std::string text;
::message *_dst = nullptr;
stringlist_t *keylist = nullptr;
::PEP_rating rating{};
::PEP_decrypt_flags_t flags = 0;
::PEP_STATUS status = ::decrypt_message(
Adapter::session(),
msg.get(),
&_dst,
&keylist,
&rating,
&flags);
throw_status(status);
Message dst;
if (_dst) {
dst = make_message(_dst);
} else {
dst = msg;
}
if (dst.get()->attachments) {
for (auto a = dst.get()->attachments; a && a->value; a = a->next) {
if (std::string("application/pEp.sync") == a->mime_type) {
char *_text;
status = ::PER_to_XER_Sync_msg(a->value, a->size, &_text);
throw_status(status);
text += _text;
::pEp_free(_text);
return text;
} else if (std::string("application/pEp.distribution") == a->mime_type) {
char *_text;
status = ::PER_to_XER_Distribution_msg(a->value, a->size, &_text);
throw_status(status);
text += _text;
::pEp_free(_text);
return text;
}
}
}
return text;
}
void join_sync_thread()
{
if (Adapter::_sync_thread.joinable()) {
Adapter::_sync_thread.join();
}
}
Message Transport::recv()
{
mkdir(inbox_path.c_str(), 0770);
auto msg = make_message(nullptr);
return msg;
}
void Transport::send(Message msg)
{
mkdir(outbox_path.c_str(), 0770);
}
} // namespace Test
} // namespace pEp

@ -0,0 +1,64 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#ifndef LIBPEPADAPTER_FRAMEWORK_HH
#define LIBPEPADAPTER_FRAMEWORK_HH
#include <string>
#include <vector>
#include <memory>
#include <pEp/message.h>
namespace pEp {
namespace Test {
// manually set up test
void setup(std::vector<std::string> &args);
// call this in main() for auto set up
void setup(int argc = 1, char **argv = nullptr);
std::string get_resource_abs(const std::string &name);
void import_key_from_file(const std::string& filename);
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
Message make_message(::message *msg);
// use this instead of constructor to auto assign ::free_identity as
// deleter
Identity make_identity(::pEp_identity *ident);
// MIME parser
Message mime_parse(std::string text);
// MIME composer
std::string mime_compose(Message msg);
// Sync and Distribution decoder
std::string make_pEp_msg(Message msg);
// wait until Sync has shut down
void join_sync_thread();
struct Transport {
std::string inbox_path = "inbox";
std::string outbox_path = "outbox";
// reads next message from inbox
Message recv();
// appends message to outbox
void send(Message msg);
};
extern Transport transport;
extern std::string per_user_dir;
} // namespace Test
} // namespace pEp
#endif // LIBPEPADAPTER_FRAMEWORK_HH

@ -0,0 +1,70 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "framework/framework.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <iostream>
#include <cassert>
#include <pEp/utils.hh>
#include <pEp/keymanagement.h>
#include <pEp/sync_api.h>
#include "../src/Adapter.hh"
namespace Utils = pEp::Utils;
using namespace pEp;
PEP_STATUS messageToSend(struct _message *msg)
{
TESTLOG("called");
return PEP_STATUS_OK;
}
PEP_STATUS notifyHandshake(pEp_identity *me, pEp_identity *partner, ::sync_handshake_signal signal)
{
TESTLOG("called");
return PEP_STATUS_OK;
}
class JNISync {
public:
void onSyncStartup()
{
TESTLOG("called");
}
void onSyncShutdown()
{
TESTLOG("called");
}
} o;
int main(int argc, char *argv[])
{
Test::setup(argc, argv);
pEp::Adapter::session
.initialize(pEp::Adapter::SyncModes::Async, false, messageToSend, notifyHandshake);
// Create new identity
TESTLOG("updating or creating identity for me");
::pEp_identity *me = ::new_identity("alice@peptest.ch", NULL, "23", "Who the F* is Alice");
assert(me);
::PEP_STATUS status = ::myself(Adapter::session(), me);
::free_identity(me);
throw_status(status);
// start and stop sync repeatedly
unsigned long long int nrIters = 3;
for (int i = 0; i < nrIters; i++) {
TESTLOG("RUN NR: ");
TESTLOG(i);
TESTLOG("SYNC START");
TESTLOG("starting the adapter including sync");
Adapter::startup<JNISync>(&o, &JNISync::onSyncStartup, &JNISync::onSyncShutdown);
Utils::sleep_millis(2000);
TESTLOG("SYNC STOP");
Adapter::stop_sync();
Utils::sleep_millis(2000);
}
return 0;
}

@ -0,0 +1,51 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "framework/framework.hh"
#include <cassert>
#include <pEp/keymanagement.h>
#include <pEp/key_reset.h>
#include "../src/passphrase_cache.hh"
#include "../src/Adapter.hh"
using namespace pEp;
using namespace std;
int main(int argc, char** argv)
{
pEp::Adapter::pEpLog::set_enabled(true);
Test::setup(argc, argv);
Adapter::session.initialize();
passphrase_cache.add("erwin");
passphrase_cache.add("cathy");
passphrase_cache.add("bob");
std::string bob_filename = Test::get_resource_abs("bob-primary-with-password-bob-subkey-without.pgp");
std::string bob_fpr = "5C76378A62B04CF3F41BEC8D4940FC9FA1878736";
std::string erwin_filename = Test::get_resource_abs("erwin_normal_encrypted.pgp");
std::string erwin_fpr = "CBA968BC01FCEB89F04CCF155C5E9E3F0420A570";
Test::import_key_from_file(bob_filename);
Test::import_key_from_file(erwin_filename);
::pEp_identity* bob = ::new_identity("bob@example.org", bob_fpr.c_str(), "BOB", "Bob Dog");
::PEP_STATUS status = ::set_own_key(Adapter::session(), bob, bob_fpr.c_str());
assert(status == PEP_STATUS_OK);
::pEp_identity* erwin = ::new_identity("erwin@example.org", erwin_fpr.c_str(), "BOB", "Bob is Erwin");
status = ::set_own_key(Adapter::session(), erwin, erwin_fpr.c_str());
assert(status == PEP_STATUS_OK);
status = ::key_reset_all_own_keys(Adapter::session());
assert(status == PEP_STATUS_OK);
::free_identity(bob);
::free_identity(erwin);
// session(Adapter::release);
return 0;
}

@ -0,0 +1,254 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "framework/framework.hh"
#include <pEp/pitytest11/test_utils.hh>
//#include <iostream>
#include "../src/Adapter.hh"
#include "../src/utils.hh"
#include <pEp/std_utils.hh>
#include "../src/grp_manager_interface.hh"
#include "../src/grp_driver_engine.hh"
#include "../src/grp_driver_dummy.hh"
#include "../src/grp_driver_replicator.hh"
//#include "../src/adapter_group.h"
#include "../src/status_to_string.hh"
#include <pEp/pEpEngine.h>
#include <pEp/message_api.h>
using namespace std;
using namespace pEp;
using namespace pEp::Adapter;
using namespace pEp::Adapter::pEpLog;
bool debug_info_full = true;
// Model
const string lmd_path = "test.db";
::pEp_identity* alice = nullptr;
::pEp_identity* bob = nullptr;
::pEp_identity* carol = nullptr;
::pEp_identity* grp_ident = nullptr;
::PEP_STATUS status;
string dummy_in;
GroupUpdateInterface* gu = nullptr;
GroupQueryInterface* gq = nullptr;
/*
* Callbacks
*/
::PEP_STATUS test_messageToSend(::message* _msg)
{
log("called");
log(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)
{
log("called");
log("me: " + pEp::Utils::to_string(_me, false));
log("partner: " + pEp::Utils::to_string(_partner, false));
log("Signal: " + to_string(signal));
// log("Signal: " + string{ ::sync_handshake_signal_to_string(signal) });
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);
log("STATUS: " + status_to_string(status));
assert(!status);
log("Alice:" + pEp::Utils::to_string(alice, debug_info_full));
}
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 = ::myself(Adapter::session(), bob);
status = ::update_identity(Adapter::session(), bob);
log("STATUS: " + status_to_string(status));
assert(!status);
log("Bob:" + pEp::Utils::to_string(bob, debug_info_full));
}
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);
// status = ::myself(Adapter::session(), carol);
log("STATUS: " + status_to_string(status));
assert(!status);
log("Carol:" + pEp::Utils::to_string(carol, debug_info_full));
}
void test_setup_and_start_sync()
{
logH2("test_setup_and_start_sync");
Adapter::start_sync();
}
void test_group_create()
{
logH2("test_group_create");
::identity_list* initial_memberlist = nullptr;
initial_memberlist = new_identity_list(bob);
::identity_list_add(initial_memberlist, carol);
log("create group identity");
grp_ident = ::new_identity("group1@peptest.ch", NULL, "432", "group1");
assert(grp_ident);
log("grp_ident:" + pEp::Utils::to_string(grp_ident, debug_info_full));
// PEP_STATUS stat = ::myself(Adapter::session(), grp_ident);
// log("STATUS: " + status_to_string(status));
// assert(stat == PEP_STATUS_OK);
// log("grp_ident:" + pEp::Utils::to_string(grp_ident, debug_info_full));
log("adapter_group_create()");
status = gu->adapter_group_create(Adapter::session(), grp_ident, alice, nullptr);
log("STATUS: " + status_to_string(status));
assert(!status);
}
void test_group_invite_member(::pEp_identity& ident)
{
logH2("test_group_invite_member");
assert(grp_ident);
status = gu->adapter_group_invite_member(Adapter::session(), grp_ident, &ident);
log("STATUS: " + status_to_string(status));
assert(!status);
}
void test_group_remove_member(::pEp_identity& ident)
{
logH2("test_group_remove_member");
status = gu->adapter_group_remove_member(Adapter::session(), grp_ident, &ident);
log("STATUS: " + status_to_string(status));
assert(!status);
}
void test_group_dissolve()
{
logH2("test_group_dissolve");
status = gu->adapter_group_dissolve(Adapter::session(), grp_ident, alice);
log("STATUS: " + status_to_string(status));
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;
// pEpSQLite::log_enabled = true;
// ListManagerDummy::log_enabled = true;
GroupDriverDummy::log_enabled = true;
GroupDriverEngine::log_enabled = true;
GroupDriverReplicator::log_enabled = true;
GroupDriverDummy gdd{ lmd_path };
GroupDriverEngine gde{};
GroupDriverReplicator gdr{};
gu = &gde;
gq = nullptr;
// gu = &gdd;
// gq = &gdd;
// gu = &gdr;
// gq = &gdr;
Adapter::session.initialize();
// Setup Test Context
test_create_alice_me();
test_create_bob_partner();
test_create_carol_partner();
test_setup_and_start_sync();
logH1("1. Create group");
test_group_create();
logH1("2. Add Bob");
test_group_invite_member(*bob); // Fails
logH1("3. Add Carol");
test_group_invite_member(*carol);
logH1("4. Remove Carol");
test_group_remove_member(*carol);
if (gq != nullptr) {
::pEp_identity* grp_ident = ::new_identity("group1@peptest.ch", NULL, "432", "group1");
::pEp_identity* manager = nullptr;
PEP_STATUS stat = gq->group_query_manager(Adapter::session(), grp_ident, &manager);
log(status_to_string(stat));
log(::Utils::to_string(manager));
}
logH1("6. Dissolve");
test_group_dissolve();
Adapter::stop_sync();
return 0;
}

@ -0,0 +1,124 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "framework/framework.hh"
#include <iostream>
#include <vector>
#include <pEp/sync_api.h>
#include "../src/callback_dispatcher.hh"
#include "../src/Adapter.hh"
#include "../src/passphrase_cache.hh"
using namespace std;
using namespace pEp;
vector<string> expected_msg = { "synchronizeGroupKeys",
"groupKeysUpdate",
"initUnledGroupKeyReset",
"beacon",
"beacon" };
vector<::sync_handshake_signal> expected_notification = { SYNC_NOTIFY_IN_GROUP,
SYNC_NOTIFY_START,
SYNC_NOTIFY_SOLE,
SYNC_NOTIFY_START,
SYNC_NOTIFY_STOP };
::PEP_STATUS test_messageToSend(::message* _msg)
{
static auto actual = expected_msg.begin();
Test::Message msg = Test::make_message(_msg);
string text = Test::make_pEp_msg(msg);
cerr << "expecting: " << *actual << endl;
cerr << text;
assert(text.find(*actual++) != string::npos);
return PEP_STATUS_OK;
}
::PEP_STATUS test_notifyHandshake(::pEp_identity* _me, ::pEp_identity* _partner, sync_handshake_signal signal)
{
static auto actual = expected_notification.begin();
Test::Identity me = Test::make_identity(_me);
Test::Identity partner = Test::make_identity(_partner);
cerr << "expecting: " << *actual << endl;
cerr << "notifyHandshake: " << signal << endl;
assert(signal == *actual++);
return PEP_STATUS_OK;
}
int main(int argc, char** argv)
{
pEp::Adapter::pEpLog::set_enabled(true);
Test::setup(argc, argv);
pEpLog(getenv("HOME"));
int n;
std::cin >> n;
Adapter::session.initialize(Adapter::SyncModes::Async, false);
// set up two own identites for sync
passphrase_cache.add("erwin");
passphrase_cache.add("bob");
std::string bob_filename = Test::get_resource_abs(
"bob-primary-with-password-bob-subkey-without.pgp");
std::string bob_fpr = "5C76378A62B04CF3F41BEC8D4940FC9FA1878736";
std::string erwin_filename = Test::get_resource_abs("erwin_normal_encrypted.pgp");
std::string erwin_fpr = "CBA968BC01FCEB89F04CCF155C5E9E3F0420A570";
Test::import_key_from_file(bob_filename);
Test::import_key_from_file(erwin_filename);
Test::Identity bob = Test::make_identity(
::new_identity("bob@example.org", bob_fpr.c_str(), "BOB", "Bob Dog"));
PEP_STATUS status = ::set_own_key(Adapter::session(), bob.get(), bob_fpr.c_str());
assert(status == PEP_STATUS_OK);
status = ::enable_identity_for_sync(Adapter::session(), bob.get());
assert(status == PEP_STATUS_OK);
Test::Identity erwin = Test::make_identity(
::new_identity("erwin@example.org", erwin_fpr.c_str(), "BOB", "Bob is Erwin"));
status = ::set_own_key(Adapter::session(), erwin.get(), erwin_fpr.c_str());
assert(status == PEP_STATUS_OK);
status = ::enable_identity_for_sync(Adapter::session(), erwin.get());
assert(status == PEP_STATUS_OK);
// simulate a device group by setting the identities to in sync
status = ::set_identity_flags(Adapter::session(), bob.get(), PEP_idf_devicegroup);
status = ::set_identity_flags(Adapter::session(), erwin.get(), PEP_idf_devicegroup);
// register at callback_dispatcher and start sync
callback_dispatcher.add(test_messageToSend, test_notifyHandshake);
Adapter::start_sync();
// leave device group
status = ::leave_device_group(Adapter::session());
throw_status(status);
// wait for sync shutdown and release first session
Test::join_sync_thread();
assert(!Adapter::is_sync_running());
// switch off and on again
Adapter::start_sync();
sleep(2);
assert(Adapter::is_sync_running());
Adapter::stop_sync();
Test::join_sync_thread();
assert(!Adapter::is_sync_running());
Adapter::session.release();
return 0;
}

@ -0,0 +1,307 @@
#include "../src/listmanager_dummy.hh"
#include "../src/utils.hh"
#include <pEp/pitytest11/test_utils.hh>
#include <exception>
#include <map>
#include <cassert>
using namespace std;
using namespace pEp;
using namespace pEp::Adapter::pEpLog;
using namespace pEp::Utils;
struct lm_list {
string addr;
string mod;
vector<string> members;
};
struct model_test_lmd {
string alice;
string bob;
string carol;
string joe;
string db_path;
vector<lm_list> lists;
vector<string> lists_addr() const
{
vector<string> ret;
for (const lm_list& l : this->lists) {
ret.push_back(l.addr);
}
return ret;
}
};
void apply_model(ListManagerDummy& lmd, const model_test_lmd& model)
{
// log("apply_model()");
for (const lm_list& l : model.lists) {
lmd.list_add(l.addr, l.mod);
for (const string& m : l.members) {
lmd.member_add(l.addr, m);
}
}
}
void verify_model(ListManagerDummy& lmd, const model_test_lmd& model)
{
// log("verify_model()");
assert((model.lists_addr()) == lmd.lists());
for (const lm_list& l : model.lists) {
assert(l.members == lmd.members(l.addr));
}
for (const lm_list& l : model.lists) {
assert(l.mod == lmd.moderator(l.addr));
}
}
void recreate_apply_and_verify_model(ListManagerDummy& lmd, const model_test_lmd& model)
{
try {
lmd.delete_db();
} catch (const exception& e) {
}
assert(!path_exists(model.db_path));
apply_model(lmd, model);
verify_model(lmd, model);
}
model_test_lmd create_default_model()
{
model_test_lmd model;
model.db_path = "test_lmd.db";
model.alice = "alice@peptest.org";
model.bob = "bob@peptest.org";
model.carol = "carol@peptest.org";
model.joe = "joe@peptest.org";
lm_list l1;
l1.addr = "list1@peptest.org";
l1.mod = model.alice;
l1.members.push_back(model.bob);
l1.members.push_back(model.carol);
lm_list l2;
l2.addr = "list2@peptest.org";
l2.mod = model.alice;
l2.members.push_back(model.bob);
l2.members.push_back(model.carol);
l2.members.push_back(model.joe);
lm_list l3;
l3.addr = "list3@peptest.org";
l3.mod = model.bob;
l3.members.push_back(model.carol);
l3.members.push_back(model.joe);
model.lists.push_back(l1);
model.lists.push_back(l2);
model.lists.push_back(l3);
return model;
}
model_test_lmd create_model_bad_path()
{
model_test_lmd model = create_default_model();
model.db_path = "/wont_create_dirs/bad.db";
return model;
}
int main(int argc, char* argv[])
{
// pEpSQLite::log_enabled = true;
ListManagerDummy::log_enabled = false;
logH1("Testing SUCCESS conditions");
{
logH2("Test create new db");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
}
{
logH2("Test re-open db");
model_test_lmd model = create_default_model();
assert(path_exists(model.db_path));
ListManagerDummy lmd(model.db_path);
verify_model(lmd, model);
logH2("Test list_delete");
lmd.list_delete(model.lists.at(2).addr);
model.lists.pop_back();
verify_model(lmd, model);
logH2("Test auto reopen after close()");
lmd.close_db();
logH2("Test member_remove");
lmd.member_remove(model.lists.at(0).addr, model.lists.at(0).members.at(1));
model.lists.at(0).members.pop_back();
verify_model(lmd, model);
logH2("Test list_exists() - true");
assert(lmd.list_exists(model.lists.at(0).addr));
logH2("Test list_exists() - false");
assert(!lmd.list_exists("does_not_exist_for_sure"));
logH2("Test member_exists() - true");
assert(lmd.member_exists(model.lists.at(0).addr, model.lists.at(0).members.at(0)));
logH2("Test member_exists() - false");
assert(!lmd.member_exists(model.lists.at(0).addr, "does_not_exist_for_sure"));
logH2("Test delete_db");
lmd.delete_db();
assert(!path_exists(model.db_path));
}
logH1("Testing ERROR conditions");
{
logH2("Testing success on close_db() on model_bad_path");
model_test_lmd model = create_model_bad_path();
ListManagerDummy lmd(model.db_path);
lmd.close_db();
}
{
logH2("Testing exception on delete_db() on model_bad_path");
model_test_lmd model = create_model_bad_path();
ListManagerDummy lmd(model.db_path);
ASSERT_EXCEPT(lmd.delete_db());
}
{
logH2("Testing exception on lists() on: on model_bad_path");
model_test_lmd model = create_default_model();
model.db_path = "/wont_create_dirs/bad.db";
ListManagerDummy lmd(model.db_path);
ASSERT_EXCEPT(lmd.lists());
}
// ------------------------------------------------------------------------------------
logH1("list_add() Error conditions");
{
logH2("Testing list_add() AlreadyExistsException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.list_add(model.lists.at(0).addr, "any");
assert(false);
} catch (const AlreadyExistsException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
// ------------------------------------------------------------------------------------
logH1("list_delete() Error conditions");
{
logH2("Testing list_delete() DoesNotExistException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.list_delete("does_not_exist_for_sure");
assert(false);
} catch (const ListDoesNotExistException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
// ------------------------------------------------------------------------------------
logH1("member_add() Error conditions");
{
logH2("Testing member_add() AlreadyExistsException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.member_add(model.lists.at(0).addr, model.lists.at(0).members.at(0));
assert(false);
} catch (const AlreadyExistsException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
{
logH2("Testing member_add() to not existing list - DoesNotExistException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.member_add("does_not_exist_for_sure", model.lists.at(0).members.at(0));
assert(false);
} catch (const ListDoesNotExistException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
// ------------------------------------------------------------------------------------
logH1("member_remove() Error conditions");
{
logH2("Testing member_remove() not existing member - DoesNotExistException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.member_remove(model.lists.at(0).addr, "does_not_exist_for_sure");
assert(false);
} catch (const MemberDoesNotExistException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
{
logH2("Testing member_remove() not existing list - DoesNotExistException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.member_remove("does_not_exist_for_sure", model.lists.at(0).members.at(0));
assert(false);
} catch (const ListDoesNotExistException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
// ------------------------------------------------------------------------------------
logH1("moderator() Error conditions");
{
logH2("Testing moderator() DoesNotExistException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.moderator("does_not_exist_for_sure");
assert(false);
} catch (const ListDoesNotExistException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
// ------------------------------------------------------------------------------------
logH1("members() Error conditions");
{
logH2("Testing members() DoesNotExistException");
model_test_lmd model = create_default_model();
ListManagerDummy lmd(model.db_path);
recreate_apply_and_verify_model(lmd, model);
try {
lmd.members("does_not_exist_for_sure");
assert(false);
} catch (const ListDoesNotExistException& e) {
log(nested_exception_to_string(e));
} catch (...) {
assert(false);
}
}
logH1("All Tests SUCCESSFUL");
}

@ -0,0 +1,125 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "framework/framework.hh"
#include <iostream>
#include <cassert>
#include <cstring>
#include <sys/param.h>
#include <cstring>
#include "../src/message_cache.hh"
#include "../src/Adapter.hh"
using namespace std;
using namespace pEp;
int main(int argc, char **argv)
{
Test::setup(argc, argv);
Adapter::session.initialize();
::pEp_identity *alice = ::new_identity("alice@mail.com", nullptr, PEP_OWN_USERID, "Alice");
::myself(Adapter::session(), alice);
char *mime = strdup("From: Alice <alice@mail.com>\n"
"To: Bob <bob@mail.com>\n"
"Subject: short message\n"
"\n"
"long message\n");
// add to cache
::message *src = nullptr;
bool has_possible_pEp_msg;
::PEP_STATUS status = MessageCache::cache_mime_decode_message(
mime,
strlen(mime),
&src,
&has_possible_pEp_msg);
assert(status == PEP_STATUS_OK);
status = ::myself(Adapter::session(), src->from);
assert(status == PEP_STATUS_OK);
::update_identity(Adapter::session(), src->to->ident);
assert(status == PEP_STATUS_OK);
::pEp_identity *bob = identity_dup(src->to->ident);
src->dir = ::PEP_dir_outgoing;
::message *dst = nullptr;
cout << "cache_encrypt_message()" << endl;
status = MessageCache::cache_encrypt_message(
Adapter::session(),
src,
nullptr,
&dst,
PEP_enc_PEP,
0);
assert(status != PEP_ILLEGAL_VALUE);
assert(src->longmsg == nullptr);
assert(src->attachments == nullptr);
assert(dst == nullptr);
// remove from cache
free(mime);
mime = nullptr;
status = MessageCache::cache_mime_encode_message(MessageCache::msg_src, src, false, &mime, false);
assert(status == PEP_STATUS_OK);
cout << "cache_mime_encode_message()" << endl;
cout << "mime: " << endl << mime << endl;
// add to cache
::free_message(src);
src = nullptr;
cout << "cache_mime_decode_message" << endl;
status = MessageCache::cache_mime_decode_message(mime, strlen(mime), &src, &has_possible_pEp_msg);
assert(status == PEP_STATUS_OK);
assert(src->longmsg == nullptr);
assert(src->attachments == nullptr);
::PEP_rating rating;
::PEP_decrypt_flags_t flags = 0;
::stringlist_t *keylist = nullptr;
cout << "cache_decrypt_message" << endl;
status = MessageCache::cache_decrypt_message(
Adapter::session(),
src,
&dst,
&keylist,
&rating,
&flags);
assert(status != PEP_ILLEGAL_VALUE);
assert(src->longmsg == nullptr);
assert(src->attachments == nullptr);
// remove from cache
free(mime);
mime = nullptr;
cout << "cache_mime_encode_message" << endl;
status = MessageCache::cache_mime_encode_message(MessageCache::msg_src, src, false, &mime, false);
assert(src->longmsg == nullptr);
assert(src->attachments == nullptr);
cout << "mime: " << endl << mime << endl;
free(mime);
::free_message(src);
::free_message(dst);
::free_identity(bob);
::free_identity(alice);
Adapter::session.release();
return 0;
}

@ -0,0 +1,642 @@
#include "test_pEpSQLite.hh"
#include "../src/pEpSQLite.hh"
#include "../src/utils.hh"
#include <pEp/std_utils.hh>
#include <pEp/pitytest11/test_utils.hh>
#include <fstream>
#include <cassert>
using namespace std;
using namespace pEp;
using namespace pEp::Test;
using namespace pEp::Utils;
namespace pEp {
namespace Test {
// --------------------------------- FIXTURES ---------------------------------
// filenames
string fixture_db_filename_new()
{
// TESTLOG("called");
string path = "new.db";
return path;
}
string fixture_db_filename_bad()
{
// TESTLOG("called");
string db_path_bad = "/will_not_create_dirs/bad.db";
return db_path_bad;
}
string fixture_db_filename_existing_and_verified()
{
// TESTLOG("called");
string path = "new.db";
return path;
}
string fixture_db_filename_corrupt()
{
// TESTLOG("called");
string path = "corrupt.db";
return path;
}
// prepared db's
string fixture_init_db_new()
{
// TESTLOG("called");
string path = fixture_db_filename_new();
path_ensure_not_existing(path);
return path;
}
string fixture_init_db_existing_and_verified()
{
// TESTLOG("called");
string path = "existing.db";
path_ensure_not_existing(path);
return path;
}
string fixture_init_db_corrupt()
{
// TESTLOG("called");
string path = fixture_db_filename_corrupt();
path_ensure_not_existing(path);
ofstream db_corrupt = file_create(path);
db_corrupt << "G4rbage" << endl;
db_corrupt.close();
return path;
}
// instance
pEpSQLite fixture_instance_of_new()
{
// TESTLOG("called");
return test_create_instance_on_new();
}
pEpSQLite fixture_instance_of_existing_and_verified()
{
// TESTLOG("called");
return test_create_instance_on_existing();
}
pEpSQLite fixture_instance_of_bad()
{
// TESTLOG("called");
return test_create_instance_on_path_bad();
}
pEpSQLite fixture_instance_of_corrupt()
{
// TESTLOG("called");
return test_create_instance_on_path_corrupt();
}
// open
pEpSQLite fixture_db_open_of_new()
{
// TESTLOG("called");
return test_createopen_db_new();
}
pEpSQLite fixture_db_open_of_existing_and_verified()
{
// TESTLOG("called");
return test_db_verify_content_after_insert_on_tables_exist();
}
pEpSQLite fixture_db_open_of_bad()
{
// TESTLOG("called");
return test_createopen_db_bad();
}
pEpSQLite fixture_db_open_of_corrupt()
{
// TESTLOG("called");
return test_createopen_db_corrupt();
}
pEpSQLite fixture_db_open_after_close()
{
// TESTLOG("called");
return test_close_after_open();
}
// tables
pEpSQLite fixture_db_open_with_tables_of_new()
{
// TESTLOG("called");
return test_db_create_tables_on_open_new();
}
pEpSQLite fixture_db_open_with_tables_of_corrupt()
{
// TESTLOG("called");
return test_db_create_tables_on_open_corrupt();
}
// content
pEpSQLite fixture_db_open_with_tables_and_content()
{
// TESTLOG("called");
return test_db_insert_on_tables_exist();
}
// delete
pEpSQLite fixture_db_open_after_delete()
{
// TESTLOG("called");
return test_delete_file_gone_after_open_existing();
}
pEpSQLite fixture_db_open_after_close_after_delete()
{
// TESTLOG("called");
return test_delete_file_gone_after_close_new();
}
// --------------------------------- TESTS ---------------------------------
// instance creation
// OK
pEpSQLite test_create_instance_on_new()
{
TESTLOG("called");
pEpSQLite db(fixture_init_db_new());
return db;
}
// OK
pEpSQLite test_create_instance_on_existing()
{
TESTLOG("called");
pEpSQLite db(fixture_init_db_existing_and_verified());
return db;
}
// OK
pEpSQLite test_create_instance_on_path_bad()
{
TESTLOG("called");
pEpSQLite db(fixture_db_filename_bad());
return db;
}
// OK
pEpSQLite test_create_instance_on_path_corrupt()
{
TESTLOG("called");
pEpSQLite db(fixture_init_db_corrupt());
return db;
}
// db create_open (create_or_open())
// OK, new db
pEpSQLite test_createopen_db_new()
{
TESTLOG("called");
pEpSQLite db = fixture_instance_of_new();
assert(!path_exists(fixture_db_filename_new()));
db.create_or_open_db();
assert(path_exists(fixture_db_filename_new()));
return db;
}
// OK, open db
pEpSQLite test_createopen_db_existing()