/** * * db_test.cc * An Tao * * Copyright 2018, An Tao. All rights reserved. * Use of this source code is governed by a MIT license * that can be found in the License file. * * Drogon * * Drogon database test program * */ #include "Users.h" #include #include #include #include #include #include #include using namespace drogon::orm; using namespace drogon_model::postgres; #define RESET "\033[0m" #define RED "\033[31m" /* Red */ #define GREEN "\033[32m" /* Green */ #define TEST_COUNT 36 int counter = 0; int gLoops = 1; std::promise pro; auto globalf = pro.get_future(); using namespace std::chrono_literals; void addCount(int &count, std::promise &pro) { ++count; // LOG_DEBUG << count; if (count == TEST_COUNT * gLoops) { pro.set_value(1); } } void testOutput(bool isGood, const std::string &testMessage) { if (isGood) { std::cout << GREEN << counter + 1 << ".\t" << testMessage << "\t\tOK\n"; std::cout << RESET; addCount(counter, pro); } else { std::cout << RED << testMessage << "\t\tBAD\n"; std::cout << RESET; exit(1); } } void doTest(const drogon::orm::DbClientPtr &clientPtr) { // Prepare the test environment *clientPtr << "DROP TABLE IF EXISTS USERS" >> [](const Result &r) { testOutput(true, "Prepare the test environment(0)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "Prepare the test environment(0)"); }; *clientPtr << "CREATE TABLE users \ (\ user_id character varying(32),\ user_name character varying(64),\ password character varying(64),\ org_name character varying(20),\ signature character varying(50),\ avatar_id character varying(32),\ id serial PRIMARY KEY,\ salt character varying(20),\ admin boolean DEFAULT false,\ CONSTRAINT user_id_org UNIQUE(user_id, org_name)\ )" >> [](const Result &r) { testOutput(true, "Prepare the test environment(1)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "Prepare the test environment(1)"); }; /// Test1:DbClient streaming-type interface /// 1.1 insert,non-blocking *clientPtr << "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *" << "pg" << "postgresql" << "123" << "default" >> [](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; testOutput(r[0]["id"].as() == 1, "DbClient streaming-type interface(0)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(0)"); }; /// 1.2 insert,blocking *clientPtr << "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *" << "pg1" << "postgresql1" << "123" << "default" << Mode::Blocking >> [](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; testOutput(r[0]["id"].as() == 2, "DbClient streaming-type interface(1)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(1)"); }; /// 1.3 query,no-blocking *clientPtr << "select * from users where 1 = 1" << Mode::NonBlocking >> [](const Result &r) { testOutput(r.size() == 2, "DbClient streaming-type interface(2)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(2)"); }; /// 1.4 query,blocking *clientPtr << "select * from users where 1 = 1" << Mode::Blocking >> [](const Result &r) { testOutput(r.size() == 2, "DbClient streaming-type interface(3)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(3)"); }; /// 1.5 query,blocking int count = 0; *clientPtr << "select user_name, user_id, id from users where 1 = 1" << Mode::Blocking >> [&count](bool isNull, const std::string &name, std::string user_id, int id) { if (!isNull) count++; else { testOutput(count == 2, "DbClient streaming-type interface(4)"); } } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(4)"); }; /// 1.6 query, parameter binding *clientPtr << "select * from users where id = $1" << 1 >> [](const Result &r) { testOutput(r.size() == 1, "DbClient streaming-type interface(5)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(5)"); }; /// 1.7 query, parameter binding *clientPtr << "select * from users where user_id = $1 and user_name = $2" << "pg1" << "postgresql1" >> [](const Result &r) { testOutput(r.size() == 1, "DbClient streaming-type interface(6)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(6)"); }; /// 1.8 delete *clientPtr << "delete from users where user_id = $1 and user_name = $2" << "pg1" << "postgresql1" >> [](const Result &r) { testOutput(r.affectedRows() == 1, "DbClient streaming-type interface(7)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(7)"); }; /// 1.9 update *clientPtr << "update users set user_id = $1, user_name = $2 where user_id " "= $3 and user_name = $4" << "pg1" << "postgresql1" << "pg" << "postgresql" >> [](const Result &r) { testOutput(r.affectedRows() == 1, "DbClient streaming-type interface(8)"); } >> [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(8)"); }; /// 1.10 truncate *clientPtr << "truncate table users" >> [](const Result &r) { testOutput(true, "DbClient streaming-type interface(9)"); } >> [](const DrogonDbException &e) { std::cerr << "error:" << e.base().what() << std::endl; testOutput(false, "DbClient streaming-type interface(9)"); }; /// Test asynchronous method /// 2.1 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values($1,$2,$3,$4) returning *", [](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; testOutput(r[0]["id"].as() == 3, "DbClient asynchronous interface(0)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(0)"); }, "pg", "postgresql", "123", "default"); /// 2.2 insert clientPtr->execSqlAsync( "insert into users \ (user_id,user_name,password,org_name) \ values($1,$2,$3,$4)", [](const Result &r) { // std::cout << "id=" << r[0]["id"].as() << std::endl; testOutput(r.affectedRows() == 1, "DbClient asynchronous interface(1)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(1)"); }, "pg1", "postgresql1", "123", "default"); /// 2.3 query clientPtr->execSqlAsync( "select * from users where 1 = 1", [](const Result &r) { testOutput(r.size() == 2, "DbClient asynchronous interface(2)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(2)"); }); /// 2.2 query, parameter binding clientPtr->execSqlAsync( "select * from users where id = $1", [](const Result &r) { testOutput(r.size() == 0, "DbClient asynchronous interface(3)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(3)"); }, 1); /// 2.3 query, parameter binding clientPtr->execSqlAsync( "select * from users where user_id = $1 and user_name = $2", [](const Result &r) { testOutput(r.size() == 1, "DbClient asynchronous interface(4)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(4)"); }, "pg1", "postgresql1"); /// 2.4 delete clientPtr->execSqlAsync( "delete from users where user_id = $1 and user_name = $2", [](const Result &r) { testOutput(r.affectedRows() == 1, "DbClient asynchronous interface(5)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(5)"); }, "pg1", "postgresql1"); /// 2.5 update clientPtr->execSqlAsync( "update users set user_id = $1, user_name = $2 where user_id " "= $3 and user_name = $4", [](const Result &r) { testOutput(r.affectedRows() == 1, "DbClient asynchronous interface(6)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(6)"); }, "pg1", "postgresql1", "pg", "postgresql"); /// 2.6 truncate clientPtr->execSqlAsync( "truncate table users", [](const Result &r) { testOutput(true, "DbClient asynchronous interface(7)"); }, [](const DrogonDbException &e) { std::cerr << "error:" << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(7)"); }); /// Test synchronous method /// 3.1 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *", "pg", "postgresql", "123", "default"); testOutput(r[0]["id"].as() == 5, "DbClient synchronous interface(0)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(0)"); } /// 3.2 insert try { auto r = clientPtr->execSqlSync( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4)", "pg1", "postgresql1", "123", "default"); testOutput(r.affectedRows() == 1, "DbClient synchronous interface(1)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(1)"); } /// 3.3 query try { auto r = clientPtr->execSqlSync( "select * from users where user_id=$1 and user_name=$2", "pg1", "postgresql1"); testOutput(r.size() == 1, "DbClient synchronous interface(2)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(2)"); } /// 3.4 query for none try { auto r = clientPtr->execSqlSync( "select * from users where user_id=$1 and user_name=$2", "pg111", "postgresql1"); testOutput(r.size() == 0, "DbClient synchronous interface(3)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient asynchronous interface(3)"); } /// 3.5 bad sql try { auto r = clientPtr->execSqlSync( "select * from users where user_id=$1 and user_name='12'", "pg111", "postgresql1"); testOutput(r.size() == 0, "DbClient synchronous interface(4)"); } catch (const DrogonDbException &e) { // std::cerr << e.base().what() << std::endl; testOutput(true, "DbClient asynchronous interface(4)"); } /// 3.6 truncate try { auto r = clientPtr->execSqlSync("truncate table users"); testOutput(true, "DbClient synchronous interface(5)"); } catch (const DrogonDbException &e) { // std::cerr << e.base().what() << std::endl; testOutput(true, "DbClient asynchronous interface(5)"); } /// Test future interface /// 4.1 insert auto f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4) returning *", "pg", "postgresql", "123", "default"); try { auto r = f.get(); testOutput(r[0]["id"].as() == 7, "DbClient future interface(0)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient future interface(0)"); } /// 4.2 insert f = clientPtr->execSqlAsyncFuture( "insert into users (user_id,user_name,password,org_name) " "values($1,$2,$3,$4)", "pg1", "postgresql1", "123", "default"); try { auto r = f.get(); testOutput(r.affectedRows() == 1, "DbClient future interface(1)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient future interface(1)"); } /// 4.3 query f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=$1 and user_name=$2", "pg1", "postgresql1"); try { auto r = f.get(); testOutput(r.size() == 1, "DbClient future interface(2)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient future interface(2)"); } /// 4.4 query for none f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=$1 and user_name=$2", "pg111", "postgresql1"); try { auto r = f.get(); testOutput(r.size() == 0, "DbClient future interface(3)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "DbClient future interface(3)"); } /// 4.5 bad sql f = clientPtr->execSqlAsyncFuture( "select * from users where user_id=$1 and user_name='12'", "pg111", "postgresql1"); try { auto r = f.get(); testOutput(r.size() == 0, "DbClient future interface(4)"); } catch (const DrogonDbException &e) { // std::cerr << e.base().what() << std::endl; testOutput(true, "DbClient future interface(4)"); } /// 4.6 truncate f = clientPtr->execSqlAsyncFuture("truncate table users"); try { auto r = f.get(); testOutput(true, "DbClient future interface(5)"); } catch (const DrogonDbException &e) { // std::cerr << e.base().what() << std::endl; testOutput(true, "DbClient future interface(5)"); } /// Test ORM mapper /// 5.1 insert, noneblocking drogon::orm::Mapper mapper(clientPtr); Users user; user.setUserId("pg"); user.setUserName("postgres"); user.setPassword("123"); user.setOrgName("default"); mapper.insert( user, [](Users ret) { testOutput(ret.getPrimaryKey() == 9, "ORM mapper asynchronous interface(0)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "ORM mapper asynchronous interface(0)"); }); /// 5.2 insert user.setUserId("pg1"); user.setUserName("postgres1"); mapper.insert( user, [](Users ret) { testOutput(ret.getPrimaryKey() == 10, "ORM mapper asynchronous interface(1)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "ORM mapper asynchronous interface(1)"); }); /// 5.3 select where in mapper.findBy( Criteria(Users::Cols::_id, CompareOperator::IN, std::vector{10, 200}), [](std::vector users) { testOutput(users.size() == 1, "ORM mapper asynchronous interface(2)"); }, [](const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "ORM mapper asynchronous interface(2)"); }); /// 5.4 find by primary key. blocking try { auto user = mapper.findByPrimaryKey(10); testOutput(true, "ORM mapper asynchronous interface(3)"); } catch (const DrogonDbException &e) { std::cerr << e.base().what() << std::endl; testOutput(false, "ORM mapper asynchronous interface(3)"); } } int main(int argc, char *argv[]) { trantor::Logger::setLogLevel(trantor::Logger::DEBUG); #if USE_POSTGRESQL auto clientPtr = DbClient::newPgClient( "host=127.0.0.1 port=5432 dbname=postgres user=postgres", 1); #endif LOG_DEBUG << "start!"; sleep(1); if (argc == 2) { gLoops = atoi(argv[1]); } for (int i = 0; i < gLoops; ++i) { doTest(clientPtr); } globalf.get(); std::this_thread::sleep_for(0.008s); return 0; }