Repository: incubator-hawq Updated Branches: refs/heads/master a1f47072f -> f8fd15e37
HAWQ-723. New Command & PSQL test libraries Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/f8fd15e3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/f8fd15e3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/f8fd15e3 Branch: refs/heads/master Commit: f8fd15e3726f7b19c776393b5aef398702ee7680 Parents: a1f4707 Author: ivan <[email protected]> Authored: Tue May 10 10:20:32 2016 +0800 Committer: ivan <[email protected]> Committed: Tue May 10 10:20:32 2016 +0800 ---------------------------------------------------------------------- src/test/feature/lib/command.cpp | 125 ++++++++++++++++++ src/test/feature/lib/command.h | 44 +++++++ src/test/feature/lib/psql.cpp | 238 ++++++++++++++++++++++++++++++++++ src/test/feature/lib/psql.h | 81 ++++++++++++ 4 files changed, 488 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/f8fd15e3/src/test/feature/lib/command.cpp ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/command.cpp b/src/test/feature/lib/command.cpp new file mode 100644 index 0000000..1760971 --- /dev/null +++ b/src/test/feature/lib/command.cpp @@ -0,0 +1,125 @@ +#include <unistd.h> +#include <iostream> +#include <fstream> +#include "command.h" + +Command& Command::run() +{ + FILE *fp = NULL; + char result[MAX_BUFFER_SIZE] = {0}; + + if (!this->_isCommandValid()) + { + goto error; + } + + fp = popen(this->_cmd_string.append(" 2>&1").c_str(), "r"); + if (NULL == fp) + { + goto error; + } + + this->_result_output.clear(); + while(fgets(result, sizeof(result), fp) != NULL) + { + this->_result_output.append(result); + } + + this->_result_status = pclose(fp); + if (-1 == this->_result_status) + { + goto error; + } + this->_result_status = WEXITSTATUS(this->_result_status); + + if (this->_output_file.length() > 0) + { + this->_saveToFile(); + } + + return *this; + +error: + this->_result_status = -1; + return *this; +} + +Command& Command::setCommand(const std::string& cmd) +{ + this->_cmd_string = cmd; + return *this; +} + +Command& Command::setOutputFile(const std::string& out) +{ + this->_output_file = out; + return *this; +} + +const std::string& Command::getCommand() const +{ + return this->_cmd_string; +} + +const std::string& Command::getResultOutput() const +{ + return this->_result_output; +} + +int Command::getResultStatus() const +{ + return this->_result_status; +} + +bool Command::_isCommandValid() const +{ + if (this->_cmd_string.length() > 0) + { + return true; + } + else + { + return false; + } +} + +void Command::_saveToFile() +{ + std::ofstream out(this->_output_file, std::ofstream::out); + out << this->_result_output; + out.close(); +} + +const std::string& Command::getCommandOutput(const std::string& cmd) +{ + return Command() + .setCommand(cmd) + .run() + .getResultOutput(); +} + +const std::string& Command::getCommandOutput(const std::string& cmd, const std::string& out) +{ + return Command() + .setCommand(cmd) + .setOutputFile(out) + .run() + .getResultOutput(); +} + +int Command::getCommandStatus(const std::string& cmd) +{ + return Command() + .setCommand(cmd) + .run() + .getResultStatus(); +} + +int Command::getCommandStatus(const std::string& cmd, const std::string& out) +{ + return Command() + .setCommand(cmd) + .setOutputFile(out) + .run() + .getResultStatus(); +} http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/f8fd15e3/src/test/feature/lib/command.h ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/command.h b/src/test/feature/lib/command.h new file mode 100644 index 0000000..78da0aa --- /dev/null +++ b/src/test/feature/lib/command.h @@ -0,0 +1,44 @@ +#ifndef __COMMAND_H__ +#define __COMMAND_H__ + +#include <string> + +class Command +{ +public: + Command() : _result_status(-1) {} + explicit Command(const std::string& cmd) : _cmd_string(cmd), + _result_status(-1) {} + Command(const std::string& cmd, const std::string& out) : _cmd_string(cmd), + _output_file(out), + _result_status(-1) {} + virtual ~Command() {} + + Command& run(); + Command& setCommand(const std::string& cmd); + Command& setOutputFile(const std::string& out); + const std::string& getCommand() const; + const std::string& getResultOutput() const; + int getResultStatus() const; + + static const std::string& getCommandOutput(const std::string& cmd); + static const std::string& getCommandOutput(const std::string& cmd, const std::string& out); + static int getCommandStatus(const std::string& cmd); + static int getCommandStatus(const std::string& cmd, const std::string& out); + +private: + Command(const Command&); + const Command& operator=(const Command&); + + bool _isCommandValid() const; + void _saveToFile(); + + std::string _cmd_string; + std::string _output_file; + std::string _result_output; + int _result_status; + + static const int MAX_BUFFER_SIZE = 1024; +}; + +#endif http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/f8fd15e3/src/test/feature/lib/psql.cpp ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/psql.cpp b/src/test/feature/lib/psql.cpp new file mode 100644 index 0000000..b9b7acf --- /dev/null +++ b/src/test/feature/lib/psql.cpp @@ -0,0 +1,238 @@ +#include <iostream> +#include <unistd.h> +#include "psql.h" +#include "command.h" + +#define PSQL_BASIC_DIFF_OPTS "-w -I NOTICE: -I HINT: -I CONTEXT: -I GP_IGNORE:" +#define PSQL_PRETTY_DIFF_OPTS "-w -I NOTICE: -I HINT: -I CONTEXT: -I GP_IGNORE: -C3" + +void PSQLQueryResult::setErrorMessage(const std::string errmsg) +{ + this->_errmsg = errmsg; +} + +const std::string& PSQLQueryResult::getErrorMessage() const +{ + return this->_errmsg; +} + +bool PSQLQueryResult::isError() const +{ + return this->_errmsg.length() > 0; +} + +const std::vector<std::vector<std::string> >& PSQLQueryResult::getRows() const +{ + return this->_rows; +} + +const std::vector<std::string>& PSQLQueryResult::getFields() const +{ + return this->_fields; +} + +const std::vector<std::string>& PSQLQueryResult::getRow(int ri) const +{ + return this->getRows()[ri]; +} + +const std::string& PSQLQueryResult::getData(int ri, int ci) const +{ + return this->getRow(ri)[ci]; +} + +std::string PSQLQueryResult::getData(int ri, const std::string& ck) const +{ + for (int ci=0;ci<this->_fields.size();ci++) + { + if (ck == this->_fields[ci]) + { + return this->getData(ri, ci); + } + } + return ""; +} + +const std::string& PSQLQueryResult::getFieldName(int ci) const +{ + return this->_fields[ci]; +} + +int PSQLQueryResult::rowCount() const +{ + return this->_rows.size(); +} + +int PSQLQueryResult::fieldCount() const +{ + return this->_fields.size(); +} + +void PSQLQueryResult::savePGResult(const PGresult *res) +{ + int i, j; + int nfields = PQnfields(res); + for (i=0; i<nfields; i++) + { + this->_fields.push_back(PQfname(res, i)); + } + + for (i=0; i<PQntuples(res); i++) + { + std::vector<std::string> row; + for (j=0; j<nfields; j++) + { + row.push_back(PQgetvalue(res, i, j)); + } + this->_rows.push_back(row); + } +} + +void PSQLQueryResult::reset() +{ + this->_errmsg.clear(); + this->_rows.clear(); + this->_fields.clear(); +} + +PSQL& PSQL::runSQLCommand(const std::string& sql_cmd) +{ + Command::getCommandStatus(this->_getPSQLQueryCommand(sql_cmd)); + return *this; +} + +PSQL& PSQL::runSQLFile(const std::string& sql_file) +{ + Command::getCommandStatus(this->_getPSQLFileCommand(sql_file)); + return *this; +} + +const PSQLQueryResult& PSQL::getQueryResult(const std::string& sql) +{ + PGconn *conn = NULL; + PGresult *res = NULL; + + conn = PQconnectdb(this->getConnectionString().c_str()); + if (PQstatus(conn) != CONNECTION_OK) + { + this->_result.setErrorMessage(PQerrorMessage(conn)); + goto done; + } + + res = PQexec(conn, sql.c_str()); + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + this->_result.setErrorMessage(PQerrorMessage(conn)); + goto done; + } + + this->_result.reset(); + this->_result.savePGResult(res); + +done: + if (res) + { + PQclear(res); + res = NULL; + } + + if (conn) + { + PQfinish(conn); + conn = NULL; + } + + return this->_result; +} + +PSQL& PSQL::setHost(const std::string& host) +{ + this->_host = host; + return *this; +} + +PSQL& PSQL::setPort(const std::string& port) +{ + this->_port = port; + return *this; +} + +PSQL& PSQL::setUser(const std::string& username) +{ + this->_user = username; + return *this; +} + +PSQL& PSQL::setPassword(const std::string& password) +{ + this->_password = password; + return *this; +} + +PSQL& PSQL::setOutputFile(const std::string& out) +{ + this->_output_file = out; + return *this; +} + +std::string PSQL::getConnectionString() const +{ + // host=localhost port=5432 dbname=mydb + std::string command; + command.append("host=").append(this->_host) + .append(" port=").append(this->_port) + .append(" user=").append(this->_user) + .append(" dbname=").append(this->_dbname); + return command; +} + +const std::string PSQL::_getPSQLBaseCommand() const +{ + std::string command = "psql"; + command.append(" -p ").append(this->_port); + command.append(" -h ").append(this->_host); + command.append(" -U ").append(this->_user); + command.append(" -d ").append(this->_dbname); + if (this->_output_file.length() > 0) + { + command.append(" -o ").append(this->_output_file); + } + + return command; +} + +const std::string PSQL::_getPSQLQueryCommand(const std::string& query) const +{ + std::string command = this->_getPSQLBaseCommand(); + return command.append(" -c '").append(query).append("'"); +} + +const std::string PSQL::_getPSQLFileCommand(const std::string& file) const +{ + std::string command = this->_getPSQLBaseCommand(); + return command.append(" -f ").append(file); +} + +bool PSQL::checkDiff(const std::string& expect_file, const std::string& result_file, bool save_diff) +{ + std::string diff_file = result_file + ".diff"; + std::string command; + command.append("gpdiff.pl ").append(PSQL_BASIC_DIFF_OPTS).append(" ") + .append(expect_file).append(" ") + .append(result_file).append(" ") + .append(" >").append(diff_file); + + if (Command::getCommandStatus(command) == 0) + { + unlink(diff_file.c_str()); + return false; + } + else + { + if (!save_diff) + { + unlink(diff_file.c_str()); + } + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/f8fd15e3/src/test/feature/lib/psql.h ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/psql.h b/src/test/feature/lib/psql.h new file mode 100644 index 0000000..fb6d64c --- /dev/null +++ b/src/test/feature/lib/psql.h @@ -0,0 +1,81 @@ +#ifndef __PSQL_H__ +#define __PSQL_H__ + +#include "libpq-fe.h" +#include <vector> +#include "command.h" + +class PSQLQueryResult +{ +public: + PSQLQueryResult() {} + + void savePGResult(const PGresult *res); + void setErrorMessage(const std::string errmsg); + const std::string& getErrorMessage() const; + bool isError() const; + + const std::vector<std::vector<std::string> >& getRows() const; + const std::vector<std::string>& getFields() const; + + const std::vector<std::string>& getRow(int ri) const; + const std::string& getData(int ri, int ci) const; + std::string getData(int ri, const std::string& ck) const; + const std::string& getFieldName(int ci) const; + + int rowCount() const; + int fieldCount() const; + + void reset(); + +private: + std::string _errmsg; + std::vector<std::vector<std::string> > _rows; + std::vector<std::string> _fields; +}; + +class PSQL +{ +public: + PSQL(const std::string& db, + const std::string& host = "localhost", + const std::string& port = "5432", + const std::string& user = "gpadmin", + const std::string& password = "") : _dbname(db), + _host(host), + _port(port), + _user(user), + _password(password) {} + virtual ~PSQL() {}; + + PSQL& runSQLCommand(const std::string& sql_cmd); + PSQL& runSQLFile(const std::string& sql_file); + const PSQLQueryResult& getQueryResult(const std::string& sql); + + PSQL& setHost(const std::string& host); + PSQL& setPort(const std::string& port); + PSQL& setUser(const std::string& username); + PSQL& setPassword(const std::string& password); + PSQL& setOutputFile(const std::string& out); + std::string getConnectionString() const; + + static bool checkDiff(const std::string& expect_file, const std::string& result_file, bool save_diff = true); + +private: + PSQL(const PSQL&); + const PSQL& operator=(const PSQL&); + + const std::string _getPSQLBaseCommand() const; + const std::string _getPSQLQueryCommand(const std::string& query) const; + const std::string _getPSQLFileCommand(const std::string& file) const; + + std::string _dbname; + std::string _host; + std::string _port; + std::string _user; + std::string _password; + std::string _output_file; + PSQLQueryResult _result; +}; + +#endif
