#include "stdafx.h" #include "TestMysql.h" #include #include #include "md5.h" #include "../include/qtl_mysql.hpp" using namespace std; struct TestMysqlRecord { uint32_t id; char name[33]; qtl::mysql::time create_time; TestMysqlRecord() { memset(this, 0, sizeof(TestMysqlRecord)); } void print() const { printf("ID=\"%d\", Name=\"%s\"\n", id, name); } }; namespace qtl { template<> inline void bind_record(qtl::mysql::statement& command, TestMysqlRecord&& v) { qtl::bind_field(command, 0, v.id); qtl::bind_field(command, 1, v.name); qtl::bind_field(command, 3, v.create_time); } } TestMysql::TestMysql() { id=0; TEST_ADD(TestMysql::test_dual) TEST_ADD(TestMysql::test_clear) TEST_ADD(TestMysql::test_insert) TEST_ADD(TestMysql::test_select) TEST_ADD(TestMysql::test_update) TEST_ADD(TestMysql::test_insert2) TEST_ADD(TestMysql::test_iterator) TEST_ADD(TestMysql::test_insert_blob) TEST_ADD(TestMysql::test_select_blob) } inline void TestMysql::connect(qtl::mysql::database& db) { TEST_ASSERT_MSG(db.open("localhost", "root", "", "test")==true, "Cannot connect to database"); } void TestMysql::test_dual() { qtl::mysql::database db; connect(db); try { db.query("select 0, 'hello world' from dual", [](uint32_t i, const std::string& str) { printf("0=\"%d\", 'hello world'=\"%s\"\n", i, str.data()); }); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } } void TestMysql::test_select() { qtl::mysql::database db; connect(db); try { db.query("select * from test where id=?", id, [](const qtl::indicator& id, const std::string& name, const qtl::mysql::time& create_time) { printf("ID=\"%d\", Name=\"%s\"\n", id.data, name.data()); }); db.query("select * from test where id=?", id, [](const TestMysqlRecord& record) { printf("ID=\"%d\", Name=\"%s\"\n", record.id, record.name); }); db.query("select * from test where id=?", id, &TestMysqlRecord::print); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } } void TestMysql::test_insert() { qtl::mysql::database db; connect(db); try { id=db.insert("insert into test(Name, CreateTime) values(?, now())", "test_user"); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } TEST_ASSERT_MSG(id>0, "insert failture."); } void TestMysql::test_insert2() { qtl::mysql::database db; connect(db); try { uint64_t affected=0; qtl::mysql::statement stmt=db.open_command("insert into test(Name, CreateTime) values(?, now())"); qtl::execute(stmt, &affected, "second_user", "third_user"); TEST_ASSERT_MSG(affected==2, "Cannot insert 2 records to table test."); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } } void TestMysql::test_update() { qtl::mysql::database db; connect(db); try { db.execute_direct("update test set Name=? WHERE ID=?", NULL, "other_user", id); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } TEST_ASSERT_MSG(id>0, "insert failture."); } void TestMysql::test_clear() { qtl::mysql::database db; connect(db); try { db.simple_execute("delete from test"); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } } void TestMysql::test_iterator() { qtl::mysql::database db; connect(db); try { cout<<"after insert all:"<("select * from test")) { printf("ID=\"%d\", Name=\"%s\"\n", record.id, record.name); } } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } } void TestMysql::test_insert_blob() { qtl::mysql::database db; connect(db); try { #ifdef _WIN32 const char filename[]="C:\\windows\\explorer.exe"; #else const char filename[]="/bin/sh"; #endif //_WIN32 fstream fs(filename, ios::binary|ios::in); TEST_ASSERT_MSG(fs, "Cannot open test file."); unsigned char md5[16]={0}; char md5_hex[33]={0}; get_md5(fs, md5); mysql_hex_string(md5_hex, (char*)md5, sizeof(md5)); printf("MD5 of file %s: %s.\n", filename, md5_hex); db.simple_execute("DELETE FROM test_blob"); fs.clear(); fs.seekg(0, ios::beg); id=db.insert("INSERT INTO test_blob (Filename, Content, MD5) values(?, ?, ?)", make_tuple(filename, ref((istream&)fs), qtl::const_blob_data(md5, sizeof(md5)))); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } } void TestMysql::test_select_blob() { qtl::mysql::database db; connect(db); try { const char dest_file[]="explorer.exe"; fstream fs(dest_file, ios::binary|ios::in|ios::out|ios::trunc); TEST_ASSERT_MSG(fs, "Cannot open test file."); unsigned char md5[16]={0}; char md5_hex[33]={0}; fs.seekg(ios::beg); std::string source_file; db.query_first("SELECT Filename, Content, MD5 FROM test_blob WHERE id=?", make_tuple(id), make_tuple(ref(source_file), ref((ostream&)fs), qtl::blob_data(md5, sizeof(md5)))); fs.flush(); mysql_hex_string(md5_hex, (char*)md5, sizeof(md5)); printf("MD5 of file %s stored in database: %s.\n", source_file.data(), md5_hex); fs.clear(); fs.seekg(0, ios::beg); get_md5(fs, md5); mysql_hex_string(md5_hex, (char*)md5, sizeof(md5)); printf("MD5 of file %s: %s.\n", dest_file, md5_hex); } catch(qtl::mysql::error& e) { ASSERT_EXCEPTION(e); } } void TestMysql::get_md5(std::istream& is, unsigned char* result) { std::array buffer; MD5_CTX context; MD5Init(&context); while(!is.eof()) { is.read(&buffer.front(), buffer.size()); MD5Update(&context, (unsigned char*)buffer.data(), (unsigned int)is.gcount()); } MD5Final(result, &context); } int main(int argc, char* argv[]) { Test::TextOutput output(Test::TextOutput::Verbose); cout<