diff --git a/__tests/CMakeLists.txt b/__tests/CMakeLists.txt new file mode 100644 index 0000000..2214137 --- /dev/null +++ b/__tests/CMakeLists.txt @@ -0,0 +1,7 @@ +# Generated from tests.pro. + +if(QT_BUILD_STANDALONE_TESTS) + # Add qt_find_package calls for extra dependencies that need to be found when building + # the standalone tests here. +endif() +qt_build_tests() diff --git a/__tests/auto/CMakeLists.txt b/__tests/auto/CMakeLists.txt new file mode 100644 index 0000000..787de99 --- /dev/null +++ b/__tests/auto/CMakeLists.txt @@ -0,0 +1,13 @@ +# Generated from auto.pro. + +add_subdirectory(tst_basic) +add_subdirectory(tst_benckmark) +add_subdirectory(tst_datatypes) +add_subdirectory(tst_phrases) +add_subdirectory(tst_properties) +add_subdirectory(tst_qttypes) +add_subdirectory(tst_quuid) +add_subdirectory(tst_generators) +add_subdirectory(tst_upgrades) +add_subdirectory(tst_json) +add_subdirectory(tst_datetime) diff --git a/__tests/auto/auto.pro b/__tests/auto/auto.pro new file mode 100644 index 0000000..4fa7fa1 --- /dev/null +++ b/__tests/auto/auto.pro @@ -0,0 +1,18 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + tst_basic \ + tst_benckmark \ + tst_datatypes \ + tst_phrases \ + tst_properties \ + tst_qttypes \ + tst_quuid \ + tst_generators \ + tst_upgrades \ + tst_json \ + tst_datetime + +cmake.CONFIG += no_run-tests_target +prepareRecursiveTarget(run-tests) +QMAKE_EXTRA_TARGETS += run-tests diff --git a/__tests/auto/cmake/CMakeLists.txt b/__tests/auto/cmake/CMakeLists.txt new file mode 100644 index 0000000..83841c9 --- /dev/null +++ b/__tests/auto/cmake/CMakeLists.txt @@ -0,0 +1,14 @@ + +cmake_minimum_required(VERSION 2.8) + +project(qmake_cmake_files) + +enable_testing() + +find_package(Qt5Core REQUIRED) + +include("${_Qt5CTestMacros}") + +test_module_includes( + Nut QNut +) diff --git a/__tests/auto/cmake/cmake.pro b/__tests/auto/cmake/cmake.pro new file mode 100644 index 0000000..793e741 --- /dev/null +++ b/__tests/auto/cmake/cmake.pro @@ -0,0 +1,7 @@ + +# Cause make to do nothing. +TEMPLATE = subdirs + +CMAKE_QT_MODULES_UNDER_TEST = nut + +CONFIG += ctest_testcase diff --git a/__tests/auto/common/comment.cpp b/__tests/auto/common/comment.cpp new file mode 100644 index 0000000..4fa3fa9 --- /dev/null +++ b/__tests/auto/common/comment.cpp @@ -0,0 +1,67 @@ +#include "comment.h" +#include "post.h" +#include "user.h" + +Comment::Comment(QObject *parent) : Table(parent) +{ + init(); +} + +int Comment::id() const +{ + return m_id; +} + +QString Comment::message() const +{ + return m_message; +} + +QDateTime Comment::saveDate() const +{ + return m_saveDate; +} + +qreal Comment::point() const +{ + return m_point; +} + +void Comment::setId(int id) +{ + if (m_id == id) + return; + + m_id = id; + Q_EMIT idChanged(m_id); +} + +void Comment::setMessage(QString message) +{ + if (m_message == message) + return; + + m_message = message; + Q_EMIT messageChanged(m_message); +} + +void Comment::setSaveDate(QDateTime saveDate) +{ + if (m_saveDate == saveDate) + return; + + m_saveDate = saveDate; + Q_EMIT saveDateChanged(m_saveDate); +} + +void Comment::setPoint(qreal point) +{ + if (qFuzzyCompare(m_point, point)) + return; + + m_point = point; + Q_EMIT pointChanged(m_point); +} + +NUT_FOREIGN_KEY_IMPLEMENT(Comment, Post, int, post, post, setPost) +NUT_FOREIGN_KEY_IMPLEMENT(Comment, User, int, author, author, setAuthor) diff --git a/__tests/auto/common/comment.h b/__tests/auto/common/comment.h new file mode 100644 index 0000000..ecdbb31 --- /dev/null +++ b/__tests/auto/common/comment.h @@ -0,0 +1,66 @@ +#ifndef COMMENT_H +#define COMMENT_H + +#include +#include +#include +#include + +#ifdef NUT_NAMESPACE +using namespace NUT_NAMESPACE; +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +Q_MOC_INCLUDE("user.h") +Q_MOC_INCLUDE("post.h") +#endif + +class User; +class Post; +class Comment : public Table +{ + Q_OBJECT + + Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) + Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged) + Q_PROPERTY(QDateTime saveDate READ saveDate WRITE setSaveDate NOTIFY saveDateChanged) + Q_PROPERTY(qreal point READ point WRITE setPoint NOTIFY pointChanged) + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_FIELD(int, id) + NUT_FIELD(QString, message) + NUT_FIELD(QDateTime, saveDate) + NUT_FIELD(qreal, point) + + NUT_FOREIGN_KEY_DECLARE(Post, int, post, post, setPost) + NUT_FOREIGN_KEY_DECLARE(User, int, author, author, setAuthor) + + int m_id; + QString m_message; + QDateTime m_saveDate; + qreal m_point; + +public: + Q_INVOKABLE explicit Comment(QObject *parentTableSet = nullptr); + + int id() const; + QString message() const; + QDateTime saveDate() const; + qreal point() const; + +public Q_SLOTS: + void setId(int id); + void setMessage(QString message); + void setSaveDate(QDateTime saveDate); + void setPoint(qreal point); + +Q_SIGNALS: + void idChanged(int id); + void messageChanged(QString message); + void saveDateChanged(QDateTime saveDate); + void pointChanged(qreal point); +}; + +Q_DECLARE_METATYPE(Comment*) + +#endif // COMMENT_H diff --git a/__tests/auto/common/consts.h b/__tests/auto/common/consts.h new file mode 100644 index 0000000..96c5a2a --- /dev/null +++ b/__tests/auto/common/consts.h @@ -0,0 +1,65 @@ +#ifndef CONSTS_H +#define CONSTS_H + +#include +#include + +#define REGISTER(x) qDebug() << (#x) << "type id:" << qMetaTypeId() +#define PRINT(x) +//qDebug() << (#x "=") << (x); +#define TIC() QElapsedTimer timer; timer.start() +#define TOC() qDebug() << QStringLiteral("Elapsed time: %1ms for %2") \ + .arg(timer.elapsed() / 1000.) \ + .arg(QString::fromUtf8(__func__)) + + +#define DATABASE QStringLiteral("nut_test_%1_db") \ +.arg(QString::fromUtf8(metaObject()->className())).toLower() +#include "test_params.h" + +/* +#define DRIVER QStringLiteral("QMYSQL") +#define HOST QStringLiteral("192.168.10.2") +#define USERNAME QStringLiteral("root") +#define PASSWORD QStringLiteral("lDexDJGvQwx20sfgtsetDSupmn9") +*/ + + +#ifdef Q_OS_LINUX +# define OS "Linux" +#elif defined(Q_OS_WIN) +# define OS "Windows" +#elif defined(Q_OS_OSX) +# define OS "macOS" +#else +# define OS "Unknown" +#endif + +#ifdef Q_CC_GNU +# ifdef Q_CC_MINGW +# define CC "MinGW" +# else +# define CC "GNU" +# endif +#elif defined (Q_CC_MSVC) +# define CC "msvc" +#elif defined (Q_CC_CLANG) +# define CC "clang" +#else +# define CC "Unknown" +#endif + +#define PRINT_FORM(db) +// qDebug() << "\n\n****************************" \ +// << "\nAll tests passed," \ +// << "please fill in bellow form and email it to me at" \ +// << "hamed.masafi@gmail.com" \ +// << "\n\tDriver:" << db.driver() \ +// << "\n\tOS: " OS " (version: ________)" \ +// << "\n\tCompiler: " CC " (version: ________)" \ +// << "\n\tQt version: " QT_VERSION_STR \ +// << "\n\tTest:" << metaObject()->className() \ +// << "\n****************************\n"; + + +#endif // CONSTS_H diff --git a/__tests/auto/common/mysql/consts.h b/__tests/auto/common/mysql/consts.h new file mode 100644 index 0000000..62ff2df --- /dev/null +++ b/__tests/auto/common/mysql/consts.h @@ -0,0 +1,10 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER QStringLiteral("QMYSQL") +#define DATABASE QStringLiteral("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QString() +#define USERNAME QString() +#define PASSWORD QString() + +#endif // DATABASE_CONSTS_H diff --git a/__tests/auto/common/nut-lib.pri b/__tests/auto/common/nut-lib.pri new file mode 100644 index 0000000..087315a --- /dev/null +++ b/__tests/auto/common/nut-lib.pri @@ -0,0 +1,65 @@ +contains(debug_and_release, CONFIG): message(debug_and_release) + +debug_and_release:!ReleaseBuild:!DebugBuild { + runtarget.target = run-tests + runtarget.CONFIG = recursive + runtarget.recurse_target = run-tests + QMAKE_EXTRA_TARGETS += runtarget +} else { + oneshell.target = .ONESHELL + QMAKE_EXTRA_TARGETS += oneshell + + win32:!win32-g++ { + CONFIG(debug, debug|release): outdir_helper = debug + CONFIG(release, debug|release): outdir_helper = release + runtarget.target = run-tests + !compat_test: runtarget.depends += $(DESTDIR_TARGET) + runtarget.commands += set PATH=$$shell_path($$shadowed($$dirname(_QMAKE_CONF_))/bin);$$shell_path($$[QT_INSTALL_BINS]);$(PATH) + runtarget.commands += $$escape_expand(\\n\\t)set QT_PLUGIN_PATH=$$shadowed($$dirname(_QMAKE_CONF_))/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH) + runtarget.commands += $$escape_expand(\\n\\t)set QML2_IMPORT_PATH=$$shadowed($$dirname(_QMAKE_CONF_))/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH) + !isEmpty(LOGGING_RULES): runtarget.commands += $$escape_expand(\\n\\t)set \"QT_LOGGING_RULES=$$LOGGING_RULES\" + runtarget.commands += $$escape_expand(\\n\\t)if exist $${outdir_helper}\\fail del $${outdir_helper}\\fail + runtarget.commands += $$escape_expand(\\n\\t)start /w call $(DESTDIR_TARGET) ^> $${outdir_helper}\\test.log ^|^| echo FAIL ^> $${outdir_helper}\\fail ^& exit 0 + runtarget.commands += $$escape_expand(\\n\\t)type $${outdir_helper}\\test.log + runtarget.commands += $$escape_expand(\\n\\t)if exist $${outdir_helper}\\fail exit 42 + QMAKE_EXTRA_TARGETS += runtarget + } else { + win32-g++: QMAKE_DIRLIST_SEP = ";" + runtarget.commands += export PATH=\"$$shell_path($$shadowed($$dirname(_QMAKE_CONF_))/bin):$$shell_path($$[QT_INSTALL_BINS]):$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\" + runtarget.commands += $$escape_expand(\\n\\t)export QT_PLUGIN_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\" + runtarget.commands += $$escape_expand(\\n\\t)export QML2_IMPORT_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\" + !isEmpty(LOGGING_RULES): runtarget.commands += $$escape_expand(\\n\\t)export QT_LOGGING_RULES=\"$$LOGGING_RULES\" + win32-g++: QMAKE_DIRLIST_SEP = ":" + + linux|win32-g++ { + runtarget.commands += $$escape_expand(\\n\\t)export LD_LIBRARY_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\" + runtarget.commands += $$escape_expand(\\n\\t)export QT_QPA_PLATFORM=minimal + } else:mac { + runtarget.commands += $$escape_expand(\\n\\t)export DYLD_LIBRARY_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\" + runtarget.commands += $$escape_expand(\\n\\t)export DYLD_FRAMEWORK_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\" + } + + runtarget.target = run-tests + win32-g++ { + !compat_test: runtarget.depends += $(DESTDIR_TARGET) + runtarget.commands += $$escape_expand(\\n\\t)./$(DESTDIR_TARGET) + } else { + !compat_test: runtarget.depends += $(TARGET) + runtarget.commands += $$escape_expand(\\n\\t)./$(TARGET) + } + QMAKE_EXTRA_TARGETS += runtarget + } +} + +INCLUDEPATH += $$PWD/../common + +QT += nut +CONFIG += testcase + +DEFINES += NUT_PATH=\\\"$$PWD/../../\\\" +DEFINES += NUT_PRINT_DEBUG_INFO + +runtarget.target = run-tests +runtarget.CONFIG = recursive +runtarget.recurse_target = run-tests +QMAKE_EXTRA_TARGETS += runtarget diff --git a/__tests/auto/common/pgsql/consts.h b/__tests/auto/common/pgsql/consts.h new file mode 100644 index 0000000..7066d6e --- /dev/null +++ b/__tests/auto/common/pgsql/consts.h @@ -0,0 +1,10 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER QStringLiteral("QPSQL") +#define DATABASE QStringLiteral("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QString() +#define USERNAME QStringLiteral("postgres") +#define PASSWORD QStringLiteral("root") + +#endif // DATABASE_CONSTS_H diff --git a/__tests/auto/common/post.cpp b/__tests/auto/common/post.cpp new file mode 100644 index 0000000..9e87705 --- /dev/null +++ b/__tests/auto/common/post.cpp @@ -0,0 +1,85 @@ +#include "post.h" +#include "comment.h" +#include "score.h" +#include "tableset.h" + +Post::Post(QObject *parent) : Table(parent), + m_id(0), m_title(""), + m_comments(new TableSet(this)), + m_scores(new TableSet(this)) +{ + init(); +} + +int Post::id() const +{ + return m_id; +} + +QString Post::title() const +{ + return m_title; +} + +QDateTime Post::saveDate() const +{ + return m_saveDate; +} + +QString Post::body() const +{ + return m_body; +} + +bool Post::isPublic() const +{ + return m_isPublic; +} + +void Post::setId(int id) +{ + if (m_id == id) + return; + + m_id = id; + Q_EMIT idChanged(m_id); +} + +void Post::setTitle(QString title) +{ + if (m_title == title) + return; + + m_title = title; + Q_EMIT titleChanged(m_title); +} + +void Post::setSaveDate(QDateTime saveDate) +{ + if (m_saveDate == saveDate) + return; + + m_saveDate = saveDate; + Q_EMIT saveDateChanged(m_saveDate); +} + +void Post::setBody(QString body) +{ + if (m_body == body) + return; + + m_body = body; + Q_EMIT bodyChanged(m_body); +} + +void Post::setPublic(bool isPublic) +{ + if (m_isPublic == isPublic) + return; + + m_isPublic = isPublic; + Q_EMIT isPublicChanged(m_isPublic); +} + +NUT_IMPLEMENT_CHILD_TABLE(Post, Comment, comments) +NUT_IMPLEMENT_CHILD_TABLE(Post, Score, scores) diff --git a/__tests/auto/common/post.h b/__tests/auto/common/post.h new file mode 100644 index 0000000..b2feb75 --- /dev/null +++ b/__tests/auto/common/post.h @@ -0,0 +1,79 @@ +#ifndef POST_H +#define POST_H + +#include +#include +#include +#include +#include +#include + +#ifdef NUT_NAMESPACE +using namespace NUT_NAMESPACE; +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +Q_MOC_INCLUDE("comment.h") +Q_MOC_INCLUDE("score.h") +#endif + +class Comment; +class Score; +class Post : public Table +{ + Q_OBJECT + + Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) + Q_PROPERTY(QDateTime saveDate READ saveDate WRITE setSaveDate NOTIFY saveDateChanged) + Q_PROPERTY(QString body READ body WRITE setBody NOTIFY bodyChanged) + Q_PROPERTY(bool isPublic READ isPublic WRITE setPublic NOTIFY isPublicChanged) + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_FIELD(int, id) + + NUT_NOT_NULL(title) + NUT_LEN(title, 50) + NUT_FIELD(QString, title) + + NUT_FIELD(QDateTime, saveDate) + + NUT_FIELD(QString, body) + NUT_FIELD(bool, isPublic) + + NUT_DECLARE_CHILD_TABLE(Comment, comments) + NUT_DECLARE_CHILD_TABLE(Score, scores) + + int m_id; + QString m_title; + QDateTime m_saveDate; + QString m_body; + bool m_isPublic; + +public: + Q_INVOKABLE Post(QObject *parentTableSet = nullptr); + + int id() const; + QString title() const; + QDateTime saveDate() const; + QString body() const; + bool isPublic() const; + +Q_SIGNALS: + void idChanged(int id); + void titleChanged(QString title); + void saveDateChanged(QDateTime saveDate); + void bodyChanged(QString body); + void isPublicChanged(bool isPublic); + +public Q_SLOTS: + void setId(int id); + void setTitle(QString title); + void setSaveDate(QDateTime saveDate); + void setBody(QString body); + void setPublic(bool isPublic); +}; + +Q_DECLARE_METATYPE(Post*) + +#endif // POST_H diff --git a/__tests/auto/common/score.cpp b/__tests/auto/common/score.cpp new file mode 100644 index 0000000..2de623b --- /dev/null +++ b/__tests/auto/common/score.cpp @@ -0,0 +1,11 @@ +#include "score.h" +#include "user.h" +#include "post.h" + +Score::Score(QObject *parent) : NUT_WRAP_NAMESPACE(Table)(parent) +{ + +} + +NUT_FOREIGN_KEY_IMPLEMENT(Score, Post, int, post, post, setPost) +NUT_FOREIGN_KEY_IMPLEMENT(Score, User, QUuid, author, author, setAuthor) diff --git a/__tests/auto/common/score.h b/__tests/auto/common/score.h new file mode 100644 index 0000000..efcad7c --- /dev/null +++ b/__tests/auto/common/score.h @@ -0,0 +1,34 @@ +#ifndef SCORE_H +#define SCORE_H + +#include +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +Q_MOC_INCLUDE("user.h") +Q_MOC_INCLUDE("post.h") +#endif + +class User; +class Post; +class Score : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + + NUT_DECLARE_FIELD(int, score, score, setScore) + + NUT_DECLARE_FIELD(int, condition, condition, setCondition) + + NUT_FOREIGN_KEY_DECLARE(Post, int, post, post, setPost) + NUT_FOREIGN_KEY_DECLARE(User, QUuid, author, author, setAuthor) + +public: + Q_INVOKABLE Score(QObject *parent = Q_NULLPTR); +}; + +#endif // SCORE_H diff --git a/__tests/auto/common/sqlite/consts.h b/__tests/auto/common/sqlite/consts.h new file mode 100644 index 0000000..a6bcaef --- /dev/null +++ b/__tests/auto/common/sqlite/consts.h @@ -0,0 +1,10 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER QStringLiteral("QSQLITE") +#define DATABASE QStringLiteral("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QString() +#define USERNAME QString() +#define PASSWORD QString() + +#endif // DATABASE_CONSTS_H diff --git a/__tests/auto/common/sqlserver/consts.h b/__tests/auto/common/sqlserver/consts.h new file mode 100644 index 0000000..a78782d --- /dev/null +++ b/__tests/auto/common/sqlserver/consts.h @@ -0,0 +1,11 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER "QODBC" +#define DATABASE QString("DRIVER={SQL Server};Server=.;Database=%1;Uid=sa;Port=1433;Pwd=qwe123!@#;WSID=.") \ + .arg(QString("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QStringLiteral(".") +#define USERNAME QString() +#define PASSWORD QString() + +#endif // DATABASE_CONSTS_H diff --git a/__tests/auto/common/test_params.h b/__tests/auto/common/test_params.h new file mode 100644 index 0000000..c1d81c5 --- /dev/null +++ b/__tests/auto/common/test_params.h @@ -0,0 +1,4 @@ +#define DRIVER QStringLiteral("QSQLITE") +#define HOST QString() +#define USERNAME QString() +#define PASSWORD QString() diff --git a/__tests/auto/common/test_params_mssql.h b/__tests/auto/common/test_params_mssql.h new file mode 100644 index 0000000..5bb5c7b --- /dev/null +++ b/__tests/auto/common/test_params_mssql.h @@ -0,0 +1,14 @@ +#include + +#ifdef DATABASE +#undef DATABASE +#endif + +#define DATABASE \ + QStringLiteral("DRIVER={SQL Server Native Client 11.0};Server=localhost;DATABASE=nut_test_%1_db;UID=sa;PWD=NUT_sa_PASS_1_???;") \ + .arg(QString::fromUtf8(metaObject()->className()).toLower()) + +#define DRIVER QStringLiteral("QODBC") +#define HOST QLatin1String("") +#define USERNAME QLatin1String("") +#define PASSWORD QLatin1String("") diff --git a/__tests/auto/common/test_params_mysql.h b/__tests/auto/common/test_params_mysql.h new file mode 100644 index 0000000..94e82f9 --- /dev/null +++ b/__tests/auto/common/test_params_mysql.h @@ -0,0 +1,4 @@ +#define DRIVER QStringLiteral("QMYSQL") +#define HOST QStringLiteral("localhost") +#define USERNAME QStringLiteral("root") +#define PASSWORD QStringLiteral("root") diff --git a/__tests/auto/common/test_params_postgresql.h b/__tests/auto/common/test_params_postgresql.h new file mode 100644 index 0000000..32424bc --- /dev/null +++ b/__tests/auto/common/test_params_postgresql.h @@ -0,0 +1,4 @@ +#define DRIVER QStringLiteral("QPSQL") +#define HOST QStringLiteral("localhost") +#define USERNAME QStringLiteral("postgres") +#define PASSWORD QStringLiteral("postgres") diff --git a/__tests/auto/common/test_params_sqlite.h b/__tests/auto/common/test_params_sqlite.h new file mode 100644 index 0000000..c1d81c5 --- /dev/null +++ b/__tests/auto/common/test_params_sqlite.h @@ -0,0 +1,4 @@ +#define DRIVER QStringLiteral("QSQLITE") +#define HOST QString() +#define USERNAME QString() +#define PASSWORD QString() diff --git a/__tests/auto/common/user.cpp b/__tests/auto/common/user.cpp new file mode 100644 index 0000000..3cbbf47 --- /dev/null +++ b/__tests/auto/common/user.cpp @@ -0,0 +1,55 @@ +#include "comment.h" +#include "score.h" + +#include "user.h" + +User::User(QObject *tableSet) : Nut::Table(tableSet), + m_comments(new Nut::TableSet(this)), + m_scores(new Nut::TableSet(this)) +{ + init(); +} + +int User::id() const +{ + return m_id; +} + +QString User::username() const +{ + return m_username; +} + +QString User::password() const +{ + return m_password; +} + +void User::setId(int id) +{ + if (m_id == id) + return; + + m_id = id; + Q_EMIT idChanged(m_id); +} + +void User::setUsername(QString username) +{ + if (m_username == username) + return; + + m_username = username; + Q_EMIT usernameChanged(m_username); +} + +void User::setPassword(QString password) +{ + if (m_password == password) + return; + + m_password = password; + Q_EMIT passwordChanged(m_password); +} + +NUT_IMPLEMENT_CHILD_TABLE(User, Comment, comments) diff --git a/__tests/auto/common/user.h b/__tests/auto/common/user.h new file mode 100644 index 0000000..01144bd --- /dev/null +++ b/__tests/auto/common/user.h @@ -0,0 +1,68 @@ +#ifndef USER_H +#define USER_H + +#include +#include + +#include +#include +#include + +#ifdef NUT_NAMESPACE +using namespace NUT_NAMESPACE; +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +Q_MOC_INCLUDE("comment.h") +Q_MOC_INCLUDE("score.h") +#endif + +class Comment; +class Score; +class User : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) + Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged) + Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged) + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_FIELD(int, id) + + NUT_NOT_NULL(username) + NUT_LEN(username, 50) + NUT_FIELD(QString, username) + + NUT_NOT_NULL(password) + NUT_LEN(password, 50) + NUT_FIELD(QString, password) + + NUT_DECLARE_CHILD_TABLE(Comment, comments) + NUT_DECLARE_CHILD_TABLE(Score, scores) + + int m_id; + QString m_username; + QString m_password; + +public: + Q_INVOKABLE User(QObject *parentTableSet = nullptr); + + int id() const; + QString username() const; + QString password() const; + +public Q_SLOTS: + void setId(int id); + void setUsername(QString username); + void setPassword(QString password); + +Q_SIGNALS: + void idChanged(int id); + void usernameChanged(QString username); + void passwordChanged(QString password); +}; + +Q_DECLARE_METATYPE(User*) + +#endif // USER_H diff --git a/__tests/auto/common/weblogdatabase.cpp b/__tests/auto/common/weblogdatabase.cpp new file mode 100644 index 0000000..cf459b9 --- /dev/null +++ b/__tests/auto/common/weblogdatabase.cpp @@ -0,0 +1,16 @@ +#include + +#include "user.h" +#include "post.h" +#include "comment.h" +#include "user.h" +#include "score.h" +#include "weblogdatabase.h" + +WeblogDatabase::WeblogDatabase() : Database(), + m_posts(new TableSet(this)), + m_comments(new TableSet(this)), + m_users(new TableSet(this)), + m_scores(new TableSet(this)) +{ +} diff --git a/__tests/auto/common/weblogdatabase.h b/__tests/auto/common/weblogdatabase.h new file mode 100644 index 0000000..af39d01 --- /dev/null +++ b/__tests/auto/common/weblogdatabase.h @@ -0,0 +1,37 @@ +#ifndef TDATABASE_H +#define TDATABASE_H + +#include + +#ifdef NUT_NAMESPACE +using namespace NUT_NAMESPACE; +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +Q_MOC_INCLUDE("user.h") +Q_MOC_INCLUDE("post.h") +Q_MOC_INCLUDE("score.h") +Q_MOC_INCLUDE("comment.h") +#endif + +class Post; +class Comment; +class User; +class Score; +class WeblogDatabase : public Database +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(Post, posts) + NUT_DECLARE_TABLE(Comment, comments) + NUT_DECLARE_TABLE(User, users) + NUT_DECLARE_TABLE(Score, scores) + +public: + WeblogDatabase(); +}; + + +#endif // TDATABASE_H diff --git a/__tests/auto/tst_basic/CMakeLists.txt b/__tests/auto/tst_basic/CMakeLists.txt new file mode 100644 index 0000000..27f1ac5 --- /dev/null +++ b/__tests/auto/tst_basic/CMakeLists.txt @@ -0,0 +1,89 @@ +# Generated from tst_basic.pro. + +##################################################################### +## tst_basic Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_basic LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_basic + SOURCES + ../common/comment.cpp ../common/comment.h + ../common/consts.h + ../common/post.cpp ../common/post.h + ../common/score.cpp ../common/score.h + ../common/user.cpp ../common/user.h + ../common/weblogdatabase.cpp ../common/weblogdatabase.h + tst_basic.cpp tst_basic.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_basic.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_basic/tst_basic.cpp b/__tests/auto/tst_basic/tst_basic.cpp new file mode 100644 index 0000000..97a8daa --- /dev/null +++ b/__tests/auto/tst_basic/tst_basic.cpp @@ -0,0 +1,344 @@ +#include +#include +#include +#include + +#include "consts.h" + +#include "tst_basic.h" +#include "query.h" +#include "tableset.h" +#include "tablemodel.h" +#include "databasemodel.h" + +#include "user.h" +#include "post.h" +#include "comment.h" +#include "score.h" + +BasicTest::BasicTest(QObject *parent) : QObject(parent) +{ +} + +void BasicTest::initTestCase() +{ + //register all entities with Qt-MetaType mechanism + REGISTER(User); + REGISTER(Post); + REGISTER(Score); + REGISTER(Comment); + REGISTER(WeblogDatabase); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + qDebug().noquote() << "Connecting to" << DATABASE; + + bool ok = db.open(); + QVERIFY(ok); + + db.comments()->query().remove(); + db.posts()->query().remove(); + db.users()->query().remove(); + db.scores()->query().remove(); +} + +void BasicTest::dataSchema() +{ +// auto json = db.model().toJson(); +// auto model = DatabaseModel::fromJson(json); + + // qDebug() << model.toJson(); + // qDebug() << db.model().toJson(); + // QTEST_ASSERT(model == db.model()); +} + +void BasicTest::createUser() +{ + user = Nut::create(); + user->setUsername(QStringLiteral("admin")); + user->setPassword(QStringLiteral("123456")); + db.users()->append(user); + QTEST_ASSERT(db.saveChanges() != 0); + QTEST_ASSERT(user->id() != 0); +} + +void BasicTest::createPost() +{ + TIC(); + auto newPost = Nut::create(); + newPost->setTitle(QStringLiteral("post title")); + newPost->setSaveDate(QDateTime::currentDateTime()); + newPost->setPublic(false); + + db.posts()->append(newPost); + + for(int i = 0 ; i < 3; i++){ + auto comment = Nut::create(); + comment->setMessage(QStringLiteral("comment #") + QString::number(i)); + comment->setSaveDate(QDateTime::currentDateTime()); + comment->setAuthorId(user->id()); + newPost->comments()->append(comment); + } + for (int i = 0; i < 10; ++i) { + auto score = Nut::create(); + score->setScore(i % 5); + score->setCondition(1); // test keyword on mysql + newPost->scores()->append(score); + } + + QTEST_ASSERT(db.saveChanges() != 0); + + postId = newPost->id(); + + QTEST_ASSERT(newPost->id() != 0); + + TOC(); +} + +void BasicTest::createPost2() +{ + //create post on the fly + QVariant postIdVar = db.posts()->query().insert( + (Post::titleField() = QStringLiteral("This is a sample")) + & (Post::isPublicField() = true)); + + QVERIFY(postIdVar.type() == QVariant::LongLong + || postIdVar.type() == QVariant::ULongLong + || postIdVar.type() == QVariant::Double); + int postId = postIdVar.toInt(); + + for(int i = 0 ; i < 3; i++){ + auto comment = Nut::create(); + comment->setMessage(QStringLiteral("comment #") + QString::number(i + 2)); + comment->setSaveDate(QDateTime::currentDateTime()); + comment->setAuthor(user); + //join child to master by id + comment->setPostId(postId); + db.comments()->append(comment); + } + QTEST_ASSERT(db.saveChanges() != 0); + + QVERIFY(postId != 0); +} + +void BasicTest::updatePostOnTheFly() +{ + auto c = db.posts()->query() + .where(Post::idField() == postId) + .update(Post::titleField() = QStringLiteral("New title")); + + QCOMPARE(c, 1); + + auto titles = db.posts() + ->query() + .where(Post::idField() == postId) + .select(Post::titleField()); + + QCOMPARE(titles.count(), 1); + QCOMPARE(titles.at(0), QStringLiteral("New title")); +} + +void BasicTest::selectPublicts() +{ + auto publinPostsCount = db.posts()->query() + .where(Post::isPublicField() == true) + .count(); + + auto nonPublicPostsCount = db.posts()->query() + .where(Post::isPublicField() == false) + .count(); + + QCOMPARE(publinPostsCount, 1); + QCOMPARE(nonPublicPostsCount, 1); +} + +void BasicTest::selectPosts() +{ + auto q = db.posts()->query() + .join() + .orderBy((!Post::saveDateField()) | Post::bodyField()) + .where(Post::idField() == postId); + + auto posts = q.toList(); + post = posts.at(0); + post->setBody(QLatin1String()); + + PRINT(posts.length()); + PRINT(posts.at(0)->comments()->length()); + QCOMPARE(posts.length(), 1); + QCOMPARE(posts.at(0)->comments()->length(), 3); + QCOMPARE(posts.at(0)->title(), QStringLiteral("post title")); + + QCOMPARE(posts.at(0)->comments()->at(0)->message(), QStringLiteral("comment #0")); + QCOMPARE(posts.at(0)->comments()->at(1)->message(), QStringLiteral("comment #1")); + QCOMPARE(posts.at(0)->comments()->at(2)->message(), QStringLiteral("comment #2")); + db.cleanUp(); +} + +void BasicTest::selectScoreAverage() +{ + bool ok; + auto avg = db.scores() + ->query() + .join() + .where(Post::idField() == postId) + .average(Score::scoreField()) + .toInt(&ok); + + QVERIFY(ok); + QCOMPARE(avg, 2); +} + +void BasicTest::selectScoreSum() +{ + auto sum = db.scores()->query().sum(Score::scoreField()); + QCOMPARE(sum, 20); +} + +void BasicTest::selectScoreCount() +{ + auto count = db.scores()->query().count(); + QCOMPARE(count, 10); +} + +void BasicTest::selectFirst() +{ + auto posts = db.posts()->query() + .orderBy(Post::idField()) + .first(); + + QVERIFY(posts != Q_NULLPTR); +} + +void BasicTest::selectPostsWithoutTitle() +{ + auto q = db.posts()->query(); + q.where(Post::titleField().isNull()); + auto count = q.count(); + QCOMPARE(count, 0); +} + +void BasicTest::selectPostIds() +{ + auto q = db.posts()->query(); + auto ids = q.select(Post::idField()); + + QCOMPARE(ids.count(), 2); +} + +void BasicTest::selectPostsWithComments() +{ + auto posts = db.posts()->query().join().toList(); + + QCOMPARE(posts.first()->comments()->length(), 3); +} + +void BasicTest::selectCommantsWithPost() +{ + auto comments = db.comments()->query().join().toList(); + QCOMPARE(comments.length(), 6); + QVERIFY(!comments.first()->post().isNull()); +} + +void BasicTest::testDate() +{ + QDateTime d = QDateTime::currentDateTime(); + QTime t = QTime(d.time().hour(), d.time().minute(), d.time().second()); + d.setTime(t); + + auto newPost = Nut::create(); + newPost->setTitle(QStringLiteral("post title")); + newPost->setSaveDate(d); + newPost->setPublic(true); + + db.posts()->append(newPost); + + db.saveChanges(); + + auto q = db.posts()->query() + .where(Post::idField() == newPost->id()) + .orderBy(Post::idField()) + .first(); + + QCOMPARE(q->saveDate(), d); +} + +void BasicTest::testLimitedQuery() +{ + auto comments = db.comments()->query() + .toList(2); + QCOMPARE(comments.length(), 2); +} + +void BasicTest::join() +{ +// TIC(); +// auto q = db.comments()->query() +// ->join() +// ->join(); + +// auto comments = q->toList(); + +// TOC(); +// QTEST_ASSERT(comments.length()); +// QTEST_ASSERT(comments[0]->author()); +// QTEST_ASSERT(comments[0]->author()->username() == "admin"); +} + + +void BasicTest::selectWithInvalidRelation() +{ + auto q = db.posts()->query(); + q.join(QStringLiteral("Invalid_Class_Name")); + q.toList(); +} + +void BasicTest::modifyPost() +{ + auto q = db.posts()->query() + .where(Post::idField() == postId) + .orderBy(Post::idField()); + + Nut::Row post = q.first(); + + QTEST_ASSERT(post != nullptr); + + post->setTitle(QStringLiteral("new name")); + db.saveChanges(); + + q = db.posts()->query() + .where(Post::idField() == postId) + .orderBy(Post::idField()); + + post = q.first(); + PRINT(post->title()); + QCOMPARE(post->title(), "new name"); +} + +void BasicTest::emptyDatabase() +{ +// auto commentsCount = db.comments()->query().remove(); +// auto postsCount = db.posts()->query().remove(); +// QTEST_ASSERT(postsCount == 3); +// QTEST_ASSERT(commentsCount == 6); +} + +void BasicTest::cleanupTestCase() +{ +// post->deleteLater(); +// user->deleteLater(); + + //release models before exiting +// qDeleteAll(TableModel::allModels()); + +// if (QFile::remove("nut_tst_basic")) +// qDebug() << "database removed"; + + PRINT_FORM(db); +} + +QTEST_MAIN(BasicTest) diff --git a/__tests/auto/tst_basic/tst_basic.h b/__tests/auto/tst_basic/tst_basic.h new file mode 100644 index 0000000..1f3163a --- /dev/null +++ b/__tests/auto/tst_basic/tst_basic.h @@ -0,0 +1,52 @@ +#ifndef MAINTEST_H +#define MAINTEST_H + +#include +#include + +#include "weblogdatabase.h" + +class Post; +class User; +class BasicTest : public QObject +{ + Q_OBJECT + WeblogDatabase db; + int postId; + Nut::Row post; + Nut::Row user; + +public: + explicit BasicTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + + void dataSchema(); + void createUser(); + void createPost(); + void createPost2(); + void selectPublicts(); + void join(); + void selectPosts(); + void selectScoreAverage(); + void selectScoreSum(); + void selectScoreCount(); + void selectFirst(); + void selectPostsWithoutTitle(); + void selectPostIds(); + void updatePostOnTheFly(); + void selectPostsWithComments(); + void selectCommantsWithPost(); + void testDate(); + void testLimitedQuery(); + void selectWithInvalidRelation(); + void modifyPost(); + void emptyDatabase(); + + void cleanupTestCase(); +}; + +#endif // MAINTEST_H diff --git a/__tests/auto/tst_basic/tst_basic.pro b/__tests/auto/tst_basic/tst_basic.pro new file mode 100644 index 0000000..0789142 --- /dev/null +++ b/__tests/auto/tst_basic/tst_basic.pro @@ -0,0 +1,25 @@ +QT += testlib sql + +TARGET = tst_basic +TEMPLATE = app +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + ../common/comment.cpp \ + ../common/post.cpp \ + ../common/user.cpp \ + ../common/weblogdatabase.cpp \ + ../common/score.cpp \ + tst_basic.cpp + +HEADERS += \ + ../common/consts.h \ + ../common/comment.h \ + ../common/post.h \ + ../common/user.h \ + ../common/weblogdatabase.h \ + ../common/score.h \ + tst_basic.h + diff --git a/__tests/auto/tst_benckmark/CMakeLists.txt b/__tests/auto/tst_benckmark/CMakeLists.txt new file mode 100644 index 0000000..990032e --- /dev/null +++ b/__tests/auto/tst_benckmark/CMakeLists.txt @@ -0,0 +1,89 @@ +# Generated from tst_benckmark.pro. + +##################################################################### +## tst_benchmark Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_benchmark LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_benchmark + SOURCES + ../common/comment.cpp ../common/comment.h + ../common/consts.h + ../common/post.cpp ../common/post.h + ../common/score.cpp ../common/score.h + ../common/user.cpp ../common/user.h + ../common/weblogdatabase.cpp ../common/weblogdatabase.h + tst_benchmark.cpp tst_benchmark.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_benckmark.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_benckmark/tst_benchmark.cpp b/__tests/auto/tst_benckmark/tst_benchmark.cpp new file mode 100644 index 0000000..0c6119d --- /dev/null +++ b/__tests/auto/tst_benckmark/tst_benchmark.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +#include "consts.h" + +#include "tst_benchmark.h" +#include "query.h" +#include "tableset.h" +#include "tablemodel.h" +#include "databasemodel.h" + +#include "user.h" +#include "post.h" +#include "comment.h" +#include "score.h" + +BenchmarkTest::BenchmarkTest(QObject *parent) : QObject(parent) +{ + +} + +void BenchmarkTest::initTestCase() +{ + REGISTER(User); + REGISTER(Post); + REGISTER(Score); + REGISTER(Comment); + REGISTER(WeblogDatabase); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + bool ok = db.open(); + + QTEST_ASSERT(ok); +} + +void BenchmarkTest::insert1kPost() +{ + QElapsedTimer t; + t.start(); + + for (int i = 0; i < 100; ++i) { + auto newPost = Nut::create(); + newPost->setTitle(QStringLiteral("post title")); + newPost->setSaveDate(QDateTime::currentDateTime()); + + db.posts()->append(newPost); + } + db.saveChanges(); + qDebug("1k post inserted in %lld ms", t.elapsed()); + +} + +QTEST_MAIN(BenchmarkTest) diff --git a/__tests/auto/tst_benckmark/tst_benchmark.h b/__tests/auto/tst_benckmark/tst_benchmark.h new file mode 100644 index 0000000..a624dd1 --- /dev/null +++ b/__tests/auto/tst_benckmark/tst_benchmark.h @@ -0,0 +1,27 @@ +#ifndef MAINTEST_H +#define MAINTEST_H + +#include +#include + +#include "weblogdatabase.h" +class Post; +class BenchmarkTest : public QObject +{ + Q_OBJECT + WeblogDatabase db; + int postId; + Post *post; + Query *q; +public: + explicit BenchmarkTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + + void insert1kPost(); +}; + +#endif // MAINTEST_H diff --git a/__tests/auto/tst_benckmark/tst_benckmark.pro b/__tests/auto/tst_benckmark/tst_benckmark.pro new file mode 100644 index 0000000..19fd248 --- /dev/null +++ b/__tests/auto/tst_benckmark/tst_benckmark.pro @@ -0,0 +1,26 @@ +QT += testlib sql + +TARGET = tst_benchmark +TEMPLATE = app + +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + ../common/comment.cpp \ + ../common/post.cpp \ + ../common/user.cpp \ + ../common/weblogdatabase.cpp \ + ../common/score.cpp \ + tst_benchmark.cpp + +HEADERS += \ + ../common/consts.h \ + ../common/comment.h \ + ../common/post.h \ + ../common/user.h \ + ../common/weblogdatabase.h \ + ../common/score.h \ + tst_benchmark.h + diff --git a/__tests/auto/tst_commands/CMakeLists.txt b/__tests/auto/tst_commands/CMakeLists.txt new file mode 100644 index 0000000..80b782f --- /dev/null +++ b/__tests/auto/tst_commands/CMakeLists.txt @@ -0,0 +1,35 @@ +# Generated from tst_commands.pro. + +##################################################################### +## tst_nut Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_nut LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_nut + QMLTEST + QML_IMPORTPATH + "${CMAKE_CURRENT_BINARY_DIR}/../src/imports" + SOURCES + ../common/comment.cpp ../common/comment.h + ../common/post.cpp ../common/post.h + ../common/user.cpp ../common/user.h + ../common/weblogdatabase.cpp ../common/weblogdatabase.h + tst_commands.cpp tst_commands.h + INCLUDE_DIRECTORIES + ../../src + ../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Qml + Qt::Quick + Qt::Sql +) + +#### Keys ignored in scope 1:.:.:tst_commands.pro:: +# IMPORTPATH = "$$OUT_PWD/../src/imports" +# TEMPLATE = "app" diff --git a/__tests/auto/tst_commands/tst_commands.cpp b/__tests/auto/tst_commands/tst_commands.cpp new file mode 100644 index 0000000..ee234d2 --- /dev/null +++ b/__tests/auto/tst_commands/tst_commands.cpp @@ -0,0 +1,69 @@ +#include +#include +#include + +#include "consts.h" + +#include "tst_commands.h" +#include "query.h" +#include "tableset.h" +#include "tablemodel.h" +#include "databasemodel.h" + +#include "post.h" +#include "comment.h" +#include "user.h" +#include "score.h" + +CommandsTest::CommandsTest(QObject *parent) : QObject(parent) +{ + +} + +void CommandsTest::initTestCase() +{ + REGISTER(Post); + REGISTER(Comment); + REGISTER(WeblogDatabase); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + bool ok = db.open(); + + QTEST_ASSERT(ok); +} + +void CommandsTest::cmd1() +{ + Query *q = db.posts()->query() + ->setWhere(Post::titleField() == "test" && Post::idField() < 4 + 5); + + q->toList(); + + qDebug() << q->sqlCommand(); +} + +void CommandsTest::cmd2() +{ + Query *q = db.posts()->query() + ->setWhere(!Post::idField().in({1, 2, 3, 4})); + + q->toList(); +// q->update(Post::idField()++); + + qDebug() << q->sqlCommand(); +} + +void CommandsTest::join() +{ + auto q = db.posts()->query() + ->join() + ->toList(); + +} + +QTEST_MAIN(CommandsTest) diff --git a/__tests/auto/tst_commands/tst_commands.h b/__tests/auto/tst_commands/tst_commands.h new file mode 100644 index 0000000..fdc1ef5 --- /dev/null +++ b/__tests/auto/tst_commands/tst_commands.h @@ -0,0 +1,29 @@ +#ifndef MAINTEST_H +#define MAINTEST_H + +#include +#include + +#include "weblogdatabase.h" +class Post; +class CommandsTest : public QObject +{ + Q_OBJECT + WeblogDatabase db; + int postId; + Post *post; + Query *q; +public: + explicit CommandsTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + + void cmd1(); + void cmd2(); + void join(); +}; + +#endif // MAINTEST_H diff --git a/__tests/auto/tst_commands/tst_commands.pro b/__tests/auto/tst_commands/tst_commands.pro new file mode 100644 index 0000000..7a0473d --- /dev/null +++ b/__tests/auto/tst_commands/tst_commands.pro @@ -0,0 +1,21 @@ +QT += qml quick testlib sql + +TARGET = tst_nut +CONFIG += warn_on qmltestcase c++11 +INCLUDEPATH += $$PWD/../../src $$PWD/../common +include(../../nut.pri) +TEMPLATE = app +IMPORTPATH += $$OUT_PWD/../src/imports +SOURCES += \ + ../common/comment.cpp \ + ../common/post.cpp \ + ../common/weblogdatabase.cpp \ + ../common/user.cpp \ + tst_commands.cpp + +HEADERS += \ + ../common/comment.h \ + ../common/post.h \ + ../common/weblogdatabase.h \ + ../common/user.h \ + tst_commands.h diff --git a/__tests/auto/tst_datatypes/CMakeLists.txt b/__tests/auto/tst_datatypes/CMakeLists.txt new file mode 100644 index 0000000..9083f2a --- /dev/null +++ b/__tests/auto/tst_datatypes/CMakeLists.txt @@ -0,0 +1,85 @@ +# Generated from tst_datatypes.pro. + +##################################################################### +## tst_datatypes Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_datatypes LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_datatypes + SOURCES + db.cpp db.h + sampletable.cpp sampletable.h + tst_datatypes.cpp tst_datatypes.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_datatypes.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_datatypes/db.cpp b/__tests/auto/tst_datatypes/db.cpp new file mode 100644 index 0000000..e570806 --- /dev/null +++ b/__tests/auto/tst_datatypes/db.cpp @@ -0,0 +1,9 @@ +#include "db.h" + +#include "sampletable.h" + +DB::DB() : Nut::Database (), + m_sampleTables(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_datatypes/db.h b/__tests/auto/tst_datatypes/db.h new file mode 100644 index 0000000..9c39e54 --- /dev/null +++ b/__tests/auto/tst_datatypes/db.h @@ -0,0 +1,21 @@ +#ifndef DB_H +#define DB_H + +#include "database.h" + +class SampleTable; +class DB : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(SampleTable, sampleTables) + +public: + DB(); +}; + +Q_DECLARE_METATYPE(DB*) + +#endif // DB_H diff --git a/__tests/auto/tst_datatypes/sampletable.cpp b/__tests/auto/tst_datatypes/sampletable.cpp new file mode 100644 index 0000000..68a9c9d --- /dev/null +++ b/__tests/auto/tst_datatypes/sampletable.cpp @@ -0,0 +1,6 @@ +#include "sampletable.h" + +SampleTable::SampleTable(QObject *parent) : Nut::Table (parent) +{ + +} diff --git a/__tests/auto/tst_datatypes/sampletable.h b/__tests/auto/tst_datatypes/sampletable.h new file mode 100644 index 0000000..ef36ece --- /dev/null +++ b/__tests/auto/tst_datatypes/sampletable.h @@ -0,0 +1,72 @@ +#ifndef SAMPLETABLE_H +#define SAMPLETABLE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef QT_GUI_LIB +#include +#include +#endif + +#include "table.h" + +#define FIELD_Q(type) NUT_DECLARE_FIELD(q##type, f##type, f##type, setF##type) + +class SampleTable : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + + NUT_DECLARE_FIELD(qint8, f_int8, f_int8, setInt8) + NUT_DECLARE_FIELD(qint16, f_int16, f_int16, setInt16) + NUT_DECLARE_FIELD(qint32, f_int32, f_int32, setInt32) + NUT_DECLARE_FIELD(qint64, f_int64, f_int64, setInt64) + + NUT_DECLARE_FIELD(quint8, f_uint8, f_uint8, setUint8) + NUT_DECLARE_FIELD(quint16, f_uint16, f_uint16, setUint16) + NUT_DECLARE_FIELD(quint32, f_uint32, f_uint32, setUint32) + NUT_DECLARE_FIELD(quint64, f_uint64, f_uint64, setUint64) + + NUT_DECLARE_FIELD(qreal, f_real, f_real, setReal) + NUT_DECLARE_FIELD(float, f_float, f_float, setFloat) +// NUT_DECLARE_FIELD(long double, fldouble, fldouble, setFldouble) + NUT_DECLARE_FIELD(QString, f_string, f_string, setString) + + NUT_DECLARE_FIELD(QTime, f_time, f_time, setTime) + NUT_DECLARE_FIELD(QDate, f_date, f_date, setDate) + NUT_DECLARE_FIELD(QDateTime, f_dateTime, f_dateTime, setDateTime) + + NUT_DECLARE_FIELD(QUuid, f_uuid, f_uuid, setUuid) + + NUT_DECLARE_FIELD(QUrl, f_url, f_url, setUrl) + + NUT_DECLARE_FIELD(QJsonDocument, f_jsonDoc, f_jsonDoc, setJsonDoc) + NUT_DECLARE_FIELD(QJsonObject, f_jsonObj, f_jsonObj, setJsonObj) + NUT_DECLARE_FIELD(QJsonArray, f_jsonArray, f_jsonArray, setJsonArray) + NUT_DECLARE_FIELD(QJsonValue, f_jsonValue, f_jsonValue, setJsonValue) + + NUT_DECLARE_FIELD(QStringList, f_stringList, f_stringList, setStringList) + NUT_DECLARE_FIELD(QChar, f_qchar, f_qchar, setQchar) +#ifdef QT_GUI_LIB + NUT_DECLARE_FIELD(QPoint, f_point, f_point, setPoint) + NUT_DECLARE_FIELD(QPointF, f_pointf, f_pointf, setPointf) + NUT_DECLARE_FIELD(QPolygon, f_polygon, f_polygon, setPolygon) + NUT_DECLARE_FIELD(QPolygonF, f_polygonf, f_polygonf, setPolygonf) + NUT_DECLARE_FIELD(QColor, f_color, f_color, setColor) +#endif +public: + Q_INVOKABLE SampleTable(QObject *parent = Q_NULLPTR); +}; + +Q_DECLARE_METATYPE(SampleTable*) + +#endif // SAMPLETABLE_H diff --git a/__tests/auto/tst_datatypes/tst_datatypes.cpp b/__tests/auto/tst_datatypes/tst_datatypes.cpp new file mode 100644 index 0000000..b2a472a --- /dev/null +++ b/__tests/auto/tst_datatypes/tst_datatypes.cpp @@ -0,0 +1,231 @@ +#include +#include +#include +#include + +#include "consts.h" + +#include "tst_datatypes.h" +#include "query.h" +#include "tableset.h" +#include "tablemodel.h" +#include "databasemodel.h" + +#include "sampletable.h" + +#include +#include + +DataTypesTest::DataTypesTest(QObject *parent) : QObject(parent) +{ +} + +void DataTypesTest::initTestCase() +{ + //register all entities with Qt-MetaType mechanism + REGISTER(SampleTable); + REGISTER(DB); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + QFile::remove(DATABASE); + bool ok = db.open(); + f_int8 = 8; + f_int16 = 16; + f_int32 = 32l; + f_int64 = 64ll; + f_uint8 = 8u; + f_uint16 = 16u; + f_uint32 = 32ul; + f_uint64 = 64ull; + f_real = 1.2; + f_float = 2.3f; + + f_url = QUrl(QStringLiteral("http://google.com/search?q=nut")); + + f_time = QTime::currentTime(); + f_time.setHMS(f_time.hour(), f_time.minute(), f_time.second()); + + f_date = QDate::currentDate(); + f_dateTime = QDateTime::currentDateTime(); + f_dateTime.setTime(f_time); + + f_uuid = QUuid::createUuid(); + f_jsonDoc = QJsonDocument::fromJson("{\"a\": 1}"); + f_jsonObj = f_jsonDoc.object(); + f_jsonArray.insert(0, QJsonValue(1)); + f_jsonArray.insert(1, QJsonValue(QString::fromUtf8("Hi"))); + f_jsonArray.insert(2, QJsonValue(true)); + + f_jsonValue = QJsonValue(true); + + f_stringList.append(QStringLiteral("One")); + f_stringList.append(QStringLiteral("Two")); + f_stringList.append(QStringLiteral("Three")); + f_string = QStringLiteral("this is \n sample ' unescapped \r\n text"); + + f_qchar = QLatin1Char('z'); + +#ifdef QT_GUI_LIB + f_point = QPoint(1, 2); + f_pointf = QPointF(1.2, 3.4); + f_polygon = QPolygon() << QPoint(1, 2) << QPoint(3, 4) << QPoint(5, 6); + f_polygonf = QPolygonF() << QPointF(1.2, 2.3) << QPointF(3.4, 4.5) << QPointF(5.6, 6.7); + f_color = Qt::red; +#endif + + QVERIFY(ok); + + db.sampleTables()->query().remove(); +} + +void DataTypesTest::insert() +{ + auto t = Nut::create(); + + t->setInt8(f_int8); + t->setInt16(f_int16); + t->setInt32(f_int32); + t->setInt64(f_int64); + + t->setUint8(f_uint8); + t->setUint16(f_uint16); + t->setUint32(f_uint32); + t->setUint64(f_uint64); + + t->setReal(f_real); + t->setFloat(f_float); + + t->setUrl(f_url); + + t->setTime(f_time); + t->setDate(f_date); + t->setDateTime(f_dateTime); + t->setUuid(f_uuid); + + t->setJsonDoc(f_jsonDoc); + t->setJsonObj(f_jsonObj); + t->setJsonArray(f_jsonArray); + t->setJsonValue(f_jsonValue); + + t->setString(f_string); + t->setStringList(f_stringList); + t->setQchar(f_qchar); +#ifdef QT_GUI_LIB + t->setColor(f_color); + + t->setPoint(f_point); + t->setPointf(f_pointf); + + t->setPolygon(f_polygon); + t->setPolygonf(f_polygonf); +#endif + db.sampleTables()->append(t); + db.saveChanges(); +} + +void DataTypesTest::retrive() +{ + Nut::RowList list = db.sampleTables()->query().toList(); + QCOMPARE(list.count(), 1); + Nut::Row t = list.first(); + + QCOMPARE(t->f_int8(), f_int8); + QCOMPARE(t->f_int16(), f_int16); + QCOMPARE(t->f_int32(), f_int32); + QCOMPARE(t->f_int64(), f_int64); + + QCOMPARE(t->f_uint8(), f_uint8); + QCOMPARE(t->f_uint16(), f_uint16); + QCOMPARE(t->f_uint32(), f_uint32); + QCOMPARE(t->f_uint64(), f_uint64); + + qDebug() << t->f_real() + << f_real + << qAbs(t->f_real() - f_real) * 1000000000000.f + << qFuzzyCompare(t->f_real(), f_real); +// QCOMPARE(qFuzzyCompare(t->f_real(), f_real)); +// QCOMPARE(qFuzzyCompare(t->f_float(), f_float)); + + + QCOMPARE(t->f_url(), f_url); + QCOMPARE(t->f_uuid(), f_uuid); + + QCOMPARE(t->f_time(), f_time); + QCOMPARE(t->f_date(), f_date); + QCOMPARE(t->f_dateTime(), f_dateTime); + + QCOMPARE(t->f_jsonDoc(), f_jsonDoc); + QCOMPARE(t->f_jsonObj(), f_jsonObj); + QCOMPARE(t->f_jsonArray(), f_jsonArray); + QCOMPARE(t->f_jsonValue(), f_jsonValue); + + QCOMPARE(t->f_string(), f_string); + QCOMPARE(t->f_stringList(), f_stringList); + QCOMPARE(t->f_qchar(), f_qchar); +#ifdef QT_GUI_LIB + QCOMPARE(t->f_point(), f_point); + QCOMPARE(t->f_pointf(), f_pointf); + + QCOMPARE(t->f_polygon(), f_polygon); + QCOMPARE(t->f_polygonf(), f_polygonf); + QCOMPARE(t->f_color(), f_color); +#endif +} + +#define CHECK(name) \ + c = db.sampleTables()->query().where(SampleTable::f_##name##Field() == f_##name).count(); \ + QCOMPARE(c, 1); + +void DataTypesTest::check() +{ + int c; + + CHECK(int8) + CHECK(int16) + CHECK(int32) + CHECK(int64) + CHECK(uint8) + CHECK(uint16) + CHECK(uint32) + CHECK(uint64) + CHECK(real) + CHECK(float) + CHECK(url) + + CHECK(time) + CHECK(date) + CHECK(dateTime) + + CHECK(uuid) +// CHECK(jsonDoc) +// CHECK(jsonObj) +// CHECK(jsonArray) +// CHECK(jsonValue) + + CHECK(string) + CHECK(stringList) + + CHECK(qchar) +#ifdef QT_GUI_LIB + CHECK(point) + CHECK(pointf) + CHECK(polygon) + CHECK(polygonf) + CHECK(color) +#endif +} + +void DataTypesTest::cleanupTestCase() +{ + db.sampleTables()->query().remove(); + db.close(); + + PRINT_FORM(db); +} + +QTEST_MAIN(DataTypesTest) diff --git a/__tests/auto/tst_datatypes/tst_datatypes.h b/__tests/auto/tst_datatypes/tst_datatypes.h new file mode 100644 index 0000000..e0450b5 --- /dev/null +++ b/__tests/auto/tst_datatypes/tst_datatypes.h @@ -0,0 +1,72 @@ +#ifndef MAINTEST_H +#define MAINTEST_H + +#include +#include + +#include +#include +#include +#include +#ifdef QT_GUI_LIB +#include +#include +#endif +#include +#include + +#include "db.h" +class DataTypesTest : public QObject +{ + Q_OBJECT + DB db; + + qint8 f_int8; + qint16 f_int16; + qint32 f_int32; + qint64 f_int64; + quint8 f_uint8; + quint16 f_uint16; + quint32 f_uint32; + quint64 f_uint64; + qreal f_real; + float f_float; + + QTime f_time; + QDate f_date; + QDateTime f_dateTime; + + QJsonDocument f_jsonDoc; + QJsonObject f_jsonObj; + QJsonArray f_jsonArray; + QJsonValue f_jsonValue; + + QString f_string; + QStringList f_stringList; + + QChar f_qchar; + QUrl f_url; + QUuid f_uuid; +#ifdef QT_GUI_LIB + QPoint f_point; + QPointF f_pointf; + QPolygon f_polygon; + QPolygonF f_polygonf; + QColor f_color; +#endif + +public: + explicit DataTypesTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + + void insert(); + void retrive(); + void check(); + void cleanupTestCase(); +}; + +#endif // MAINTEST_H diff --git a/__tests/auto/tst_datatypes/tst_datatypes.pro b/__tests/auto/tst_datatypes/tst_datatypes.pro new file mode 100644 index 0000000..ca0be8c --- /dev/null +++ b/__tests/auto/tst_datatypes/tst_datatypes.pro @@ -0,0 +1,18 @@ +QT += testlib sql gui + +TARGET = tst_datatypes +TEMPLATE = app + +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + db.cpp \ + sampletable.cpp \ + tst_datatypes.cpp + +HEADERS += \ + db.h \ + sampletable.h \ + tst_datatypes.h diff --git a/__tests/auto/tst_datetime/CMakeLists.txt b/__tests/auto/tst_datetime/CMakeLists.txt new file mode 100644 index 0000000..74e87e3 --- /dev/null +++ b/__tests/auto/tst_datetime/CMakeLists.txt @@ -0,0 +1,85 @@ +# Generated from tst_datetime.pro. + +##################################################################### +## tst_datetime Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_datetime LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_datetime + SOURCES + db.cpp db.h + sampletable.cpp sampletable.h + tst_datetime.cpp tst_datetime.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_datetime.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_datetime/db.cpp b/__tests/auto/tst_datetime/db.cpp new file mode 100644 index 0000000..e570806 --- /dev/null +++ b/__tests/auto/tst_datetime/db.cpp @@ -0,0 +1,9 @@ +#include "db.h" + +#include "sampletable.h" + +DB::DB() : Nut::Database (), + m_sampleTables(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_datetime/db.h b/__tests/auto/tst_datetime/db.h new file mode 100644 index 0000000..9c39e54 --- /dev/null +++ b/__tests/auto/tst_datetime/db.h @@ -0,0 +1,21 @@ +#ifndef DB_H +#define DB_H + +#include "database.h" + +class SampleTable; +class DB : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(SampleTable, sampleTables) + +public: + DB(); +}; + +Q_DECLARE_METATYPE(DB*) + +#endif // DB_H diff --git a/__tests/auto/tst_datetime/sampletable.cpp b/__tests/auto/tst_datetime/sampletable.cpp new file mode 100644 index 0000000..68a9c9d --- /dev/null +++ b/__tests/auto/tst_datetime/sampletable.cpp @@ -0,0 +1,6 @@ +#include "sampletable.h" + +SampleTable::SampleTable(QObject *parent) : Nut::Table (parent) +{ + +} diff --git a/__tests/auto/tst_datetime/sampletable.h b/__tests/auto/tst_datetime/sampletable.h new file mode 100644 index 0000000..9936dd1 --- /dev/null +++ b/__tests/auto/tst_datetime/sampletable.h @@ -0,0 +1,27 @@ +#ifndef SAMPLETABLE_H +#define SAMPLETABLE_H + +#include +#include +#include + +#include "table.h" + +class SampleTable : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + + NUT_DECLARE_FIELD(QDate, d, d, setD) + NUT_DECLARE_FIELD(QTime, t, t, setT) + NUT_DECLARE_FIELD(QDateTime, dt, dt, setDT) + +public: + Q_INVOKABLE SampleTable(QObject *parent = nullptr); +}; + +Q_DECLARE_METATYPE(SampleTable*) + +#endif // SAMPLETABLE_H diff --git a/__tests/auto/tst_datetime/tst_datetime.cpp b/__tests/auto/tst_datetime/tst_datetime.cpp new file mode 100644 index 0000000..f453b58 --- /dev/null +++ b/__tests/auto/tst_datetime/tst_datetime.cpp @@ -0,0 +1,219 @@ +#include +#include +#include +#include + +#include "consts.h" + +#include "tst_datetime.h" +#include "query.h" +#include "tableset.h" +#include "tablemodel.h" +#include "databasemodel.h" + +#include "sampletable.h" + +DateTimeTest::DateTimeTest(QObject *parent) : QObject(parent) +{ + _baseDateTime = QDateTime::currentDateTime(); +} + +void DateTimeTest::initTestCase() +{ + //register all entities with Qt-MetaType mechanism + REGISTER(SampleTable); + REGISTER(DB); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + QVERIFY(db.open()); + + db.sampleTables()->query().remove(); +} + +#define TEST_DATE(date, command, n) \ + do { \ + auto s = Nut::create(); \ + s->setD(date); \ + db.sampleTables()->append(s); \ + db.saveChanges(); \ + auto count = db.sampleTables() \ + ->query() \ + .where(SampleTable::dField().command(n) == date.command(n)) \ + .count(); \ + QVERIFY(count > 0); \ + db.sampleTables()->query().remove(); \ + } while (false) + +#define TEST_TIME(time, command, n, num) \ + do { \ + auto s = Nut::create(); \ + s->setT(time); \ + db.sampleTables()->append(s); \ + db.saveChanges(); \ + auto count = db.sampleTables() \ + ->query() \ + .where(SampleTable::tField().command(n) == time.addSecs(num)) \ + .count(); \ + QVERIFY(count > 0); \ + db.sampleTables()->query().remove(); \ + } while (false) + +#define TEST_DATE2(datetime, command, n) \ + do { \ + auto s = Nut::create(); \ + s->setDT(datetime); \ + db.sampleTables()->append(s); \ + db.saveChanges(); \ + auto count = db.sampleTables() \ + ->query() \ + .where(SampleTable::dtField().command(n) == datetime.command(n)) \ + .count(); \ + QVERIFY(count > 0); \ + db.sampleTables()->query().remove(); \ + } while (false) + +#define TEST_TIME2(datetime, command, n, num) \ + do { \ + auto s = Nut::create(); \ + s->setDT(datetime); \ + db.sampleTables()->append(s); \ + db.saveChanges(); \ + auto count = db.sampleTables() \ + ->query() \ + .where(SampleTable::dtField().command(n) == datetime.addSecs(num)) \ + .count(); \ + QVERIFY(count > 0); \ + db.sampleTables()->query().remove(); \ + } while (false) + +#define MINUTE(m) m * 60 +#define HOUR(h) MINUTE(h) * 60 + +void DateTimeTest::dateAdd() +{ + QDate d = QDate::currentDate(); + + TEST_DATE(d, addYears, 10); + TEST_DATE(d, addMonths, 10); + TEST_DATE(d, addDays, 10); + + TEST_DATE(d, addYears, -10); + TEST_DATE(d, addMonths, -10); + TEST_DATE(d, addDays, -10); +} + +void DateTimeTest::timeAdd() +{ + QTime t(12, 34, 56); + + TEST_TIME(t, addHours, 10, HOUR(10)); + TEST_TIME(t, addMinutes, 10, MINUTE(10)); + TEST_TIME(t, addSeconds, 10, 10); + + TEST_TIME(t, addHours, -10, HOUR(-10)); + TEST_TIME(t, addMinutes, -10, MINUTE(-10)); + TEST_TIME(t, addSeconds, -10, -10); +} + +void DateTimeTest::dateTimeAdd() +{ + QDateTime dt({2021, 12, 23}, {12, 34, 56}); + + TEST_DATE2(dt, addYears, 10); + TEST_DATE2(dt, addMonths, 10); + TEST_DATE2(dt, addDays, 10); + + TEST_DATE2(dt, addYears, -10); + TEST_DATE2(dt, addMonths, -10); + TEST_DATE2(dt, addDays, -10); + + + TEST_TIME2(dt, addHours, 10, HOUR(10)); + TEST_TIME2(dt, addMinutes, 10, MINUTE(10)); + TEST_TIME2(dt, addSeconds, 10, 10); + + TEST_TIME2(dt, addHours, -10, HOUR(-10)); + TEST_TIME2(dt, addMinutes, -10, MINUTE(-10)); + TEST_TIME2(dt, addSeconds, -10, -10); +} + +void DateTimeTest::datePart() +{ + db.sampleTables()->query().remove(); + + QDate d = QDate::currentDate(); + auto s = Nut::create(); + s->setD(d); + db.sampleTables()->append(s); + db.saveChanges(); + + int count; + + count = db.sampleTables()->query().where(SampleTable::dField().year() == d.year()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::dField().month() == d.month()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::dField().day() == d.day()).count(); + QVERIFY(count); + +} + +void DateTimeTest::timePart() +{ + db.sampleTables()->query().remove(); + + QTime t = QTime::currentTime(); + auto s = Nut::create(); + s->setT(t); + db.sampleTables()->append(s); + db.saveChanges(); + + int count; + + count = db.sampleTables()->query().where(SampleTable::tField().hour() == t.hour()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::tField().minute() == t.minute()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::tField().second() == t.second()).count(); + QVERIFY(count); +} + +void DateTimeTest::dateTimePart() +{ + db.sampleTables()->query().remove(); + + QDateTime dt = QDateTime::currentDateTime(); + auto s = Nut::create(); + s->setDT(dt); + db.sampleTables()->append(s); + db.saveChanges(); + + int count; + + count = db.sampleTables()->query().where(SampleTable::dtField().year() == dt.date().year()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::dtField().month() == dt.date().month()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::dtField().day() == dt.date().day()).count(); + QVERIFY(count); + + count = db.sampleTables()->query().where(SampleTable::dtField().hour() == dt.time().hour()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::dtField().minute() == dt.time().minute()).count(); + QVERIFY(count); + count = db.sampleTables()->query().where(SampleTable::dtField().second() == dt.time().second()).count(); + QVERIFY(count); +} + +void DateTimeTest::cleanupTestCase() +{ + db.sampleTables()->query().remove(); + db.close(); +} + +QTEST_MAIN(DateTimeTest) diff --git a/__tests/auto/tst_datetime/tst_datetime.h b/__tests/auto/tst_datetime/tst_datetime.h new file mode 100644 index 0000000..923a590 --- /dev/null +++ b/__tests/auto/tst_datetime/tst_datetime.h @@ -0,0 +1,42 @@ +#ifndef MAINTEST_H +#define MAINTEST_H + +#include +#include + +#include +#include +#include +#include +#ifdef QT_GUI_LIB +#include +#include +#endif +#include +#include + +#include "db.h" +class DateTimeTest : public QObject +{ + Q_OBJECT + DB db; + + QDateTime _baseDateTime; + +public: + explicit DateTimeTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + void dateAdd(); + void timeAdd(); + void dateTimeAdd(); + void datePart(); + void timePart(); + void dateTimePart(); + void cleanupTestCase(); +}; + +#endif // MAINTEST_H diff --git a/__tests/auto/tst_datetime/tst_datetime.pro b/__tests/auto/tst_datetime/tst_datetime.pro new file mode 100644 index 0000000..d48e3ae --- /dev/null +++ b/__tests/auto/tst_datetime/tst_datetime.pro @@ -0,0 +1,19 @@ +QT += testlib sql gui + +TARGET = tst_datetime +TEMPLATE = app + +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + db.cpp \ + sampletable.cpp \ + tst_datetime.cpp + +HEADERS += \ + db.h \ + sampletable.h \ + tst_datetime.h + diff --git a/__tests/auto/tst_generators/.gitignore b/__tests/auto/tst_generators/.gitignore new file mode 100644 index 0000000..fab7372 --- /dev/null +++ b/__tests/auto/tst_generators/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/__tests/auto/tst_generators/CMakeLists.txt b/__tests/auto/tst_generators/CMakeLists.txt new file mode 100644 index 0000000..b90e7bf --- /dev/null +++ b/__tests/auto/tst_generators/CMakeLists.txt @@ -0,0 +1,83 @@ +# Generated from tst_generators.pro. + +##################################################################### +## tst_generators Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_generators LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_generators + SOURCES + tst_generators.cpp tst_generators.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_generators.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_generators/tst_generators.cpp b/__tests/auto/tst_generators/tst_generators.cpp new file mode 100644 index 0000000..4ace4af --- /dev/null +++ b/__tests/auto/tst_generators/tst_generators.cpp @@ -0,0 +1,152 @@ +#include + +#include +#include +#include +#include + +#include "tablemodel.h" +#include +#include +#include +#include + +#include "tst_generators.h" + +GeneratorsTest::GeneratorsTest(QObject *parent) : QObject(parent) +{ + +} + + +void GeneratorsTest::types(Nut::AbstractSqlGenerator *g, QString name) +{ + QList types; + types + << QMetaType::Bool + + << QMetaType::Char + << QMetaType::SChar + << QMetaType::UChar + << QMetaType::QChar + + << QMetaType::Short + << QMetaType::UShort + << QMetaType::Int + << QMetaType::UInt + << QMetaType::Long + << QMetaType::LongLong + << QMetaType::ULong + << QMetaType::ULongLong + + << QMetaType::Double + << QMetaType::Float + + << QMetaType::QString + << QMetaType::QStringList + + << QMetaType::QBitArray + << QMetaType::QByteArray + + << QMetaType::QDate + << QMetaType::QTime + << QMetaType::QDateTime + + << QMetaType::QUrl + << QMetaType::QColor + + << QMetaType::QPoint + << QMetaType::QPointF + << QMetaType::QPolygon + << QMetaType::QPolygonF + << QMetaType::QSize + << QMetaType::QSizeF + << QMetaType::QRect + << QMetaType::QRectF + << QMetaType::QLine + << QMetaType::QLineF + + // << QMetaType::QRegion + // << QMetaType::QImage + // << QMetaType::QPixmap + // << QMetaType::QLocale + // << QMetaType::QMatrix + // << QMetaType::QMatrix4x4 + // << QMetaType::QVector2D + // << QMetaType::QVector3D + // << QMetaType::QVector4D + << QMetaType::QJsonValue + << QMetaType::QJsonObject + << QMetaType::QJsonArray + << QMetaType::QJsonDocument + + << QMetaType::QUuid + // << QMetaType::QByteArrayList + ; + + Nut::FieldModel m; + for (auto &t: types) { + m.type = t; + QString fn = g->fieldType(&m); + + QString tn = QString(QMetaType::typeName(t)); + if (!table.contains(tn)) + table.insert(tn, row()); + + table[tn].set(name, fn); + + if (fn.isEmpty()) + qDebug() << "No rule for" << t << "(" << QMetaType::typeName(t) << ")"; + Q_ASSERT(!fn.isEmpty()); + } +} + +void GeneratorsTest::test_sqlite() +{ + auto g = new Nut::SqliteGenerator; + types(g, "sqlite"); + g->deleteLater(); +} + +void GeneratorsTest::test_sqlserver() +{ + auto g = new Nut::SqlServerGenerator; + types(g, "mssql"); + g->deleteLater(); +} + +void GeneratorsTest::test_psql() +{ + auto g = new Nut::PostgreSqlGenerator; + types(g, "psql"); + g->deleteLater(); +} + +void GeneratorsTest::test_mysql() +{ + auto g = new Nut::MySqlGenerator; + types(g, "mysql"); + g->deleteLater(); +} + +void GeneratorsTest::cleanupTestCase() +{ + QMap::const_iterator i; + QString p = "\n| Type | Sqlite | MySql | Postgresql| Ms Sql server |" + "\n|--------|--------|--------|--------|--------|"; + for (i = table.constBegin(); i != table.constEnd(); ++i) { + p.append(QStringLiteral("\n|%1|%2|%3|%4|%5|") + .arg(i.key(), i.value().sqlite, i.value().mysql, + i.value().psql, i.value().mssql)); + } + + QFile file(NUT_PATH "/doc/datatypes.md"); + if (file.open(QIODevice::WriteOnly)) { + file.write(p.toUtf8()); + file.close(); + } +} + +QTEST_MAIN(GeneratorsTest) + +//#include "tst_GeneratorsTest.moc" diff --git a/__tests/auto/tst_generators/tst_generators.h b/__tests/auto/tst_generators/tst_generators.h new file mode 100644 index 0000000..a643d70 --- /dev/null +++ b/__tests/auto/tst_generators/tst_generators.h @@ -0,0 +1,48 @@ +#ifndef TST_GENERATORS_H +#define TST_GENERATORS_H + +#include +#include + +namespace Nut { +class AbstractSqlGenerator; +} + +class GeneratorsTest : public QObject +{ + Q_OBJECT + + struct row { + QString sqlite; + QString psql; + QString mysql; + QString mssql; + void set(QString name, QString value) { + if (name == "sqlite") + sqlite = value.toUpper(); + else if (name == "psql") + psql = value.toUpper(); + else if (name == "mysql") + mysql = value.toUpper(); + else if (name == "mssql") + mssql = value.toUpper(); + } + }; + QMap table; + +public: + explicit GeneratorsTest(QObject *parent = nullptr); + + void types(Nut::AbstractSqlGenerator *g, QString name); + +private Q_SLOTS: + void test_sqlite(); + void test_psql(); + void test_sqlserver(); + void test_mysql(); + + void cleanupTestCase(); + +}; + +#endif // TST_GENERATORS_H diff --git a/__tests/auto/tst_generators/tst_generators.pro b/__tests/auto/tst_generators/tst_generators.pro new file mode 100644 index 0000000..97c1cb9 --- /dev/null +++ b/__tests/auto/tst_generators/tst_generators.pro @@ -0,0 +1,14 @@ +QT += testlib sql + +CONFIG += qt console warn_on depend_includepath testcase +CONFIG -= app_bundle + +TEMPLATE = app + +include(../common/nut-lib.pri) + +SOURCES += \ + tst_generators.cpp + +HEADERS += \ + tst_generators.h diff --git a/__tests/auto/tst_join/CMakeLists.txt b/__tests/auto/tst_join/CMakeLists.txt new file mode 100644 index 0000000..1482ff6 --- /dev/null +++ b/__tests/auto/tst_join/CMakeLists.txt @@ -0,0 +1,37 @@ +# Generated from tst_join.pro. + +##################################################################### +## tst_nut Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_nut LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_nut + QMLTEST + QML_IMPORTPATH + "${CMAKE_CURRENT_BINARY_DIR}/../src/imports" + SOURCES + ../common/comment.cpp ../common/comment.h + ../common/consts.h + ../common/post.cpp ../common/post.h + ../common/score.cpp ../common/score.h + ../common/user.cpp ../common/user.h + ../common/weblogdatabase.cpp ../common/weblogdatabase.h + jointest.cpp jointest.h + INCLUDE_DIRECTORIES + ../../src + ../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Qml + Qt::Quick + Qt::Sql +) + +#### Keys ignored in scope 1:.:.:tst_join.pro:: +# IMPORTPATH = "$$OUT_PWD/../src/imports" +# TEMPLATE = "app" diff --git a/__tests/auto/tst_join/jointest.cpp b/__tests/auto/tst_join/jointest.cpp new file mode 100644 index 0000000..87c2530 --- /dev/null +++ b/__tests/auto/tst_join/jointest.cpp @@ -0,0 +1,77 @@ +#include +#include +#include + +#include "consts.h" + +#include "jointest.h" +#include "query.h" +#include "tableset.h" +#include "tablemodel.h" +#include "databasemodel.h" + +#include "user.h" +#include "post.h" +#include "comment.h" +#include "score.h" + +#define PRINT(x) qDebug() << #x "=" << x; +JoinTest::JoinTest(QObject *parent) : QObject(parent) +{ +} + +void JoinTest::initTestCase() +{ + REGISTER(User); + REGISTER(Post); + REGISTER(Comment); + REGISTER(Score); + REGISTER(WeblogDatabase); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName("nut_tst_join.db"); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + bool ok = db.open(); + +// db.comments()->query()->remove(); +// db.posts()->query()->remove(); + + QTEST_ASSERT(ok); +} + +void JoinTest::join() +{ + auto q = db.comments()->query() + ->join() + ->join(); + +// Comment *comment = q->first(); + auto comments = q->toList(); +// Comment *comment = q->toList().first(); +// qDebug() << q->sqlCommand(); + PRINT(comments.length()); + +// QTEST_ASSERT(comments.length()); +// QTEST_ASSERT(comments[0]->author()); +// QTEST_ASSERT(comments[0]->author()->username() == "admin"); +} + +void JoinTest::join2() +{ + auto q = db.users()->query() + ->join() + ->join(); + +// Comment *comment = q->first(); + auto comments = q->toList(); +// Comment *comment = q->toList().first(); +// qDebug() << q->sqlCommand(); +// QTEST_ASSERT(comments.length()); +// QTEST_ASSERT(comments[0]->author()); +// QTEST_ASSERT(comments[0]->author()->username() == "admin"); +} + +QTEST_MAIN(JoinTest) diff --git a/__tests/auto/tst_join/jointest.h b/__tests/auto/tst_join/jointest.h new file mode 100644 index 0000000..de7499e --- /dev/null +++ b/__tests/auto/tst_join/jointest.h @@ -0,0 +1,26 @@ +#ifndef JOINTEST_H +#define JOINTEST_H + +#include +#include + +#include "weblogdatabase.h" + +class JoinTest : public QObject +{ + Q_OBJECT + WeblogDatabase db; + +public: + explicit JoinTest(QObject *parent = 0); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + + void join(); + void join2(); +}; + +#endif // JOINTEST_H diff --git a/__tests/auto/tst_join/tst_join.pro b/__tests/auto/tst_join/tst_join.pro new file mode 100644 index 0000000..ee955a0 --- /dev/null +++ b/__tests/auto/tst_join/tst_join.pro @@ -0,0 +1,25 @@ +QT += qml quick testlib sql + +TARGET = tst_nut +TEMPLATE = app + +CONFIG += warn_on qmltestcase c++11 +INCLUDEPATH += $$PWD/../../src $$PWD/../common +include(../../nut.pri) +IMPORTPATH += $$OUT_PWD/../src/imports +SOURCES += \ + jointest.cpp \ + ../common/comment.cpp \ + ../common/post.cpp \ + ../common/user.cpp \ + ../common/weblogdatabase.cpp \ + ../common/score.cpp + +HEADERS += \ + jointest.h \ + ../common/consts.h \ + ../common/comment.h \ + ../common/post.h \ + ../common/user.h \ + ../common/weblogdatabase.h \ + ../common/score.h diff --git a/__tests/auto/tst_json/CMakeLists.txt b/__tests/auto/tst_json/CMakeLists.txt new file mode 100644 index 0000000..8b64ef9 --- /dev/null +++ b/__tests/auto/tst_json/CMakeLists.txt @@ -0,0 +1,65 @@ +# Generated from tst_json.pro. + +##################################################################### +## tst_upgrades Binary: +##################################################################### + +qt_internal_add_executable(tst_upgrades + GUI + SOURCES + ../../../src/nut/config/nut_config.h + ../../../src/nut/config/nut_consts.h + ../../../src/nut/config/nut_global.h + ../../../src/nut/config/nut_macros.h + ../../../src/nut/config/nut_namespace.h + ../../../src/nut/core/abstracttableset.cpp ../../../src/nut/core/abstracttableset.h + ../../../src/nut/core/abstracttablesetdata.h + ../../../src/nut/core/bulkinserter.cpp ../../../src/nut/core/bulkinserter.h ../../../src/nut/core/bulkinserter_p.h + ../../../src/nut/core/changelogtable.cpp ../../../src/nut/core/changelogtable.h + ../../../src/nut/core/database.cpp ../../../src/nut/core/database.h ../../../src/nut/core/database_p.h + ../../../src/nut/core/foreigncontainer.cpp ../../../src/nut/core/foreigncontainer.h + ../../../src/nut/core/propertysignalmapper.cpp ../../../src/nut/core/propertysignalmapper.h + ../../../src/nut/core/query.cpp ../../../src/nut/core/query.h + ../../../src/nut/core/table.cpp ../../../src/nut/core/table.h ../../../src/nut/core/table_p.h + ../../../src/nut/core/tableset.cpp ../../../src/nut/core/tableset.h + ../../../src/nut/generators/abstractsqlgenerator.cpp ../../../src/nut/generators/abstractsqlgenerator.h + ../../../src/nut/generators/mysqlgenerator.cpp ../../../src/nut/generators/mysqlgenerator.h + ../../../src/nut/generators/postgresqlgenerator.cpp ../../../src/nut/generators/postgresqlgenerator.h + ../../../src/nut/generators/sqlitegenerator.cpp ../../../src/nut/generators/sqlitegenerator.h + ../../../src/nut/generators/sqlservergenerator.cpp ../../../src/nut/generators/sqlservergenerator.h + ../../../src/nut/models/databasemodel.cpp ../../../src/nut/models/databasemodel.h + ../../../src/nut/models/sqlmodel.cpp ../../../src/nut/models/sqlmodel.h ../../../src/nut/models/sqlmodel_p.h + ../../../src/nut/models/tablemodel.cpp ../../../src/nut/models/tablemodel.h + ../../../src/nut/phrase.cpp ../../../src/nut/phrase.h + ../../../src/nut/phrases/abstractfieldphrase.cpp ../../../src/nut/phrases/abstractfieldphrase.h + ../../../src/nut/phrases/assignmentphrase.cpp ../../../src/nut/phrases/assignmentphrase.h + ../../../src/nut/phrases/assignmentphraselist.cpp ../../../src/nut/phrases/assignmentphraselist.h + ../../../src/nut/phrases/conditionalphrase.cpp ../../../src/nut/phrases/conditionalphrase.h + ../../../src/nut/phrases/fieldphrase.cpp ../../../src/nut/phrases/fieldphrase.h + ../../../src/nut/phrases/fieldphrase_bool.cpp ../../../src/nut/phrases/fieldphrase_bool.h + ../../../src/nut/phrases/fieldphrase_date.cpp ../../../src/nut/phrases/fieldphrase_date.h + ../../../src/nut/phrases/fieldphrase_qstring.cpp ../../../src/nut/phrases/fieldphrase_qstring.h + ../../../src/nut/phrases/phrasedata.cpp ../../../src/nut/phrases/phrasedata.h + ../../../src/nut/phrases/phrasedatalist.cpp ../../../src/nut/phrases/phrasedatalist.h + ../../../src/nut/phrases/phraselist.cpp ../../../src/nut/phrases/phraselist.h + ../../../src/nut/types/dbgeography.cpp ../../../src/nut/types/dbgeography.h + db.cpp db.h + sampletable.cpp sampletable.h + tst_json.cpp tst_json.h + DEFINES + NUT_SHARED_POINTER + INCLUDE_DIRECTORIES + ../../../src/nut + ../../../src/nut/config + ../../../src/nut/core + ../../../src/nut/generators + ../../../src/nut/models + ../../../src/nut/phrases + ../../../src/nut/types + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql +) + +#### Keys ignored in scope 1:.:.:tst_json.pro:: +# TEMPLATE = "app" diff --git a/__tests/auto/tst_json/db.cpp b/__tests/auto/tst_json/db.cpp new file mode 100644 index 0000000..598f17c --- /dev/null +++ b/__tests/auto/tst_json/db.cpp @@ -0,0 +1,9 @@ +#include "db.h" + +#include "sampletable.h" + +DB::DB() : Nut::Database (), + m_sampleTable(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_json/db.h b/__tests/auto/tst_json/db.h new file mode 100644 index 0000000..8149b94 --- /dev/null +++ b/__tests/auto/tst_json/db.h @@ -0,0 +1,22 @@ +#ifndef DB1_H +#define DB1_H + +#include "database.h" + +class Table; + +class DB : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(Table, sampleTable) + +public: + DB(); +}; + +Q_DECLARE_METATYPE(DB*) + +#endif // DB1_H diff --git a/__tests/auto/tst_json/sampletable.cpp b/__tests/auto/tst_json/sampletable.cpp new file mode 100644 index 0000000..3ba992b --- /dev/null +++ b/__tests/auto/tst_json/sampletable.cpp @@ -0,0 +1,7 @@ +#include "sampletable.h" + + +Table::Table(QObject *parent) : Nut::Table (parent) +{ + +} diff --git a/__tests/auto/tst_json/sampletable.h b/__tests/auto/tst_json/sampletable.h new file mode 100644 index 0000000..035803d --- /dev/null +++ b/__tests/auto/tst_json/sampletable.h @@ -0,0 +1,23 @@ +#ifndef TABLE1_H +#define TABLE1_H + +#include "table.h" +#include + +class Table : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + + NUT_DECLARE_FIELD(QJsonDocument, doc, doc, setDoc) + +public: + Q_INVOKABLE Table(QObject *parent = Q_NULLPTR); + +}; + +Q_DECLARE_METATYPE(Table*) + +#endif // TABLE1_H diff --git a/__tests/auto/tst_json/tst_json.cpp b/__tests/auto/tst_json/tst_json.cpp new file mode 100644 index 0000000..76a27e2 --- /dev/null +++ b/__tests/auto/tst_json/tst_json.cpp @@ -0,0 +1,66 @@ +#include + +#include "db.h" +#include "sampletable.h" +#include "query.h" + +#include "tst_json.h" +#include "consts.h" + +void TestJson::initDb(Nut::Database &db) +{ + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); +} + +TestJson::TestJson() +{ + +} + +TestJson::~TestJson() +{ + +} + +void TestJson::initTestCase() +{ + QFile::remove(DATABASE); + REGISTER(DB); + REGISTER(Table); +} + +void TestJson::store() +{ + initDb(db); + + db.open(); + + auto t = Nut::create
(); + QJsonParseError e; + QJsonDocument doc = QJsonDocument::fromJson(R"({"a": 4, "b":3.14})", &e); + qDebug() << e.errorString(); + t->setDoc(doc); + db.sampleTable()->append(t); + db.saveChanges(); + + int id = t->id(); + auto newObj = db.sampleTable()->query() + .where(Table::idField() == id) + .orderBy(Table::idField()) + .first(); + + Q_ASSERT(newObj != nullptr); + Q_ASSERT(newObj->doc() == t->doc()); +} + +void TestJson::cleanupTestCase() +{ + PRINT_FORM(db); +} + +QTEST_APPLESS_MAIN(TestJson) + diff --git a/__tests/auto/tst_json/tst_json.h b/__tests/auto/tst_json/tst_json.h new file mode 100644 index 0000000..ae6cba1 --- /dev/null +++ b/__tests/auto/tst_json/tst_json.h @@ -0,0 +1,33 @@ +#ifndef TST_TESTJSON_H +#define TST_TESTJSON_H + +#include "db.h" + +#include + +namespace Nut { +class Database; +} +class TestJson : public QObject +{ + Q_OBJECT + + DB db; + + void initDb(Nut::Database &db); + + int id; +public: + TestJson(); + ~TestJson(); + +private Q_SLOTS: + void initTestCase(); + + void store(); + + void cleanupTestCase(); + +}; + +#endif // TST_TESTJSON_H diff --git a/__tests/auto/tst_json/tst_json.pro b/__tests/auto/tst_json/tst_json.pro new file mode 100644 index 0000000..0255d18 --- /dev/null +++ b/__tests/auto/tst_json/tst_json.pro @@ -0,0 +1,18 @@ +QT += testlib sql + +TARGET = tst_upgrades +TEMPLATE = app +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) +#include(/doc/dev/qt/Nut/src/nut/nut.pri) + +SOURCES += \ + tst_json.cpp \ + db.cpp \ + sampletable.cpp + +HEADERS += \ + tst_json.h \ + db.h \ + sampletable.h diff --git a/__tests/auto/tst_phrases/CMakeLists.txt b/__tests/auto/tst_phrases/CMakeLists.txt new file mode 100644 index 0000000..e04bb76 --- /dev/null +++ b/__tests/auto/tst_phrases/CMakeLists.txt @@ -0,0 +1,84 @@ +# Generated from tst_phrases.pro. + +##################################################################### +## tst_phrases Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_phrases LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_phrases + SOURCES + generator.cpp generator.h + tst_phrases.cpp tst_phrases.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_phrases.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_phrases/generator.cpp b/__tests/auto/tst_phrases/generator.cpp new file mode 100644 index 0000000..c83cf79 --- /dev/null +++ b/__tests/auto/tst_phrases/generator.cpp @@ -0,0 +1,21 @@ +#include "generator.h" + +Generator::Generator() : Nut::SqliteGenerator() +{ + +} + +QString Generator::where(const Nut::ConditionalPhrase &where) +{ + return createConditionalPhrase(where.data); +} + +QString Generator::order(const Nut::PhraseList &order) +{ + return createOrderPhrase(order); +} + +QString Generator::select(const Nut::PhraseList &select) +{ + return createFieldPhrase(select); +} diff --git a/__tests/auto/tst_phrases/generator.h b/__tests/auto/tst_phrases/generator.h new file mode 100644 index 0000000..535dd1b --- /dev/null +++ b/__tests/auto/tst_phrases/generator.h @@ -0,0 +1,16 @@ +#ifndef GENERATOR_H +#define GENERATOR_H + +#include + +class Generator : public Nut::SqliteGenerator +{ +public: + Generator(); + + QString where(const Nut::ConditionalPhrase &where); + QString order(const Nut::PhraseList &order); + QString select(const Nut::PhraseList &select); +}; + +#endif // GENERATOR_H diff --git a/__tests/auto/tst_phrases/tst_phrases.cpp b/__tests/auto/tst_phrases/tst_phrases.cpp new file mode 100644 index 0000000..e24662c --- /dev/null +++ b/__tests/auto/tst_phrases/tst_phrases.cpp @@ -0,0 +1,220 @@ +#include +#include +#include + +#include "tst_phrases.h" +#include "phrase.h" +#include "generator.h" + +using namespace Nut; + +#define COMPARE_WHERE(w, sql) QCOMPARE(g.where(w), sql); +#define COMPARE_ORDER(o, sql) QCOMPARE(g.order(o), sql); +#define COMPARE_SELECT(s, sql) QCOMPARE(g.select(s), sql); + +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations") +QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") + +PhrasesTest::PhrasesTest(QObject *parent) : QObject(parent) +{ + +} + +void PhrasesTest::initTestCase() +{ + +} + +void PhrasesTest::no1() +{ + { + FieldPhrase id("main", "id"); + FieldPhrase name("main", "name"); + FieldPhrase last_name("main", "last_name"); + FieldPhrase date("main", "date"); + auto w = (id == 4 && name == QStringLiteral("hi")); + + Generator g; + + COMPARE_WHERE(id == 10 || id.in({1, 2, 3, 4}), "([main].id = '10' OR [main].id IN ('1', '2', '3', '4'))"); + } +} + +void PhrasesTest::condition_numeric_sqlite() +{ + Generator g; + + + FieldPhrase n("main", "int"); + FieldPhrase f("main", "float"); + + COMPARE_WHERE(n < 1, "[main].int < '1'"); + COMPARE_WHERE(n > 1, "[main].int > '1'"); + COMPARE_WHERE(n <= 1, "[main].int <= '1'"); + COMPARE_WHERE(n >= 1, "[main].int >= '1'"); + COMPARE_WHERE(n != 1, "[main].int <> '1'"); + COMPARE_WHERE(n == 1, "[main].int = '1'"); + COMPARE_WHERE(n++, "[main].int + '1'"); + COMPARE_WHERE(++n, "[main].int + '1'"); + COMPARE_WHERE(n.between(10, 20), "[main].int BETWEEN '10' AND '20'"); + COMPARE_WHERE(n + 1 < n + 4, "[main].int + '1' < [main].int + '4'"); + + auto p1 = n == 1; + auto p2 = n <= 4; + auto p3 = n >= 5; + auto p4 = n < 7; + + COMPARE_WHERE(p1 && p2, "([main].int = '1' AND [main].int <= '4')"); + COMPARE_WHERE(p3 == p4, "[main].int >= '5' = [main].int < '7'"); + COMPARE_WHERE(f == n + 1, "[main].float = [main].int + '1'"); + COMPARE_WHERE(f == 1.4 || (n == n + 1 && n < 100), + "([main].float = '1.4' OR ([main].int = [main].int + '1' AND [main].int < '100'))"); + + auto p24 = n = 4; + auto p26 = (n = 4) & (n = 5); + auto p27 = n | f; +} + +void PhrasesTest::condition_string_sqlite() +{ + Generator g; + FieldPhrase str("main", "string"); + + COMPARE_WHERE(str == "Hi", "[main].string = 'Hi'"); + COMPARE_WHERE(str.like("%hi%"), "[main].string LIKE '%hi%'"); + COMPARE_WHERE(str.isNull(), "[main].string IS NULL"); + COMPARE_WHERE(!str.isNull(), "[main].string IS NOT NULL"); + COMPARE_WHERE(str.in(QStringList() << "one" + << "two" + << "three"), + "[main].string IN ('one', 'two', 'three')"); + + COMPARE_WHERE(!str.in(QStringList() << "one" + << "two" + << "three"), + "[main].string NOT IN ('one', 'two', 'three')"); + COMPARE_WHERE(str != "hi" && str.like("%s"), + "([main].string <> 'hi' AND [main].string LIKE '%s')"); +} + +void PhrasesTest::condition_bool_sqlite() +{ + Generator g; + FieldPhrase b("main", "bool"); + + COMPARE_WHERE(b, "[main].bool = 'true'"); + COMPARE_WHERE(!b, "[main].bool = 'false'"); + COMPARE_WHERE(b == true, "[main].bool = 'true'"); + COMPARE_WHERE(b == false, "[main].bool = 'false'"); +} + +void PhrasesTest::condition_datetime_sqlite() +{ + Generator g; + + FieldPhrase time("main", "time"); + FieldPhrase date("main", "date"); + FieldPhrase datetime("main", "datetime"); + + QDate d(2020, 2, 20); + QTime t(12, 34, 56); + QDateTime dt(d, t); + + COMPARE_WHERE(time.hour() == 1, "CAST(strftime('%H', [main].time) AS INT) = '1'"); + COMPARE_WHERE(time.minute() == 2, "CAST(strftime('%M', [main].time) AS INT) = '2'"); + COMPARE_WHERE(time.second() == 3, "CAST(strftime('%S', [main].time) AS INT) = '3'"); + + COMPARE_WHERE(date.year() == 1, "CAST(strftime('%Y', [main].date) AS INT) = '1'"); + COMPARE_WHERE(date.month() == 2, "CAST(strftime('%m', [main].date) AS INT) = '2'"); + COMPARE_WHERE(date.day() == 3, "CAST(strftime('%d', [main].date) AS INT) = '3'"); + + COMPARE_WHERE(time.isNull(), "[main].time IS NULL"); + COMPARE_WHERE(!time.isNull(), "[main].time IS NOT NULL"); + COMPARE_WHERE(time == t, "[main].time = '12:34:56'"); + COMPARE_WHERE(time.between(t.addSecs(-10), + t), + "[main].time BETWEEN '12:34:46' AND '12:34:56'"); + COMPARE_WHERE(date.addDays(2) == d, "DATE([main].date,'+2 DAY') = '2020-02-20'"); + COMPARE_WHERE(time.addMinutes(-3) == t, "TIME([main].time,'-3 MINUTE') = '12:34:56'"); + COMPARE_WHERE(datetime.addMinutes(1) == dt, "DATETIME([main].datetime,'+1 MINUTE') = '2020-02-20 12:34:56'"); +} + +void PhrasesTest::order_sqlite() +{ + Generator g; + + FieldPhrase id("main", "id"); + FieldPhrase name("main", "name"); + FieldPhrase last_name("main", "last_name"); + + COMPARE_ORDER(id, "[main].id"); + COMPARE_ORDER(id | name, "[main].id, [main].name"); + COMPARE_ORDER(id | !name | last_name, "[main].id, [main].name DESC, [main].last_name"); +} + +void PhrasesTest::select_sqlite() +{ + Generator g; + + FieldPhrase id("main", "id"); + FieldPhrase name("main", "name"); + FieldPhrase last_name("main", "last_name"); + + COMPARE_ORDER(id, "[main].id"); + COMPARE_ORDER(id | name, "[main].id, [main].name"); + COMPARE_ORDER(id | name | last_name, "[main].id, [main].name, [main].last_name"); +} + +void PhrasesTest::extra() +{ + Generator g; + FieldPhrase url("main", "url"); + + COMPARE_WHERE(url == QUrl("http://google.com"), "[main].url = 'http://google.com'"); +} + +void PhrasesTest::mix() +{ + FieldPhrase id("", ""); + FieldPhrase name("", ""); + FieldPhrase lastName("", ""); + FieldPhrase birthDate("", ""); + + select(id); + select(id | name | lastName); + update((name = "john") & (lastName = "snow")); + insert(id = 0); + insert((id = 4) & (name = "john")); + order_by(id); + order_by(id | !name); +} + +void PhrasesTest::select(const PhraseList &ph) +{ + QTEST_ASSERT(ph.data.count()); +} + +void PhrasesTest::where(const ConditionalPhrase &ph) +{ + QTEST_ASSERT(ph.data); +} + +void PhrasesTest::update(const AssignmentPhraseList &p) +{ + QTEST_ASSERT(p.data.count()); +} + +void PhrasesTest::insert(const AssignmentPhraseList &p) +{ + QTEST_ASSERT(p.data.count()); +} + +void PhrasesTest::order_by(const PhraseList &ph) +{ + QTEST_ASSERT(ph.data.count()); +} + +QTEST_MAIN(PhrasesTest) + +QT_WARNING_POP diff --git a/__tests/auto/tst_phrases/tst_phrases.h b/__tests/auto/tst_phrases/tst_phrases.h new file mode 100644 index 0000000..cc621ae --- /dev/null +++ b/__tests/auto/tst_phrases/tst_phrases.h @@ -0,0 +1,48 @@ +#ifndef MAINTEST_H +#define MAINTEST_H + +#include +#include + +class Post; +class User; + +namespace Nut { +class PhraseList; +class AssignmentPhraseList; +class ConditionalPhrase; +} +class PhrasesTest : public QObject +{ + Q_OBJECT + +public: + explicit PhrasesTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + + void condition_numeric_sqlite(); + void condition_string_sqlite(); + void condition_bool_sqlite(); + void condition_datetime_sqlite(); + + void order_sqlite(); + void select_sqlite(); + + void extra(); + + void no1(); + void mix(); + +private: + void select(const Nut::PhraseList &ph); + void where(const Nut::ConditionalPhrase &ph); + void update(const Nut::AssignmentPhraseList &p); + void insert(const Nut::AssignmentPhraseList &p); + void order_by(const Nut::PhraseList &ph); +}; + +#endif // MAINTEST_H diff --git a/__tests/auto/tst_phrases/tst_phrases.pro b/__tests/auto/tst_phrases/tst_phrases.pro new file mode 100644 index 0000000..b4b94d4 --- /dev/null +++ b/__tests/auto/tst_phrases/tst_phrases.pro @@ -0,0 +1,17 @@ +QT += testlib sql + +TARGET = tst_phrases +TEMPLATE = app + +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + generator.cpp \ + tst_phrases.cpp + +HEADERS += \ + generator.h \ + tst_phrases.h + diff --git a/__tests/auto/tst_properties/CMakeLists.txt b/__tests/auto/tst_properties/CMakeLists.txt new file mode 100644 index 0000000..69a50ee --- /dev/null +++ b/__tests/auto/tst_properties/CMakeLists.txt @@ -0,0 +1,85 @@ +# Generated from tst_properties.pro. + +##################################################################### +## tst_basic Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_basic LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_basic + SOURCES + sampledatabase.cpp sampledatabase.h + sampletable.cpp sampletable.h + tst_properties.cpp tst_properties.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_properties.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_properties/sampledatabase.cpp b/__tests/auto/tst_properties/sampledatabase.cpp new file mode 100644 index 0000000..86f5c2d --- /dev/null +++ b/__tests/auto/tst_properties/sampledatabase.cpp @@ -0,0 +1,8 @@ +#include "sampledatabase.h" +#include "sampletable.h" + +SampleDataBase::SampleDataBase() : Nut::Database() + , m_items(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_properties/sampledatabase.h b/__tests/auto/tst_properties/sampledatabase.h new file mode 100644 index 0000000..baebf12 --- /dev/null +++ b/__tests/auto/tst_properties/sampledatabase.h @@ -0,0 +1,17 @@ +#ifndef SAMPLEDATABASE_H +#define SAMPLEDATABASE_H + +#include + +class SampleTable; +class SampleDataBase : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + NUT_DB_VERSION(1) + NUT_DECLARE_TABLE(SampleTable, items) + +public: + SampleDataBase(); +}; + +#endif // SAMPLEDATABASE_H diff --git a/__tests/auto/tst_properties/sampletable.cpp b/__tests/auto/tst_properties/sampletable.cpp new file mode 100644 index 0000000..2b3cb6a --- /dev/null +++ b/__tests/auto/tst_properties/sampletable.cpp @@ -0,0 +1,48 @@ +#include "sampletable.h" + +SampleTable::SampleTable(QObject *parent) : Nut::Table(parent) +{ + init(); +} + +int SampleTable::id() const +{ + return m_id; +} + +QString SampleTable::name() const +{ + return m_name; +} + +QString SampleTable::lastName() const +{ + return m_lastName; +} + +void SampleTable::setId(int id) +{ + if (m_id == id) + return; + + m_id = id; + Q_EMIT idChanged(m_id); +} + +void SampleTable::setName(QString name) +{ + if (m_name == name) + return; + + m_name = name; + Q_EMIT nameChanged(m_name); +} + +void SampleTable::setLastName(QString lastName) +{ + if (m_lastName == lastName) + return; + + m_lastName = lastName; + Q_EMIT lastNameChanged(m_lastName); +} diff --git a/__tests/auto/tst_properties/sampletable.h b/__tests/auto/tst_properties/sampletable.h new file mode 100644 index 0000000..2b4a399 --- /dev/null +++ b/__tests/auto/tst_properties/sampletable.h @@ -0,0 +1,40 @@ +#ifndef SAMPLETABLE_H +#define SAMPLETABLE_H + +#include + +class SampleTable : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY lastNameChanged) + + int m_id; + QString m_name; + QString m_lastName; + + NUT_PRIMARY_KEY(id) + NUT_FIELD(int, id) + NUT_FIELD(QString, name) + NUT_FIELD(QString, lastName) + +public: + explicit SampleTable(QObject *parent = nullptr); + + int id() const; + QString name() const; + QString lastName() const; + +public Q_SLOTS: + void setId(int id); + void setName(QString name); + void setLastName(QString lastName); + +Q_SIGNALS: + void idChanged(int id); + void nameChanged(QString name); + void lastNameChanged(QString lastName); +}; + +#endif // SAMPLETABLE_H diff --git a/__tests/auto/tst_properties/tst_properties.cpp b/__tests/auto/tst_properties/tst_properties.cpp new file mode 100644 index 0000000..56bfc02 --- /dev/null +++ b/__tests/auto/tst_properties/tst_properties.cpp @@ -0,0 +1,70 @@ +#include +#include "tst_properties.h" +#include "sampledatabase.h" +#include "sampletable.h" +#include "../common/consts.h" +#include + +PropertiesTest::PropertiesTest(QObject *parent) : QObject(parent) +{ +} + +void PropertiesTest::initTestCase() +{ + + REGISTER(SampleTable); + REGISTER(SampleDataBase); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + bool ok = db.open(); + QVERIFY(ok); + + db.items()->query().remove(); +} + +void PropertiesTest::insert() +{ + auto s = new SampleTable; + s->setId(1); + s->setName("hamed"); + s->setLastName("masafi"); + db.items()->append(s); + auto c = db.saveChanges(); // returns count of affected rows + QCOMPARE(c, 1); +} + +void PropertiesTest::select() +{ + auto item = db.items()->query() + .where(SampleTable::nameField() == "hamed" && SampleTable::lastNameField() == "masafi") + .first(); + QCOMPARE(item->name(), "hamed"); +} + +void PropertiesTest::parallelUpdate() +{ + auto item1 = db.items()->query() + .first(); + { + auto item2 = db.items()->query() + .first(); + + item2->setLastName("masafi 2"); + db.saveChanges(); + } + item1->setName("hamed 2"); + db.saveChanges(); + + auto item = db.items()->query() + .first(); + + QCOMPARE(item->name(), "hamed 2"); + QCOMPARE(item->lastName(), "masafi 2"); +} + +QTEST_MAIN(PropertiesTest) diff --git a/__tests/auto/tst_properties/tst_properties.h b/__tests/auto/tst_properties/tst_properties.h new file mode 100644 index 0000000..90c6491 --- /dev/null +++ b/__tests/auto/tst_properties/tst_properties.h @@ -0,0 +1,26 @@ +#ifndef TST_PROPERTIES_H +#define TST_PROPERTIES_H + +#include +#include + +#include "sampledatabase.h" + +class PropertiesTest : public QObject +{ + Q_OBJECT + SampleDataBase db; + +public: + explicit PropertiesTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + void insert(); + void select(); + void parallelUpdate(); +}; + +#endif // TST_PROPERTIES_H diff --git a/__tests/auto/tst_properties/tst_properties.pro b/__tests/auto/tst_properties/tst_properties.pro new file mode 100644 index 0000000..59933c5 --- /dev/null +++ b/__tests/auto/tst_properties/tst_properties.pro @@ -0,0 +1,19 @@ +QT += testlib sql + +TARGET = tst_basic +TEMPLATE = app + +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + sampledatabase.cpp \ + sampletable.cpp \ + tst_properties.cpp + +HEADERS += \ + sampledatabase.h \ + sampletable.h \ + tst_properties.h + diff --git a/__tests/auto/tst_qttypes/CMakeLists.txt b/__tests/auto/tst_qttypes/CMakeLists.txt new file mode 100644 index 0000000..4756615 --- /dev/null +++ b/__tests/auto/tst_qttypes/CMakeLists.txt @@ -0,0 +1,85 @@ +# Generated from tst_qttypes.pro. + +##################################################################### +## tst_qttypes Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qttypes LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qttypes + SOURCES + db.cpp db.h + sampletable.cpp sampletable.h + tst_qttypes.cpp tst_qttypes.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_qttypes.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_qttypes/db.cpp b/__tests/auto/tst_qttypes/db.cpp new file mode 100644 index 0000000..e4ed911 --- /dev/null +++ b/__tests/auto/tst_qttypes/db.cpp @@ -0,0 +1,9 @@ +#include "db.h" + +#include "sampletable.h" + +DB::DB(): Nut::Database (), + m_sampleTables(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_qttypes/db.h b/__tests/auto/tst_qttypes/db.h new file mode 100644 index 0000000..7451e98 --- /dev/null +++ b/__tests/auto/tst_qttypes/db.h @@ -0,0 +1,19 @@ +#ifndef DB_H +#define DB_H + +#include "database.h" + +class SampleTable; +class DB : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(SampleTable, sampleTables) + +public: + DB(); +}; + +#endif // DB_H diff --git a/__tests/auto/tst_qttypes/sampletable.cpp b/__tests/auto/tst_qttypes/sampletable.cpp new file mode 100644 index 0000000..9cafb3c --- /dev/null +++ b/__tests/auto/tst_qttypes/sampletable.cpp @@ -0,0 +1,6 @@ +#include "sampletable.h" + +SampleTable::SampleTable(QObject *parent) : Nut::Table(parent) +{ + +} diff --git a/__tests/auto/tst_qttypes/sampletable.h b/__tests/auto/tst_qttypes/sampletable.h new file mode 100644 index 0000000..7ad4775 --- /dev/null +++ b/__tests/auto/tst_qttypes/sampletable.h @@ -0,0 +1,29 @@ +#ifndef SAMPLETABLE_H +#define SAMPLETABLE_H + +#include +#include +#include +#include +#include + +#include "table.h" + +class SampleTable : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + + NUT_DECLARE_FIELD(QPoint, f_point, f_point, setPoint) + NUT_DECLARE_FIELD(QPointF, f_pointf, f_pointf, setPointf) + NUT_DECLARE_FIELD(QPolygon, f_polygon, f_polygon, setPolygon) + NUT_DECLARE_FIELD(QPolygonF, f_polygonf, f_polygonf, setPolygonf) + NUT_DECLARE_FIELD(QColor, f_color, f_color, setColor) + +public: + SampleTable(QObject *parent = nullptr); +}; + +#endif // SAMPLETABLE_H diff --git a/__tests/auto/tst_qttypes/tst_qttypes.cpp b/__tests/auto/tst_qttypes/tst_qttypes.cpp new file mode 100644 index 0000000..fdcb4e9 --- /dev/null +++ b/__tests/auto/tst_qttypes/tst_qttypes.cpp @@ -0,0 +1,53 @@ +#include "db.h" + + +#include "consts.h" + +#include "sampletable.h" +#include "tst_qttypes.h" + +#include + + +QtTypes::QtTypes() +{ + REGISTER(SampleTable); + REGISTER(DB); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + QFile::remove(DATABASE); + + QVERIFY(db.open()); +} + +QtTypes::~QtTypes() +{ + +} + +void QtTypes::insert() +{ + auto t = Nut::create(); + t->setPointf({1.2, 3.4}); + db.sampleTables()->append(t); + db.saveChanges(); + + auto t2 = db.sampleTables()->query().first(); + QCOMPARE(t->f_pointf(), t2->f_pointf()); +} + +void QtTypes::update(){ + auto t = db.sampleTables()->query().first(); + t->setPointf({5.6, 7.8}); + db.saveChanges(); + + auto t2 = db.sampleTables()->query().first(); + QCOMPARE(t->f_pointf(), t2->f_pointf()); +} + +QTEST_APPLESS_MAIN(QtTypes) diff --git a/__tests/auto/tst_qttypes/tst_qttypes.h b/__tests/auto/tst_qttypes/tst_qttypes.h new file mode 100644 index 0000000..e09ed16 --- /dev/null +++ b/__tests/auto/tst_qttypes/tst_qttypes.h @@ -0,0 +1,23 @@ +#ifndef TST_QTTYPES_H +#define TST_QTTYPES_H + +#include "db.h" + +#include +class QtTypes : public QObject +{ + Q_OBJECT + + DB db; + +public: + QtTypes(); + ~QtTypes(); + +private slots: + void insert(); + void update(); + +}; + +#endif // TST_QTTYPES_H diff --git a/__tests/auto/tst_qttypes/tst_qttypes.pro b/__tests/auto/tst_qttypes/tst_qttypes.pro new file mode 100644 index 0000000..08b2017 --- /dev/null +++ b/__tests/auto/tst_qttypes/tst_qttypes.pro @@ -0,0 +1,17 @@ +QT += testlib sql gui + +CONFIG += qt console warn_on depend_includepath testcase +CONFIG -= app_bundle + +TEMPLATE = app + +SOURCES += tst_qttypes.cpp \ + db.cpp \ + sampletable.cpp + +include(../common/nut-lib.pri) + +HEADERS += \ + db.h \ + sampletable.h \ + tst_qttypes.h diff --git a/__tests/auto/tst_quuid/CMakeLists.txt b/__tests/auto/tst_quuid/CMakeLists.txt new file mode 100644 index 0000000..bf12f89 --- /dev/null +++ b/__tests/auto/tst_quuid/CMakeLists.txt @@ -0,0 +1,86 @@ +# Generated from tst_quuid.pro. + +##################################################################### +## tst_uuid Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_uuid LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_uuid + SOURCES + ../common/consts.h + test.cpp test.h + testdatabase.cpp testdatabase.h + tst_uuid.cpp tst_uuid.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_quuid.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_quuid/test.cpp b/__tests/auto/tst_quuid/test.cpp new file mode 100644 index 0000000..dba4a65 --- /dev/null +++ b/__tests/auto/tst_quuid/test.cpp @@ -0,0 +1,6 @@ +#include "test.h" + +Test::Test(QObject *parentTableSet) : Table(parentTableSet) +{ + +} diff --git a/__tests/auto/tst_quuid/test.h b/__tests/auto/tst_quuid/test.h new file mode 100644 index 0000000..a02b970 --- /dev/null +++ b/__tests/auto/tst_quuid/test.h @@ -0,0 +1,22 @@ +#ifndef TEST_H +#define TEST_H + +#include + +#include "table.h" + +class Test : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_KEY(id) + NUT_DECLARE_FIELD(QUuid, id, id, setId) + NUT_DECLARE_FIELD(QUuid, uuid, uuid, setUuid) + +public: + Q_INVOKABLE Test(QObject *parentTableSet = nullptr); +}; + +Q_DECLARE_METATYPE(Test*) + +#endif // TEST_H diff --git a/__tests/auto/tst_quuid/testdatabase.cpp b/__tests/auto/tst_quuid/testdatabase.cpp new file mode 100644 index 0000000..336119e --- /dev/null +++ b/__tests/auto/tst_quuid/testdatabase.cpp @@ -0,0 +1,8 @@ +#include "testdatabase.h" +#include "test.h" + +TestDatabase::TestDatabase(QObject *parent) + : Database(parent), m_tests(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_quuid/testdatabase.h b/__tests/auto/tst_quuid/testdatabase.h new file mode 100644 index 0000000..88bb109 --- /dev/null +++ b/__tests/auto/tst_quuid/testdatabase.h @@ -0,0 +1,18 @@ +#ifndef TESTDATABASE_H +#define TESTDATABASE_H + +#include "database.h" + +class Test; +class TestDatabase : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(Test, tests) +public: + TestDatabase(QObject *parent = nullptr); +}; + +#endif // TESTDATABASE_H diff --git a/__tests/auto/tst_quuid/tst_quuid.pro b/__tests/auto/tst_quuid/tst_quuid.pro new file mode 100644 index 0000000..627d2db --- /dev/null +++ b/__tests/auto/tst_quuid/tst_quuid.pro @@ -0,0 +1,19 @@ +QT += testlib sql + +TARGET = tst_uuid +TEMPLATE = app +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + testdatabase.cpp \ + test.cpp \ + tst_uuid.cpp + +HEADERS += \ + ../common/consts.h \ + testdatabase.h \ + test.h \ + tst_uuid.h + diff --git a/__tests/auto/tst_quuid/tst_uuid.cpp b/__tests/auto/tst_quuid/tst_uuid.cpp new file mode 100644 index 0000000..e77b39b --- /dev/null +++ b/__tests/auto/tst_quuid/tst_uuid.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include "consts.h" + +#include "tst_uuid.h" +#include "query.h" +#include "tableset.h" +#include "tablemodel.h" + +#include "test.h" + +UuidTest::UuidTest(QObject *parent) : QObject(parent) +{ +} + +void UuidTest::initTestCase() +{ + REGISTER(Test); + REGISTER(TestDatabase); + + QFile::remove(DATABASE); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + bool ok = db.open(); + + db.tests()->query().remove(); + uuid = QUuid::createUuid(); + + QTEST_ASSERT(ok); +} + +void UuidTest::save() +{ + TIC(); + auto t = Nut::create(); + t->setId(QUuid::createUuid()); + t->setUuid(uuid); + db.tests()->append(t); + int n = db.saveChanges(); + TOC(); + + QTEST_ASSERT(n == 1); +} + +void UuidTest::restore() +{ + TIC(); + auto test = db.tests()->query().first(); + TOC(); + QTEST_ASSERT(!test->id().isNull()); + QTEST_ASSERT(test->uuid() == uuid); +} + +void UuidTest::cleanupTestCase() +{ +// qDeleteAll(Nut::TableModel::allModels()); +// Nut::DatabaseModel::deleteAllModels(); +} + +QTEST_MAIN(UuidTest) diff --git a/__tests/auto/tst_quuid/tst_uuid.h b/__tests/auto/tst_quuid/tst_uuid.h new file mode 100644 index 0000000..d577cb8 --- /dev/null +++ b/__tests/auto/tst_quuid/tst_uuid.h @@ -0,0 +1,30 @@ +#ifndef MAINTEST_H +#define MAINTEST_H + +#include +#include + +#include + +#include "testdatabase.h" +class Test; +class UuidTest : public QObject +{ + Q_OBJECT + TestDatabase db; + QUuid uuid; + +public: + explicit UuidTest(QObject *parent = nullptr); + +Q_SIGNALS: + +private Q_SLOTS: + void initTestCase(); + void save(); + void restore(); + + void cleanupTestCase(); +}; + +#endif // MAINTEST_H diff --git a/__tests/auto/tst_upgrades/.gitignore b/__tests/auto/tst_upgrades/.gitignore new file mode 100644 index 0000000..fab7372 --- /dev/null +++ b/__tests/auto/tst_upgrades/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/__tests/auto/tst_upgrades/CMakeLists.txt b/__tests/auto/tst_upgrades/CMakeLists.txt new file mode 100644 index 0000000..ac986fa --- /dev/null +++ b/__tests/auto/tst_upgrades/CMakeLists.txt @@ -0,0 +1,89 @@ +# Generated from tst_upgrades.pro. + +##################################################################### +## tst_upgrades Test: +##################################################################### + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_upgrades LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_upgrades + SOURCES + db1.cpp db1.h + db2.cpp db2.h + db3.cpp db3.h + table1.cpp table1.h + table2.cpp table2.h + table3.cpp table3.h + tst_upgrades.cpp tst_upgrades.h + DEFINES + NUT_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../\\\" + INCLUDE_DIRECTORIES + ../common/../common + PUBLIC_LIBRARIES + Qt::Gui + Qt::Sql + nut +) + +#### Keys ignored in scope 1:.:.:tst_upgrades.pro:: +# TEMPLATE = "app" + +## Scopes: +##################################################################### + +#### Keys ignored in scope 4:.:../common:../common/nut-lib.pri:debug_and_release AND NOT ReleaseBuild AND NOT DebugBuild: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.CONFIG = "recursive" +# runtarget.recurse_target = "run-tests" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 5:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "oneshell" +# oneshell.target = ".ONESHELL" + +#### Keys ignored in scope 6:.:../common:../common/nut-lib.pri:WIN32 AND NOT win32-g++: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "set" "PATH=$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin;$$shell_path$$[QT_INSTALL_BINS];$(PATH)" "$$escape_expand(\\n\\t)" "set" "QT_PLUGIN_PATH=$$shadowed$$dirname_QMAKE_CONF_/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)" "$$escape_expand(\\n\\t)" "set" "QML2_IMPORT_PATH=$$shadowed$$dirname_QMAKE_CONF_/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "del" "$${outdir_helper}\\fail" "$$escape_expand(\\n\\t)" "start" "/w" "call" "$(DESTDIR_TARGET)" "^>" "$${outdir_helper}\\test.log" "^|^|" "echo" "FAIL" "^>" "$${outdir_helper}\\fail" "^&" "exit" "0" "$$escape_expand(\\n\\t)" "type" "$${outdir_helper}\\test.log" "$$escape_expand(\\n\\t)" "if" "exist" "$${outdir_helper}\\fail" "exit" "42" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 7:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Debug): +# outdir_helper = "debug" + +#### Keys ignored in scope 8:.:../common:../common/nut-lib.pri:(CMAKE_BUILD_TYPE STREQUAL Release): +# outdir_helper = "release" + +#### Keys ignored in scope 9:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 10:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "set" "\"QT_LOGGING_RULES=$$LOGGING_RULES\"" + +#### Keys ignored in scope 11:.:../common:../common/nut-lib.pri:else: +# QMAKE_EXTRA_TARGETS = "runtarget" +# runtarget.commands = "export" "PATH=\"$$shell_path$$shadowed$$dirname_QMAKE_CONF_/bin:$$shell_path$$[QT_INSTALL_BINS]:$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"" "$$escape_expand(\\n\\t)" "export" "QT_PLUGIN_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QML2_IMPORT_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"" +# runtarget.target = "run-tests" + +#### Keys ignored in scope 12:.:../common:../common/nut-lib.pri:win32-g++: +# QMAKE_DIRLIST_SEP = ";" + +#### Keys ignored in scope 13:.:../common:../common/nut-lib.pri:NOT LOGGING_RULES_ISEMPTY: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "QT_LOGGING_RULES=\"$$LOGGING_RULES\"" + +#### Keys ignored in scope 15:.:../common:../common/nut-lib.pri:LINUX OR win32-g++: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "LD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "QT_QPA_PLATFORM=minimal" + +#### Keys ignored in scope 17:.:../common:../common/nut-lib.pri:APPLE: +# runtarget.commands = "$$escape_expand(\\n\\t)" "export" "DYLD_LIBRARY_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"" "$$escape_expand(\\n\\t)" "export" "DYLD_FRAMEWORK_PATH=\"$$shadowed$$dirname_QMAKE_CONF_/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"" + +#### Keys ignored in scope 19:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(DESTDIR_TARGET)" + +#### Keys ignored in scope 20:.:../common:../common/nut-lib.pri:else: +# runtarget.commands = "$$escape_expand(\\n\\t)" "./$(TARGET)" + +#### Keys ignored in scope 21:.:../common:../common/nut-lib.pri:NOT compat_test: +# runtarget.depends = "$(TARGET)" diff --git a/__tests/auto/tst_upgrades/db1.cpp b/__tests/auto/tst_upgrades/db1.cpp new file mode 100644 index 0000000..3171155 --- /dev/null +++ b/__tests/auto/tst_upgrades/db1.cpp @@ -0,0 +1,9 @@ +#include "db1.h" + +#include "table1.h" + +DB1::DB1() : Nut::Database (), + m_sampleTable(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_upgrades/db1.h b/__tests/auto/tst_upgrades/db1.h new file mode 100644 index 0000000..e1330fb --- /dev/null +++ b/__tests/auto/tst_upgrades/db1.h @@ -0,0 +1,22 @@ +#ifndef DB1_H +#define DB1_H + +#include "database.h" + +class Table1; + +class DB1 : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(Table1, sampleTable) + +public: + DB1(); +}; + +Q_DECLARE_METATYPE(DB1*) + +#endif // DB1_H diff --git a/__tests/auto/tst_upgrades/db2.cpp b/__tests/auto/tst_upgrades/db2.cpp new file mode 100644 index 0000000..de05611 --- /dev/null +++ b/__tests/auto/tst_upgrades/db2.cpp @@ -0,0 +1,9 @@ +#include "db2.h" + +#include "table2.h" + +DB2::DB2() : Nut::Database (), + m_sampleTable(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_upgrades/db2.h b/__tests/auto/tst_upgrades/db2.h new file mode 100644 index 0000000..2367216 --- /dev/null +++ b/__tests/auto/tst_upgrades/db2.h @@ -0,0 +1,22 @@ +#ifndef DB2_H +#define DB2_H + +#include "database.h" + +class Table2; + +class DB2 : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(Table2, sampleTable) + +public: + DB2(); +}; + +Q_DECLARE_METATYPE(DB2*) + +#endif // DB2_H diff --git a/__tests/auto/tst_upgrades/db3.cpp b/__tests/auto/tst_upgrades/db3.cpp new file mode 100644 index 0000000..ab4c987 --- /dev/null +++ b/__tests/auto/tst_upgrades/db3.cpp @@ -0,0 +1,9 @@ +#include "db3.h" + +#include "table3.h" + +DB3::DB3() : Nut::Database (), + m_sampleTable(new Nut::TableSet(this)) +{ + +} diff --git a/__tests/auto/tst_upgrades/db3.h b/__tests/auto/tst_upgrades/db3.h new file mode 100644 index 0000000..d51835a --- /dev/null +++ b/__tests/auto/tst_upgrades/db3.h @@ -0,0 +1,22 @@ +#ifndef DB3_H +#define DB3_H + +#include "database.h" + +class Table3; + +class DB3 : public NUT_WRAP_NAMESPACE(Database) +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(Table3, sampleTable) + +public: + DB3(); +}; + +Q_DECLARE_METATYPE(DB3*) + +#endif // DB3_H diff --git a/__tests/auto/tst_upgrades/table1.cpp b/__tests/auto/tst_upgrades/table1.cpp new file mode 100644 index 0000000..d74ed3b --- /dev/null +++ b/__tests/auto/tst_upgrades/table1.cpp @@ -0,0 +1,7 @@ +#include "table1.h" + + +Table1::Table1(QObject *parent) : Nut::Table (parent) +{ + +} diff --git a/__tests/auto/tst_upgrades/table1.h b/__tests/auto/tst_upgrades/table1.h new file mode 100644 index 0000000..0c5ce23 --- /dev/null +++ b/__tests/auto/tst_upgrades/table1.h @@ -0,0 +1,20 @@ +#ifndef TABLE1_H +#define TABLE1_H + +#include "table.h" + +class Table1 : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + +public: + Q_INVOKABLE Table1(QObject *parent = Q_NULLPTR); + +}; + +Q_DECLARE_METATYPE(Table1*) + +#endif // TABLE1_H diff --git a/__tests/auto/tst_upgrades/table2.cpp b/__tests/auto/tst_upgrades/table2.cpp new file mode 100644 index 0000000..3118a19 --- /dev/null +++ b/__tests/auto/tst_upgrades/table2.cpp @@ -0,0 +1,7 @@ +#include "table2.h" + + +Table2::Table2(QObject *parent) : Nut::Table (parent) +{ + +} diff --git a/__tests/auto/tst_upgrades/table2.h b/__tests/auto/tst_upgrades/table2.h new file mode 100644 index 0000000..c576fc8 --- /dev/null +++ b/__tests/auto/tst_upgrades/table2.h @@ -0,0 +1,23 @@ +#ifndef TABLE2_H +#define TABLE2_H + +#include "table.h" + +class Table2 : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + + NUT_DECLARE_FIELD(QString, str, str, setStr) + NUT_DECLARE_FIELD(int, grade, grade, setGrade) + +public: + Q_INVOKABLE Table2(QObject *parent = Q_NULLPTR); + +}; + +Q_DECLARE_METATYPE(Table2*) + +#endif // TABLE2_H diff --git a/__tests/auto/tst_upgrades/table3.cpp b/__tests/auto/tst_upgrades/table3.cpp new file mode 100644 index 0000000..fa07443 --- /dev/null +++ b/__tests/auto/tst_upgrades/table3.cpp @@ -0,0 +1,7 @@ +#include "table3.h" + + +Table3::Table3(QObject *parent) : Nut::Table (parent) +{ + +} diff --git a/__tests/auto/tst_upgrades/table3.h b/__tests/auto/tst_upgrades/table3.h new file mode 100644 index 0000000..e9825f3 --- /dev/null +++ b/__tests/auto/tst_upgrades/table3.h @@ -0,0 +1,22 @@ +#ifndef TABLE3_H +#define TABLE3_H + +#include "table.h" + +class Table3 : public NUT_WRAP_NAMESPACE(Table) +{ + Q_OBJECT + + NUT_PRIMARY_AUTO_INCREMENT(id) + NUT_DECLARE_FIELD(int, id, id, setId) + + NUT_DECLARE_FIELD(QString, grade, grade, setGrade) + +public: + Q_INVOKABLE Table3(QObject *parent = Q_NULLPTR); + +}; + +Q_DECLARE_METATYPE(Table3*) + +#endif // TABLE3_H diff --git a/__tests/auto/tst_upgrades/tst_upgrades.cpp b/__tests/auto/tst_upgrades/tst_upgrades.cpp new file mode 100644 index 0000000..345f09a --- /dev/null +++ b/__tests/auto/tst_upgrades/tst_upgrades.cpp @@ -0,0 +1,88 @@ +#include + +#include "db1.h" +#include "db2.h" +#include "db3.h" + +#include "table1.h" +#include "table2.h" +#include "table3.h" +#include "query.h" + +#include "tst_upgrades.h" +#include "consts.h" + +void Upgrades::initDb(Nut::Database &db) +{ + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); +} + +Upgrades::Upgrades() +{ + +} + +Upgrades::~Upgrades() +{ + +} + +void Upgrades::initTestCase() +{ + QFile::remove(DATABASE); + + REGISTER(DB1); + REGISTER(DB2); + REGISTER(DB3); + + REGISTER(Table1); + REGISTER(Table2); + REGISTER(Table3); +} + +void Upgrades::version1() +{ + DB1 db; + initDb(db); + QTEST_ASSERT(db.open()); + db.sampleTable()->query().remove(); +} + +void Upgrades::version2() +{ + DB2 db; + initDb(db); + QTEST_ASSERT(db.open()); + + auto t = Nut::create(); + t->setStr("0"); + db.sampleTable()->append(t); + db.saveChanges(); + id = t->id(); +} + +void Upgrades::version3() +{ + DB3 db; + initDb(db); + QTEST_ASSERT(db.open()); + + auto t = db.sampleTable()->query() + .first(); + QTEST_ASSERT(id == t->id()); +} + +void Upgrades::cleanupTestCase() +{ + DB1 db; + initDb(db); + PRINT_FORM(db); +} + + +QTEST_APPLESS_MAIN(Upgrades) + diff --git a/__tests/auto/tst_upgrades/tst_upgrades.h b/__tests/auto/tst_upgrades/tst_upgrades.h new file mode 100644 index 0000000..9b39957 --- /dev/null +++ b/__tests/auto/tst_upgrades/tst_upgrades.h @@ -0,0 +1,31 @@ +#ifndef TST_UPGRADES_H +#define TST_UPGRADES_H + +#include + +namespace Nut { +class Database; +} +class Upgrades : public QObject +{ + Q_OBJECT + + void initDb(Nut::Database &db); + + int id; +public: + Upgrades(); + ~Upgrades(); + +private Q_SLOTS: + void initTestCase(); + + void version1(); + void version2(); + void version3(); + + void cleanupTestCase(); + +}; + +#endif // TST_UPGRADES_H diff --git a/__tests/auto/tst_upgrades/tst_upgrades.pro b/__tests/auto/tst_upgrades/tst_upgrades.pro new file mode 100644 index 0000000..7c1e5be --- /dev/null +++ b/__tests/auto/tst_upgrades/tst_upgrades.pro @@ -0,0 +1,25 @@ +QT += testlib sql + +TARGET = tst_upgrades +TEMPLATE = app +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += tst_upgrades.cpp \ + db1.cpp \ + table1.cpp \ + db2.cpp \ + table2.cpp \ + db3.cpp \ + table3.cpp + +HEADERS += \ + tst_upgrades.h \ + db1.h \ + table1.h \ + db2.h \ + table2.h \ + db3.h \ + table3.h + diff --git a/__tests/tests.pro b/__tests/tests.pro new file mode 100644 index 0000000..6d9db4c --- /dev/null +++ b/__tests/tests.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs + +CONFIG += no_docs_target + +SUBDIRS += auto + +OTHER_FILES += ../.github/workflows/build.yml + +prepareRecursiveTarget(run-tests) +QMAKE_EXTRA_TARGETS += run-tests diff --git a/src/nut/core/database.cpp b/src/nut/core/database.cpp index 7c6c091..29f385b 100644 --- a/src/nut/core/database.cpp +++ b/src/nut/core/database.cpp @@ -136,8 +136,10 @@ bool DatabasePrivate::updateDatabase() QString databaseHistoryName = driver + QStringLiteral("\t") + databaseName + QStringLiteral("\t") + hostName; - if (updatedDatabases.contains(databaseHistoryName)) + if (allTableMaps.contains(QString::fromUtf8(q->metaObject()->className()))) { + currentModel = allTableMaps[QString::fromUtf8(q->metaObject()->className())]; return true; + } if (!getCurrentSchema()) return true; @@ -300,6 +302,12 @@ bool DatabasePrivate::getCurrentSchema() return true; } +bool DatabasePrivate::isFirstOpen() +{ + Q_Q(Database); + return !allTableMaps.contains(QString::fromUtf8(q->metaObject()->className())); +} + DatabaseModel DatabasePrivate::getLastSchema() { Row u = changeLogs->query() @@ -555,10 +563,10 @@ bool Database::open(bool updateDatabase) d->sqlGenerator = new SqliteGenerator(this); else if (d->driver == QStringLiteral("QODBC") || d->driver == QStringLiteral("QODBC3")) { QString driverName = QString(); - QStringList parts = d->databaseName.toLower().split(';'); + QStringList parts = d->databaseName.toLower().split(QLatin1Char(';')); for (auto &p: parts) if (p.trimmed().startsWith(QStringLiteral("driver="))) - driverName = p.split('=').at(1).toLower().trimmed(); + driverName = p.split(QLatin1Char('=')).at(1).toLower().trimmed(); // if (driverName == "{sql server}") d->sqlGenerator = new SqlServerGenerator(this); diff --git a/src/nut/core/database_p.h b/src/nut/core/database_p.h index 76ad7c4..f508d7a 100644 --- a/src/nut/core/database_p.h +++ b/src/nut/core/database_p.h @@ -79,6 +79,7 @@ public: QSet tableSets; + bool isFirstOpen(); bool isDatabaseNew; QString errorMessage; diff --git a/tests/auto/tst_basic/tst_basic.cpp b/tests/auto/tst_basic/tst_basic.cpp index 97a8daa..891159c 100644 --- a/tests/auto/tst_basic/tst_basic.cpp +++ b/tests/auto/tst_basic/tst_basic.cpp @@ -324,7 +324,29 @@ void BasicTest::emptyDatabase() // auto commentsCount = db.comments()->query().remove(); // auto postsCount = db.posts()->query().remove(); // QTEST_ASSERT(postsCount == 3); -// QTEST_ASSERT(commentsCount == 6); + // QTEST_ASSERT(commentsCount == 6); +} + +void BasicTest::multipleOpen() +{ + for (int i = 0; i < 10; ++i) { + WeblogDatabase database; + database.setDriver(DRIVER); + database.setHostName(HOST); + database.setDatabaseName(DATABASE); + database.setUserName(USERNAME); + database.setPassword(PASSWORD); + + bool ok = database.open(); + QVERIFY(ok); + + auto q = database.posts()->query() + .where(Post::idField() == postId) + .orderBy(Post::idField()) + .toList(); + + QTEST_ASSERT(q.count() > 0); + } } void BasicTest::cleanupTestCase() diff --git a/tests/auto/tst_basic/tst_basic.h b/tests/auto/tst_basic/tst_basic.h index 1f3163a..5659107 100644 --- a/tests/auto/tst_basic/tst_basic.h +++ b/tests/auto/tst_basic/tst_basic.h @@ -45,6 +45,7 @@ private Q_SLOTS: void selectWithInvalidRelation(); void modifyPost(); void emptyDatabase(); + void multipleOpen(); void cleanupTestCase(); }; diff --git a/tests/auto/tst_upgrades/tst_upgrades.cpp b/tests/auto/tst_upgrades/tst_upgrades.cpp index 345f09a..054e8e9 100644 --- a/tests/auto/tst_upgrades/tst_upgrades.cpp +++ b/tests/auto/tst_upgrades/tst_upgrades.cpp @@ -56,7 +56,7 @@ void Upgrades::version2() { DB2 db; initDb(db); - QTEST_ASSERT(db.open()); + QVERIFY(db.open()); auto t = Nut::create(); t->setStr("0");