Browse Source

LIB-12: listmanager prototype done

LIB-12
heck 4 years ago
parent
commit
939719dea2
  1. 3
      .clang-format
  2. 294
      test/test_sqlite3.cc

3
.clang-format

@ -38,4 +38,5 @@ SpaceAfterTemplateKeyword: false
AccessModifierOffset: -4 AccessModifierOffset: -4
AllowShortBlocksOnASingleLine: Always AllowShortBlocksOnASingleLine: Always
IndentPPDirectives: BeforeHash IndentPPDirectives: BeforeHash
Cpp11BracedListStyle: false Cpp11BracedListStyle: false
BreakStringLiterals: false

294
test/test_sqlite3.cc

@ -4,64 +4,96 @@
#include <cstdio> #include <cstdio>
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
#include <vector>
#include <map>
//TODO: add const //TODO: add const
using namespace std; using namespace std;
using namespace pEp;
sqlite3 *db; using ResultSet = vector<map<string, string>>;
string db_path; using RSRecord = map<string, string>;
void print_exception(const exception &e, int level = 0) namespace pEp {
{ namespace SQLite3 {
cerr << string(level, ' ') << "exception: " << e.what() << endl; ::sqlite3 *db;
try { string db_path;
rethrow_if_nested(e);
} catch (const exception &e) {
print_exception(e, level + 1);
} catch (...) {
}
}
static int callback(void *NotUsed, int argc, char **argv, char **azColName) ResultSet resultset;
{
int i;
for (i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
void execute_sql(const string &stmt) void create_or_open_db()
{ {
// pEpLog("execute_sql(\"" + stmt + "\")"); pEpLog("called");
char *zErrMsg = nullptr; int rc{::sqlite3_open(db_path.c_str(), &db)};
int rc = sqlite3_exec(db, stmt.c_str(), callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
runtime_error e{ string("execute_sql: " + string(sqlite3_errmsg(db)) + ":" + string(zErrMsg)) };
sqlite3_free(zErrMsg);
throw(e);
}
}
void create_or_open_db() if (rc) {
{ runtime_error e{string("Can't open database (" + db_path + "):" + ::sqlite3_errmsg(db))};
pEpLog("called"); throw (e);
int rc = sqlite3_open(db_path.c_str(), &db); }
}
void close_db()
{
::sqlite3_close(db);
}
void delete_db()
{
pEpLog("called");
remove(db_path.c_str());
if (errno) {
cerr << "could not delete db (" + db_path + "): " << strerror(errno) << endl;
}
}
ResultSet execute(const string& stmt)
{
// pEpLog("execute(\"" + stmt + "\")");
resultset.clear();
char *zErrMsg = nullptr;
int rc = ::sqlite3_exec(db, stmt.c_str(), [](void *NotUsed, int argc, char **argv, char **azColName) -> int {
RSRecord record;
for (int col = 0; col < argc; col++) {
const string key = string{azColName[col]};
// TODO: NULL is not correct, could be a valid value
const string val = string{argv[col] ? argv[col] : "NULL"};
record.insert({key, val});
}
resultset.push_back(record);
return 0;
}, 0, &zErrMsg);
if (rc != SQLITE_OK) {
runtime_error e{string("execute: " + string(::sqlite3_errmsg(db)) + ":" + string(zErrMsg))};
::sqlite3_free(zErrMsg);
throw (e);
}
return resultset;
}
if (rc) { string resultset_to_string(ResultSet rs)
runtime_error e{ string("Can't open database (" + db_path + "):" + sqlite3_errmsg(db)) }; {
throw(e); stringstream ss;
int i = 0;
for (const RSRecord& rec : rs) {
for (const auto& item : rec) {
ss << "RESULTSET[" << i << "][" << item.first << "] = " << item.second << "\"" << endl;
}
i++;
}
return ss.str();
}
} }
} }
void delete_db()
void print_exception(const exception& e, int level = 0)
{ {
pEpLog("called"); cerr << string(level, ' ') << "exception: " << e.what() << endl;
remove(db_path.c_str()); try {
if (errno) { rethrow_if_nested(e);
cerr << "could not delete db (" + db_path + "): " << strerror(errno) << endl; } catch (const exception& e) {
print_exception(e, level + 1);
} catch (...) {
} }
} }
@ -71,7 +103,7 @@ void db_config()
try { try {
string sql; string sql;
sql = "PRAGMA foreign_keys=ON"; sql = "PRAGMA foreign_keys=ON";
execute_sql(sql); SQLite3::execute(sql);
} catch (...) { } catch (...) {
runtime_error e("db_config() - failed with exception"); runtime_error e("db_config() - failed with exception");
throw_with_nested(e); throw_with_nested(e);
@ -85,123 +117,207 @@ void create_tables()
string sql; string sql;
sql = "CREATE TABLE IF NOT EXISTS lists(" sql = "CREATE TABLE IF NOT EXISTS lists("
"address TEXT NOT NULL," "address TEXT NOT NULL,"
"manager_id TEXT NOT NULL," "moderator_address TEXT NOT NULL,"
"PRIMARY KEY(address));"; "PRIMARY KEY(address));";
execute_sql(sql); SQLite3::execute(sql);
sql = "CREATE TABLE IF NOT EXISTS member_of(" sql = "CREATE TABLE IF NOT EXISTS member_of("
"address TEXT NOT NULL," "address TEXT NOT NULL,"
"list_address TEXT NOT NULL," "list_address TEXT NOT NULL,"
"PRIMARY KEY (address, list_address)," "PRIMARY KEY (address, list_address),"
"FOREIGN KEY(list_address) REFERENCES lists(address) ON DELETE CASCADE);"; "FOREIGN KEY(list_address) REFERENCES lists(address) ON DELETE CASCADE);";
execute_sql(sql); SQLite3::execute(sql);
} catch (...) { } catch (...) {
runtime_error e("create_tables() - failed with exception"); runtime_error e("create_tables() - failed with exception");
throw_with_nested(e); throw_with_nested(e);
} }
} }
void list_add(const string &addr_list, const string &addr_mgr) void list_add(const string& addr_list, const string& addr_mgr)
{ {
pEpLog("list_add(addr_list: \"" + addr_list + "\"\taddr_mgr: \"" + addr_mgr + "\")"); pEpLog("list_add(addr_list: \"" + addr_list + "\", addr_mgr: \"" + addr_mgr + "\")");
try { try {
string sql = "INSERT INTO lists(address, manager_id)" string sql = "INSERT INTO lists(address, moderator_address) VALUES ('" + addr_list + "','" +
"VALUES ('" + addr_mgr + "');";
addr_list + "','" + addr_mgr + "');"; SQLite3::execute(sql);
execute_sql(sql);
} catch (...) { } catch (...) {
runtime_error e( runtime_error e(
"list_add(addr_list: \"" + addr_list + "\"\taddr_mgr: \"" + addr_mgr + "list_add(addr_list: \"" + addr_list + "\"\taddr_mgr: \"" + addr_mgr +
"\") - failed with exception"); "\") - failed with exception");
throw_with_nested(e); throw_with_nested(e);
} }
} }
void list_delete(const string &addr_list) void list_delete(const string& addr_list)
{ {
pEpLog("list_delete(addr_list: \"" + addr_list + "\")"); pEpLog("list_delete(addr_list: \"" + addr_list + "\")");
try { try {
string sql; string sql;
sql = "DELETE FROM lists WHERE lists.address = '" + addr_list + "'"; sql = "DELETE FROM lists WHERE lists.address = '" + addr_list + "';";
execute_sql(sql); SQLite3::execute(sql);
} catch (...) { } catch (...) {
runtime_error e("list_delete(addr_list: \"" + addr_list + "\") - failed with exception"); runtime_error e("list_delete(addr_list: \"" + addr_list + "\") - failed with exception");
throw_with_nested(e); throw_with_nested(e);
} }
} }
void member_add(const string &addr_list, const string &addr_member) void member_add(const string& addr_list, const string& addr_member)
{ {
pEpLog("member_add(addr_list: \"" + addr_list + "\", addr_member: \"" + addr_member + "\")"); pEpLog("member_add(addr_list: \"" + addr_list + "\", addr_member: \"" + addr_member + "\")");
try { try {
string sql = "INSERT INTO member_of(address, list_address)" string sql = "INSERT INTO member_of(address, list_address) VALUES ('" + addr_member +
"VALUES ('" + "', '" + addr_list + "');";
addr_member + SQLite3::execute(sql);
"',"
"'" +
addr_list + "');";
execute_sql(sql);
} catch (...) { } catch (...) {
runtime_error e( runtime_error e(
"member_add(addr_list: \"" + addr_list + "\", addr_member: \"" + addr_member + "member_add(addr_list: \"" + addr_list + "\", addr_member: \"" + addr_member +
"\") - failed with exception"); "\") - failed with exception");
throw_with_nested(e); throw_with_nested(e);
} }
} }
void member_remove(const string &addr_list, const string &addr_member) void member_remove(const string& addr_list, const string& addr_member)
{ {
pEpLog("member_remove(addr_list: \"" + addr_list + "\", addr_member: '\"" + addr_member + "\")"); pEpLog("member_remove(addr_list: \"" + addr_list + "\", addr_member: '\"" + addr_member + "\")");
try { try {
string sql; string sql;
sql = "DELETE FROM member_of WHERE" sql = "DELETE FROM member_of WHERE (member_of.address = '" + addr_member +
"(member_of.address = '" + "') AND (member_of.list_address = '" + addr_list + "');";
addr_member + "') AND (member_of.list_address = '" + addr_list + "');"; SQLite3::execute(sql);
execute_sql(sql);
} catch (...) { } catch (...) {
runtime_error e( runtime_error e(
"member_remove(" + addr_list + ", " + addr_member + ") - failed with exception"); "member_remove(" + addr_list + ", " + addr_member + ") - failed with exception");
throw_with_nested(e); throw_with_nested(e);
} }
} }
vector<string> lists()
{
pEpLog("called");
vector<string> ret;
ResultSet rs;
try {
string sql;
sql = "SELECT address FROM lists";
rs = SQLite3::execute(sql);
} catch (...) {
runtime_error e("lists() - failed with exception");
throw_with_nested(e);
}
for (const RSRecord& rec : rs) {
ret.push_back(rec.at("address"));
}
return ret;
}
// Exceptions:
// * ListNotFound
string moderator(string list_address)
{
pEpLog("called");
string ret;
ResultSet rs;
try {
string sql;
sql = "SELECT moderator_address FROM lists "
"WHERE lists.address = '" + list_address + "';";
rs = SQLite3::execute(sql);
} catch (...) {
runtime_error e("lists() - failed with exception");
throw_with_nested(e);
}
if (!rs.empty()) {
for (const RSRecord& rec : rs) {
ret = rec.at("moderator_address");
}
}
return ret;
}
// Exceptions:
// * ListNotFound
vector<string> members(string list_address)
{
pEpLog("called");
vector<string> ret;
ResultSet rs;
try {
string sql;
sql = "SELECT address FROM member_of "
"WHERE list_address = '" + list_address + "'";
rs = SQLite3::execute(sql);
} catch (...) {
runtime_error e("lists() - failed with exception");
throw_with_nested(e);
}
if (!rs.empty()) {
for (const RSRecord& rec : rs) {
ret.push_back(rec.at("address"));
}
}
return ret;
}
template<typename T>
string vector_to_string(vector<T> v)
{
stringstream ss;
for (const T& elem : v) {
ss << elem << endl;
}
return ss.str();
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
pEp::Adapter::pEpLog::set_enabled(true); pEp::Adapter::pEpLog::set_enabled(true);
db_path = "test.db"; SQLite3::db_path = "test.db";
string dummy_in; string dummy_in;
try { try {
delete_db(); SQLite3::db_path = "test.db";
create_or_open_db(); SQLite3::delete_db();
cin >> dummy_in; SQLite3::create_or_open_db();
db_config(); db_config();
create_tables(); create_tables();
list_add("grp1@peptest.org", "alice@peptest.org"); list_add("grp1@peptest.org", "alice@peptest.org");
cout << vector_to_string(lists());
list_add("grp2@peptest.org", "alice@peptest.org"); list_add("grp2@peptest.org", "alice@peptest.org");
cout << vector_to_string(lists());
try { try {
list_add("grp1@peptest.org", "bob@peptest.org"); list_add("grp1@peptest.org", "bob@peptest.org");
assert(false); assert(false);
} catch (const exception &e) { } catch (const exception& e) {
print_exception(e); print_exception(e);
} }
cin >> dummy_in;
member_add("grp1@peptest.org", "bob@peptest.org"); member_add("grp1@peptest.org", "bob@peptest.org");
member_add("grp1@peptest.org", "carol@peptest.org"); member_add("grp1@peptest.org", "carol@peptest.org");
member_add("grp1@peptest.org", "joe@peptest.org"); member_add("grp1@peptest.org", "joe@peptest.org");
cin >> dummy_in; cout << vector_to_string(members("grp1@peptest.org")) << endl;
cout << moderator("grp1@peptest.org") << endl;
member_remove("grp1@peptest.org", "joe@peptest.org"); member_remove("grp1@peptest.org", "joe@peptest.org");
cin >> dummy_in;
list_delete("grp1@peptest.org"); list_delete("grp1@peptest.org");
cout << vector_to_string(lists());
cin >> dummy_in; } catch (const exception& e) {
} catch (const exception &e) {
print_exception(e); print_exception(e);
} }
sqlite3_close(db); SQLite3::close_db();
} }
Loading…
Cancel
Save