mirror of
https://github.com/redis/RedisDesktopManager.git
synced 2026-10-16 20:21:46 +08:00
Revive unit and integration tests
- Use fakeit for mocks - Repair all unit tests - Create env for QML integration tests - Add intergration test for MultilineEditor - Replace ModelTest with QAbstractItemModelTester
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
name: Run Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 2022
|
||||
pull_request:
|
||||
branches: [ 2022 ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2.3.4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2.13.2
|
||||
with:
|
||||
version: 5.15.2
|
||||
modules: qtcharts
|
||||
- name: Install Build deps
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install cmake liblz4-dev libzstd-dev libbrotli-dev libsnappy-dev lcov -y
|
||||
cmake --version
|
||||
gcc --version
|
||||
- name: Setup Redis
|
||||
uses: zhulik/redis-action@1.1.0
|
||||
- name: Build Tests
|
||||
run: qmake "SYSTEM_LZ4=1" "SYSTEM_ZSTD=1" "SYSTEM_SNAPPY=1" "SYSTEM_BROTLI=1" DEFINES+=INTEGRATION_TESTS && make -j 2
|
||||
working-directory: ./tests
|
||||
- name: Run Cpp Tests
|
||||
run: ./../bin/tests/tests -platform minimal -txt
|
||||
working-directory: ./tests
|
||||
- name: Run QML Tests
|
||||
run: ./../bin/tests/qml_tests -platform minimal -txt
|
||||
working-directory: ./tests
|
||||
|
||||
@@ -19,3 +19,6 @@
|
||||
[submodule "3rdparty/brotli"]
|
||||
path = 3rdparty/brotli
|
||||
url = https://github.com/google/brotli.git
|
||||
[submodule "3rdparty/fakeit"]
|
||||
path = 3rdparty/fakeit
|
||||
url = https://github.com/eranpeer/FakeIt.git
|
||||
|
||||
+1
Submodule 3rdparty/fakeit added at 80a446b8d9
Vendored
+1
-1
Submodule 3rdparty/qredisclient updated: 784cea7943...9e1e29e826
Vendored
-592
@@ -1,592 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL21$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** As a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "modeltest.h"
|
||||
|
||||
#include <QtCore/QtCore>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
/*!
|
||||
Connect to all of the models signals. Whenever anything happens recheck everything.
|
||||
*/
|
||||
ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false )
|
||||
{
|
||||
if (!model)
|
||||
qFatal("%s: model must not be null", Q_FUNC_INFO);
|
||||
|
||||
connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(runAllTests()) );
|
||||
|
||||
// Special checks for changes
|
||||
connect(model, SIGNAL(layoutAboutToBeChanged()),
|
||||
this, SLOT(layoutAboutToBeChanged()) );
|
||||
connect(model, SIGNAL(layoutChanged()),
|
||||
this, SLOT(layoutChanged()) );
|
||||
|
||||
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
|
||||
this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) );
|
||||
connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) );
|
||||
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(rowsInserted(QModelIndex,int,int)) );
|
||||
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
|
||||
this, SLOT(rowsRemoved(QModelIndex,int,int)) );
|
||||
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
|
||||
this, SLOT(dataChanged(QModelIndex,QModelIndex)) );
|
||||
connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
|
||||
this, SLOT(headerDataChanged(Qt::Orientation,int,int)) );
|
||||
|
||||
runAllTests();
|
||||
}
|
||||
|
||||
void ModelTest::runAllTests()
|
||||
{
|
||||
if ( fetchingMore )
|
||||
return;
|
||||
nonDestructiveBasicTest();
|
||||
rowCount();
|
||||
columnCount();
|
||||
hasIndex();
|
||||
index();
|
||||
parent();
|
||||
data();
|
||||
}
|
||||
|
||||
/*!
|
||||
nonDestructiveBasicTest tries to call a number of the basic functions (not all)
|
||||
to make sure the model doesn't outright segfault, testing the functions that makes sense.
|
||||
*/
|
||||
void ModelTest::nonDestructiveBasicTest()
|
||||
{
|
||||
QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() );
|
||||
model->canFetchMore ( QModelIndex() );
|
||||
QVERIFY( model->columnCount ( QModelIndex() ) >= 0 );
|
||||
QVERIFY( model->data ( QModelIndex() ) == QVariant() );
|
||||
fetchingMore = true;
|
||||
model->fetchMore ( QModelIndex() );
|
||||
fetchingMore = false;
|
||||
Qt::ItemFlags flags = model->flags ( QModelIndex() );
|
||||
QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 );
|
||||
model->hasChildren ( QModelIndex() );
|
||||
model->hasIndex ( 0, 0 );
|
||||
model->headerData ( 0, Qt::Horizontal );
|
||||
model->index ( 0, 0 );
|
||||
model->itemData ( QModelIndex() );
|
||||
QVariant cache;
|
||||
model->match ( QModelIndex(), -1, cache );
|
||||
model->mimeTypes();
|
||||
QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() );
|
||||
QVERIFY( model->rowCount() >= 0 );
|
||||
QVariant variant;
|
||||
model->setData ( QModelIndex(), variant, -1 );
|
||||
model->setHeaderData ( -1, Qt::Horizontal, QVariant() );
|
||||
model->setHeaderData ( 999999, Qt::Horizontal, QVariant() );
|
||||
QMap<int, QVariant> roles;
|
||||
model->sibling ( 0, 0, QModelIndex() );
|
||||
model->span ( QModelIndex() );
|
||||
model->supportedDropActions();
|
||||
}
|
||||
|
||||
/*!
|
||||
Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren()
|
||||
|
||||
Models that are dynamically populated are not as fully tested here.
|
||||
*/
|
||||
void ModelTest::rowCount()
|
||||
{
|
||||
// qDebug() << "rc";
|
||||
// check top row
|
||||
QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
|
||||
int rows = model->rowCount ( topIndex );
|
||||
QVERIFY( rows >= 0 );
|
||||
if ( rows > 0 )
|
||||
QVERIFY( model->hasChildren ( topIndex ) );
|
||||
|
||||
QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex );
|
||||
if ( secondLevelIndex.isValid() ) { // not the top level
|
||||
// check a row count where parent is valid
|
||||
rows = model->rowCount ( secondLevelIndex );
|
||||
QVERIFY( rows >= 0 );
|
||||
if ( rows > 0 )
|
||||
QVERIFY( model->hasChildren ( secondLevelIndex ) );
|
||||
}
|
||||
|
||||
// The models rowCount() is tested more extensively in checkChildren(),
|
||||
// but this catches the big mistakes
|
||||
}
|
||||
|
||||
/*!
|
||||
Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren()
|
||||
*/
|
||||
void ModelTest::columnCount()
|
||||
{
|
||||
// check top row
|
||||
QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
|
||||
QVERIFY( model->columnCount ( topIndex ) >= 0 );
|
||||
|
||||
// check a column count where parent is valid
|
||||
QModelIndex childIndex = model->index ( 0, 0, topIndex );
|
||||
if ( childIndex.isValid() )
|
||||
QVERIFY( model->columnCount ( childIndex ) >= 0 );
|
||||
|
||||
// columnCount() is tested more extensively in checkChildren(),
|
||||
// but this catches the big mistakes
|
||||
}
|
||||
|
||||
/*!
|
||||
Tests model's implementation of QAbstractItemModel::hasIndex()
|
||||
*/
|
||||
void ModelTest::hasIndex()
|
||||
{
|
||||
// qDebug() << "hi";
|
||||
// Make sure that invalid values returns an invalid index
|
||||
QVERIFY( !model->hasIndex ( -2, -2 ) );
|
||||
QVERIFY( !model->hasIndex ( -2, 0 ) );
|
||||
QVERIFY( !model->hasIndex ( 0, -2 ) );
|
||||
|
||||
int rows = model->rowCount();
|
||||
int columns = model->columnCount();
|
||||
|
||||
// check out of bounds
|
||||
QVERIFY( !model->hasIndex ( rows, columns ) );
|
||||
QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) );
|
||||
|
||||
if ( rows > 0 )
|
||||
QVERIFY( model->hasIndex ( 0, 0 ) );
|
||||
|
||||
// hasIndex() is tested more extensively in checkChildren(),
|
||||
// but this catches the big mistakes
|
||||
}
|
||||
|
||||
/*!
|
||||
Tests model's implementation of QAbstractItemModel::index()
|
||||
*/
|
||||
void ModelTest::index()
|
||||
{
|
||||
// qDebug() << "i";
|
||||
// Make sure that invalid values returns an invalid index
|
||||
QVERIFY( model->index ( -2, -2 ) == QModelIndex() );
|
||||
QVERIFY( model->index ( -2, 0 ) == QModelIndex() );
|
||||
QVERIFY( model->index ( 0, -2 ) == QModelIndex() );
|
||||
|
||||
int rows = model->rowCount();
|
||||
int columns = model->columnCount();
|
||||
|
||||
if ( rows == 0 )
|
||||
return;
|
||||
|
||||
// Catch off by one errors
|
||||
QVERIFY( model->index ( rows, columns ) == QModelIndex() );
|
||||
QVERIFY( model->index ( 0, 0 ).isValid() );
|
||||
|
||||
// Make sure that the same index is *always* returned
|
||||
QModelIndex a = model->index ( 0, 0 );
|
||||
QModelIndex b = model->index ( 0, 0 );
|
||||
QVERIFY( a == b );
|
||||
|
||||
// index() is tested more extensively in checkChildren(),
|
||||
// but this catches the big mistakes
|
||||
}
|
||||
|
||||
/*!
|
||||
Tests model's implementation of QAbstractItemModel::parent()
|
||||
*/
|
||||
void ModelTest::parent()
|
||||
{
|
||||
// qDebug() << "p";
|
||||
// Make sure the model won't crash and will return an invalid QModelIndex
|
||||
// when asked for the parent of an invalid index.
|
||||
QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() );
|
||||
|
||||
if ( model->rowCount() == 0 )
|
||||
return;
|
||||
|
||||
// Column 0 | Column 1 |
|
||||
// QModelIndex() | |
|
||||
// \- topIndex | topIndex1 |
|
||||
// \- childIndex | childIndex1 |
|
||||
|
||||
// Common error test #1, make sure that a top level index has a parent
|
||||
// that is a invalid QModelIndex.
|
||||
QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
|
||||
QVERIFY( model->parent ( topIndex ) == QModelIndex() );
|
||||
|
||||
// Common error test #2, make sure that a second level index has a parent
|
||||
// that is the first level index.
|
||||
if ( model->rowCount ( topIndex ) > 0 ) {
|
||||
QModelIndex childIndex = model->index ( 0, 0, topIndex );
|
||||
QVERIFY( model->parent ( childIndex ) == topIndex );
|
||||
}
|
||||
|
||||
// Common error test #3, the second column should NOT have the same children
|
||||
// as the first column in a row.
|
||||
// Usually the second column shouldn't have children.
|
||||
QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() );
|
||||
if ( model->rowCount ( topIndex1 ) > 0 ) {
|
||||
QModelIndex childIndex = model->index ( 0, 0, topIndex );
|
||||
QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 );
|
||||
QVERIFY( childIndex != childIndex1 );
|
||||
}
|
||||
|
||||
// Full test, walk n levels deep through the model making sure that all
|
||||
// parent's children correctly specify their parent.
|
||||
checkChildren ( QModelIndex() );
|
||||
}
|
||||
|
||||
/*!
|
||||
Called from the parent() test.
|
||||
|
||||
A model that returns an index of parent X should also return X when asking
|
||||
for the parent of the index.
|
||||
|
||||
This recursive function does pretty extensive testing on the whole model in an
|
||||
effort to catch edge cases.
|
||||
|
||||
This function assumes that rowCount(), columnCount() and index() already work.
|
||||
If they have a bug it will point it out, but the above tests should have already
|
||||
found the basic bugs because it is easier to figure out the problem in
|
||||
those tests then this one.
|
||||
*/
|
||||
void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
|
||||
{
|
||||
// First just try walking back up the tree.
|
||||
QModelIndex p = parent;
|
||||
while ( p.isValid() )
|
||||
p = p.parent();
|
||||
|
||||
// For models that are dynamically populated
|
||||
if ( model->canFetchMore ( parent ) ) {
|
||||
fetchingMore = true;
|
||||
model->fetchMore ( parent );
|
||||
fetchingMore = false;
|
||||
}
|
||||
|
||||
int rows = model->rowCount ( parent );
|
||||
int columns = model->columnCount ( parent );
|
||||
|
||||
if ( rows > 0 )
|
||||
QVERIFY( model->hasChildren ( parent ) );
|
||||
|
||||
// Some further testing against rows(), columns(), and hasChildren()
|
||||
QVERIFY( rows >= 0 );
|
||||
QVERIFY( columns >= 0 );
|
||||
if ( rows > 0 )
|
||||
QVERIFY( model->hasChildren ( parent ) );
|
||||
|
||||
//qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
|
||||
// << "columns:" << columns << "parent column:" << parent.column();
|
||||
|
||||
const QModelIndex topLeftChild = model->index( 0, 0, parent );
|
||||
|
||||
QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) );
|
||||
for ( int r = 0; r < rows; ++r ) {
|
||||
if ( model->canFetchMore ( parent ) ) {
|
||||
fetchingMore = true;
|
||||
model->fetchMore ( parent );
|
||||
fetchingMore = false;
|
||||
}
|
||||
QVERIFY( !model->hasIndex ( r, columns + 1, parent ) );
|
||||
for ( int c = 0; c < columns; ++c ) {
|
||||
QVERIFY( model->hasIndex ( r, c, parent ) );
|
||||
QModelIndex index = model->index ( r, c, parent );
|
||||
// rowCount() and columnCount() said that it existed...
|
||||
QVERIFY( index.isValid() );
|
||||
|
||||
// index() should always return the same index when called twice in a row
|
||||
QModelIndex modifiedIndex = model->index ( r, c, parent );
|
||||
QVERIFY( index == modifiedIndex );
|
||||
|
||||
// Make sure we get the same index if we request it twice in a row
|
||||
QModelIndex a = model->index ( r, c, parent );
|
||||
QModelIndex b = model->index ( r, c, parent );
|
||||
QVERIFY( a == b );
|
||||
|
||||
{
|
||||
const QModelIndex sibling = model->sibling( r, c, topLeftChild );
|
||||
QVERIFY( index == sibling );
|
||||
}
|
||||
{
|
||||
const QModelIndex sibling = topLeftChild.sibling( r, c );
|
||||
QVERIFY( index == sibling );
|
||||
}
|
||||
|
||||
// Some basic checking on the index that is returned
|
||||
QVERIFY( index.model() == model );
|
||||
QCOMPARE( index.row(), r );
|
||||
QCOMPARE( index.column(), c );
|
||||
// While you can technically return a QVariant usually this is a sign
|
||||
// of a bug in data(). Disable if this really is ok in your model.
|
||||
// QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() );
|
||||
|
||||
// If the next test fails here is some somewhat useful debug you play with.
|
||||
|
||||
if (model->parent(index) != parent) {
|
||||
qDebug() << r << c << currentDepth << model->data(index).toString()
|
||||
<< model->data(parent).toString();
|
||||
qDebug() << index << parent << model->parent(index);
|
||||
// And a view that you can even use to show the model.
|
||||
// QTreeView view;
|
||||
// view.setModel(model);
|
||||
// view.show();
|
||||
}
|
||||
|
||||
// Check that we can get back our real parent.
|
||||
QCOMPARE( model->parent ( index ), parent );
|
||||
|
||||
// recursively go down the children
|
||||
if ( model->hasChildren ( index ) && currentDepth < 10 ) {
|
||||
//qDebug() << r << c << "has children" << model->rowCount(index);
|
||||
checkChildren ( index, ++currentDepth );
|
||||
}/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
|
||||
|
||||
// make sure that after testing the children that the index doesn't change.
|
||||
QModelIndex newerIndex = model->index ( r, c, parent );
|
||||
QVERIFY( index == newerIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Tests model's implementation of QAbstractItemModel::data()
|
||||
*/
|
||||
void ModelTest::data()
|
||||
{
|
||||
// Invalid index should return an invalid qvariant
|
||||
QVERIFY( !model->data ( QModelIndex() ).isValid() );
|
||||
|
||||
if ( model->rowCount() == 0 )
|
||||
return;
|
||||
|
||||
// A valid index should have a valid QVariant data
|
||||
QVERIFY( model->index ( 0, 0 ).isValid() );
|
||||
|
||||
// shouldn't be able to set data on an invalid index
|
||||
QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) );
|
||||
|
||||
// General Purpose roles that should return a QString
|
||||
QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole );
|
||||
if ( variant.isValid() ) {
|
||||
QVERIFY( variant.canConvert<QString>() );
|
||||
}
|
||||
variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole );
|
||||
if ( variant.isValid() ) {
|
||||
QVERIFY( variant.canConvert<QString>() );
|
||||
}
|
||||
variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole );
|
||||
if ( variant.isValid() ) {
|
||||
QVERIFY( variant.canConvert<QString>() );
|
||||
}
|
||||
|
||||
// General Purpose roles that should return a QSize
|
||||
variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole );
|
||||
if ( variant.isValid() ) {
|
||||
QVERIFY( variant.canConvert<QSize>() );
|
||||
}
|
||||
|
||||
// General Purpose roles that should return a QFont
|
||||
QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole );
|
||||
if ( fontVariant.isValid() ) {
|
||||
QVERIFY( fontVariant.canConvert<QFont>() );
|
||||
}
|
||||
|
||||
// Check that the alignment is one we know about
|
||||
QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
|
||||
if ( textAlignmentVariant.isValid() ) {
|
||||
int alignment = textAlignmentVariant.toInt();
|
||||
QCOMPARE((unsigned int) alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) );
|
||||
}
|
||||
|
||||
// General Purpose roles that should return a QColor
|
||||
QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole );
|
||||
if ( colorVariant.isValid() ) {
|
||||
QVERIFY( colorVariant.canConvert<QColor>() );
|
||||
}
|
||||
|
||||
colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole );
|
||||
if ( colorVariant.isValid() ) {
|
||||
QVERIFY( colorVariant.canConvert<QColor>() );
|
||||
}
|
||||
|
||||
// Check that the "check state" is one we know about.
|
||||
QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole );
|
||||
if ( checkStateVariant.isValid() ) {
|
||||
int state = checkStateVariant.toInt();
|
||||
QVERIFY( state == Qt::Unchecked ||
|
||||
state == Qt::PartiallyChecked ||
|
||||
state == Qt::Checked );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Store what is about to be inserted to make sure it actually happens
|
||||
|
||||
\sa rowsInserted()
|
||||
*/
|
||||
void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */)
|
||||
{
|
||||
// Q_UNUSED(end);
|
||||
// qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
|
||||
// << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
|
||||
// qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
|
||||
Changing c;
|
||||
c.parent = parent;
|
||||
c.oldSize = model->rowCount ( parent );
|
||||
c.last = model->data ( model->index ( start - 1, 0, parent ) );
|
||||
c.next = model->data ( model->index ( start, 0, parent ) );
|
||||
insert.push ( c );
|
||||
}
|
||||
|
||||
/*!
|
||||
Confirm that what was said was going to happen actually did
|
||||
|
||||
\sa rowsAboutToBeInserted()
|
||||
*/
|
||||
void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
|
||||
{
|
||||
Changing c = insert.pop();
|
||||
QVERIFY( c.parent == parent );
|
||||
// qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
|
||||
// << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent );
|
||||
|
||||
// for (int ii=start; ii <= end; ii++)
|
||||
// {
|
||||
// qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent ));
|
||||
// }
|
||||
// qDebug();
|
||||
|
||||
QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) );
|
||||
QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
|
||||
|
||||
if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
|
||||
qDebug() << start << end;
|
||||
for (int i=0; i < model->rowCount(); ++i)
|
||||
qDebug() << model->index(i, 0).data().toString();
|
||||
qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
|
||||
}
|
||||
|
||||
QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) );
|
||||
}
|
||||
|
||||
void ModelTest::layoutAboutToBeChanged()
|
||||
{
|
||||
for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i )
|
||||
changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) );
|
||||
}
|
||||
|
||||
void ModelTest::layoutChanged()
|
||||
{
|
||||
for ( int i = 0; i < changing.count(); ++i ) {
|
||||
QPersistentModelIndex p = changing[i];
|
||||
QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) );
|
||||
}
|
||||
changing.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Store what is about to be inserted to make sure it actually happens
|
||||
|
||||
\sa rowsRemoved()
|
||||
*/
|
||||
void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end )
|
||||
{
|
||||
qDebug() << "ratbr" << parent << start << end;
|
||||
Changing c;
|
||||
c.parent = parent;
|
||||
c.oldSize = model->rowCount ( parent );
|
||||
c.last = model->data ( model->index ( start - 1, 0, parent ) );
|
||||
c.next = model->data ( model->index ( end + 1, 0, parent ) );
|
||||
remove.push ( c );
|
||||
}
|
||||
|
||||
/*!
|
||||
Confirm that what was said was going to happen actually did
|
||||
|
||||
\sa rowsAboutToBeRemoved()
|
||||
*/
|
||||
void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end )
|
||||
{
|
||||
qDebug() << "rr" << parent << start << end;
|
||||
Changing c = remove.pop();
|
||||
QVERIFY( c.parent == parent );
|
||||
QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) );
|
||||
QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
|
||||
QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) );
|
||||
}
|
||||
|
||||
void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
|
||||
{
|
||||
QVERIFY(topLeft.isValid());
|
||||
QVERIFY(bottomRight.isValid());
|
||||
QModelIndex commonParent = bottomRight.parent();
|
||||
QCOMPARE(topLeft.parent(), commonParent);
|
||||
QVERIFY(topLeft.row() <= bottomRight.row());
|
||||
QVERIFY(topLeft.column() <= bottomRight.column());
|
||||
int rowCount = model->rowCount(commonParent);
|
||||
int columnCount = model->columnCount(commonParent);
|
||||
QVERIFY(bottomRight.row() < rowCount);
|
||||
QVERIFY(bottomRight.column() < columnCount);
|
||||
}
|
||||
|
||||
void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int end)
|
||||
{
|
||||
QVERIFY(start >= 0);
|
||||
QVERIFY(end >= 0);
|
||||
QVERIFY(start <= end);
|
||||
int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount();
|
||||
QVERIFY(start < itemCount);
|
||||
QVERIFY(end < itemCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
-90
@@ -1,90 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL21$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** As a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef MODELTEST_H
|
||||
#define MODELTEST_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QAbstractItemModel>
|
||||
#include <QtCore/QStack>
|
||||
|
||||
class ModelTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ModelTest( QAbstractItemModel *model, QObject *parent = 0 );
|
||||
|
||||
private Q_SLOTS:
|
||||
void nonDestructiveBasicTest();
|
||||
void rowCount();
|
||||
void columnCount();
|
||||
void hasIndex();
|
||||
void index();
|
||||
void parent();
|
||||
void data();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void runAllTests();
|
||||
void layoutAboutToBeChanged();
|
||||
void layoutChanged();
|
||||
void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end );
|
||||
void rowsInserted( const QModelIndex & parent, int start, int end );
|
||||
void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end );
|
||||
void rowsRemoved( const QModelIndex & parent, int start, int end );
|
||||
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||
void headerDataChanged(Qt::Orientation orientation, int start, int end);
|
||||
|
||||
private:
|
||||
void checkChildren( const QModelIndex &parent, int currentDepth = 0 );
|
||||
|
||||
QAbstractItemModel *model;
|
||||
|
||||
struct Changing {
|
||||
QModelIndex parent;
|
||||
int oldSize;
|
||||
QVariant last;
|
||||
QVariant next;
|
||||
};
|
||||
QStack<Changing> insert;
|
||||
QStack<Changing> remove;
|
||||
|
||||
bool fetchingMore;
|
||||
|
||||
QList<QPersistentModelIndex> changing;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -134,14 +134,12 @@ bool ConnectionsManager::loadConnectionsConfigFromFile(const QString& config,
|
||||
addNewConnection(conf, false, group);
|
||||
}
|
||||
|
||||
addGroup(group);
|
||||
addGroup(group);
|
||||
} else {
|
||||
ServerConfig conf(obj.toVariantHash());
|
||||
if (conf.isNull()) continue;
|
||||
addNewConnection(conf, false);
|
||||
}
|
||||
|
||||
ServerConfig conf(obj.toVariantHash());
|
||||
|
||||
if (conf.isNull()) continue;
|
||||
|
||||
addNewConnection(conf, false);
|
||||
}
|
||||
|
||||
if (saveChangesToFile) saveConfig();
|
||||
@@ -385,7 +383,7 @@ void ConnectionsManager::createServerItemForConnection(
|
||||
emit connectionAboutToBeEdited(treeModel->config().name());
|
||||
|
||||
if (group) {
|
||||
group->removeChild(serverItem);
|
||||
group->removeConnection(serverItem);
|
||||
} else {
|
||||
removeRootItem(serverItem);
|
||||
}
|
||||
|
||||
@@ -25,13 +25,6 @@ TreeOperations::TreeOperations(const ServerConfig &config,
|
||||
m_events->registerLoggerForConnection(*m_connection);
|
||||
}
|
||||
|
||||
TreeOperations::~TreeOperations() {
|
||||
if (m_connection) {
|
||||
m_connection->disconnect();
|
||||
m_connection->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void TreeOperations::loadDatabases(
|
||||
QSharedPointer<RedisClient::Connection> c,
|
||||
QSharedPointer<AsyncFuture::Deferred<void>> d,
|
||||
@@ -39,9 +32,11 @@ void TreeOperations::loadDatabases(
|
||||
if (!d) return;
|
||||
|
||||
auto connection = c->clone(false);
|
||||
auto connectionWRef = connection.toWeakRef();
|
||||
|
||||
d->onCanceled([connection]() {
|
||||
QtConcurrent::run([connection]() {
|
||||
d->onCanceled([connectionWRef]() {
|
||||
QtConcurrent::run([connectionWRef]() {
|
||||
auto connection = connectionWRef.toStrongRef();
|
||||
if (connection) connection->disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,8 +22,6 @@ class TreeOperations : public QObject,
|
||||
TreeOperations(const ServerConfig& config,
|
||||
QSharedPointer<Events> events);
|
||||
|
||||
~TreeOperations();
|
||||
|
||||
QFuture<void> getDatabases(std::function<void (RedisClient::DatabaseList, const QString&)>) override;
|
||||
|
||||
void loadNamespaceItems(
|
||||
|
||||
@@ -43,7 +43,7 @@ void ServerGroup::insertChildAt(uint row, QSharedPointer<TreeItem> srv)
|
||||
m_servers.insert(row, srv);
|
||||
}
|
||||
|
||||
void ServerGroup::removeChild(QSharedPointer<TreeItem> srv)
|
||||
void ServerGroup::removeConnection(QSharedPointer<TreeItem> srv)
|
||||
{
|
||||
m_servers.removeAll(srv);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class ServerGroup : public QObject, public SortableTreeItem {
|
||||
|
||||
void insertChildAt(uint row, QSharedPointer<TreeItem> srv);
|
||||
|
||||
void removeChild(QSharedPointer<TreeItem> srv);
|
||||
void removeConnection(QSharedPointer<TreeItem> srv);
|
||||
|
||||
void setName(const QString &name);
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ void Model::dropItemAt(const QModelIndex &index, const QModelIndex &at)
|
||||
return;
|
||||
}
|
||||
|
||||
sourceGroup->removeChild(srv);
|
||||
sourceGroup->removeConnection(srv);
|
||||
} else {
|
||||
srv = findRootItem(item, m_treeItems);
|
||||
m_treeItems.removeAll(srv);
|
||||
|
||||
@@ -17,10 +17,7 @@ class Model : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Roles {
|
||||
itemName = Qt::UserRole + 1,
|
||||
itemType,
|
||||
itemIsInitiallyExpanded,
|
||||
itemMetaData,
|
||||
itemMetaData = Qt::UserRole + 1
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
#include <QtQuickTest/quicktest.h>
|
||||
QUICK_TEST_MAIN(qml_tests)
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
QUICK_TEST_MAIN_WITH_SETUP(qml_tests, Setup)
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
TEMPLATE = app
|
||||
TARGET = qml_tests
|
||||
|
||||
CONFIG += warn_on qmltestcase
|
||||
SOURCES += $$PWD/qml_test_runner.cpp
|
||||
CONFIG-=app_bundle
|
||||
|
||||
SOURCES += $$PWD/qml_test_runner.cpp \
|
||||
setup.cpp
|
||||
|
||||
PROJECT_ROOT = $$PWD/../..//
|
||||
|
||||
INCLUDEPATH += $$PROJECT_ROOT/src $$PROJECT_ROOT/src/modules $$PROJECT_ROOT/3rdparty/qredisclient/src
|
||||
SOURCES += \
|
||||
$$files($$PROJECT_ROOT/src/app/apputils.cpp) \
|
||||
$$files($$PROJECT_ROOT/src/app/qmlutils.cpp) \
|
||||
$$files($$PROJECT_ROOT/src/app/jsonutils.cpp) \
|
||||
$$files($$PROJECT_ROOT/src/app/qcompress.cpp) \
|
||||
$$files($$PROJECT_ROOT/src/modules/value-editor/textcharformat.cpp) \
|
||||
$$files($$PROJECT_ROOT/src/modules/value-editor/syntaxhighlighter.cpp) \
|
||||
$$files($$PROJECT_ROOT/src/modules/value-editor/largetextmodel.cpp) \
|
||||
|
||||
QT += core gui quick network concurrent charts
|
||||
|
||||
release: DESTDIR = $$PROJECT_ROOT/bin/tests
|
||||
debug: DESTDIR = $$PROJECT_ROOT/bin/tests
|
||||
|
||||
@@ -13,3 +29,15 @@ MOC_DIR = $$DESTDIR/qml_obj
|
||||
RCC_DIR = $$DESTDIR/qml_obj
|
||||
|
||||
OTHER_FILES = $$PWD/tst_*.qml
|
||||
|
||||
HEADERS += \
|
||||
setup.h \
|
||||
$$files($$PROJECT_ROOT/src/app/qmlutils.h) \
|
||||
$$files($$PROJECT_ROOT/src/modules/value-editor/textcharformat.h) \
|
||||
$$files($$PROJECT_ROOT/src/modules/value-editor/syntaxhighlighter.h) \
|
||||
$$files($$PROJECT_ROOT/src/modules/value-editor/largetextmodel.h) \
|
||||
|
||||
DISTFILES += \
|
||||
tst_MultilineEditor.qml
|
||||
|
||||
include($$PROJECT_ROOT/3rdparty/3rdparty.pri)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "setup.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
#include "modules/value-editor/syntaxhighlighter.h"
|
||||
#include "modules/value-editor/textcharformat.h"
|
||||
|
||||
void Setup::qmlEngineAvailable(QQmlEngine *engine)
|
||||
{
|
||||
QCoreApplication::instance()->setOrganizationDomain("redisdesktop.com");
|
||||
QCoreApplication::instance()->setOrganizationName("redisdesktop");
|
||||
QCoreApplication::instance()->setApplicationName("RESP.app - Developer GUI for Redis");
|
||||
|
||||
qmlRegisterType<SyntaxHighlighter>("rdm.models", 1, 0, "SyntaxHighlighter");
|
||||
qmlRegisterType<TextCharFormat>("rdm.models", 1, 0, "TextCharFormat");
|
||||
|
||||
m_qmlUtils = QSharedPointer<QmlUtils>(new QmlUtils());
|
||||
engine->rootContext()->setContextProperty("qmlUtils", m_qmlUtils.data());
|
||||
|
||||
m_testUtils = QSharedPointer<TestUtils>(new TestUtils());
|
||||
engine->rootContext()->setContextProperty("testUtils", m_testUtils.data());
|
||||
}
|
||||
|
||||
void TestUtils::removeAppSetting(const QString &category)
|
||||
{
|
||||
QSettings s;
|
||||
s.remove(category);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtQuickTest>
|
||||
#include <QQmlEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QSharedPointer>
|
||||
#include <QQuickTextDocument>
|
||||
#include "app/qmlutils.h"
|
||||
|
||||
class TestUtils : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE void removeAppSetting(const QString& category);
|
||||
};
|
||||
|
||||
class Setup : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Setup() {}
|
||||
|
||||
public slots:
|
||||
void qmlEngineAvailable(QQmlEngine *engine);
|
||||
|
||||
private:
|
||||
QSharedPointer<QmlUtils> m_qmlUtils;
|
||||
QSharedPointer<TestUtils> m_testUtils;
|
||||
};
|
||||
@@ -0,0 +1,111 @@
|
||||
import QtQuick 2.3
|
||||
import QtQml.Models 2.13
|
||||
import QtTest 1.0
|
||||
import Qt.labs.settings 1.0
|
||||
import rdm.models 1.0
|
||||
|
||||
import "./../../src/qml/value-editor/editors/formatters/"
|
||||
import "./../../src/qml/value-editor/editors/"
|
||||
|
||||
TestCase {
|
||||
name: "FormatterTests"
|
||||
|
||||
property string validJson: '{"test": 123}'
|
||||
|
||||
SystemPalette {
|
||||
id: sysPalette
|
||||
}
|
||||
|
||||
Settings {
|
||||
id: defaultFormatterSettings
|
||||
category: "formatter_overrides"
|
||||
|
||||
function cleanup() {
|
||||
testUtils.removeAppSetting("formatter_overrides")
|
||||
defaultFormatterSettings.sync()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: appSettings
|
||||
|
||||
property string valueEditorFont: "sans-serif"
|
||||
}
|
||||
|
||||
ValueFormatters {
|
||||
id: valueFormattersModel
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: valueEditor
|
||||
|
||||
property var item: QtObject {
|
||||
function isEdited() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MultilineEditor {
|
||||
id: editor
|
||||
|
||||
// ValueEditor fake properties
|
||||
property bool isMultiRow: true
|
||||
property string keyType: "list"
|
||||
property string keyName: "fake_list"
|
||||
}
|
||||
|
||||
function init() {
|
||||
defaultFormatterSettings.cleanup()
|
||||
editor.defaultFormatter = "auto"
|
||||
}
|
||||
|
||||
function test_loadFormattedValue() {
|
||||
editor.loadFormattedValue(validJson)
|
||||
|
||||
verify(editor.__formatterCombobox.currentText === "JSON")
|
||||
verify(editor.__textView.format === "json")
|
||||
verify(!editor.__textView.readOnly)
|
||||
verify(editor.__textView.textFormat === TextEdit.PlainText)
|
||||
}
|
||||
|
||||
function test_loadFormattedValue_withDefaultFormatter() {
|
||||
editor.defaultFormatter = "HEX TABLE"
|
||||
defaultFormatterSettings.setValue(editor.lastSelectedFormatterSetting, "Plain Text")
|
||||
defaultFormatterSettings.sync()
|
||||
|
||||
editor.loadFormattedValue(validJson)
|
||||
|
||||
verify(editor.__formatterCombobox.currentText === "HEX TABLE")
|
||||
verify(editor.__textView.format === "html")
|
||||
verify(editor.__textView.readOnly)
|
||||
verify(editor.__textView.textFormat === TextEdit.RichText)
|
||||
}
|
||||
|
||||
function test_loadFormattedValue_withLastSelectedFormatter() {
|
||||
editor.defaultFormatter = "last_used"
|
||||
defaultFormatterSettings.setValue(editor.lastSelectedFormatterSetting, "Plain Text")
|
||||
defaultFormatterSettings.sync()
|
||||
|
||||
editor.loadFormattedValue(validJson)
|
||||
|
||||
verify(editor.__formatterCombobox.currentText === "Plain Text")
|
||||
verify(editor.__textView.format === "plain")
|
||||
verify(!editor.__textView.readOnly)
|
||||
verify(editor.__textView.textFormat === TextEdit.PlainText)
|
||||
}
|
||||
|
||||
function test_loadFormattedValue_withLastSelectedFormatter_and_key_override() {
|
||||
defaultFormatterSettings.setValue(editor.keyName, "HEX")
|
||||
defaultFormatterSettings.setValue(editor.lastSelectedFormatterSetting, "Plain Text")
|
||||
defaultFormatterSettings.sync()
|
||||
|
||||
editor.loadFormattedValue(validJson)
|
||||
|
||||
verify(editor.__formatterCombobox.currentText === "HEX")
|
||||
verify(editor.__textView.format === "plain")
|
||||
verify(!editor.__textView.readOnly)
|
||||
verify(editor.__textView.textFormat === TextEdit.PlainText)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
// tests
|
||||
#include <qredisclient/redisclient.h>
|
||||
#include <iostream>
|
||||
#include "testcases/app/test_abstractkey.h"
|
||||
#include "testcases/app/test_configmanager.h"
|
||||
#include "testcases/app/test_connectionsmanager.h"
|
||||
#include "testcases/app/test_keymodels.h"
|
||||
@@ -21,19 +20,21 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
int allTestsResult = 0
|
||||
// connections-tree module
|
||||
+ QTest::qExec(new TestServerItem, argc, argv) +
|
||||
QTest::qExec(new TestDatabaseItem, argc, argv) +
|
||||
QTest::qExec(new TestModel, argc, argv)
|
||||
#ifndef Q_OS_WIN
|
||||
+ QTest::qExec(new TestServerItem, argc, argv)
|
||||
+ QTest::qExec(new TestDatabaseItem, argc, argv)
|
||||
#endif
|
||||
+ QTest::qExec(new TestModel, argc, argv)
|
||||
|
||||
// console module
|
||||
+ QTest::qExec(new TestConsoleOperations, argc, argv)
|
||||
|
||||
// app
|
||||
+ QTest::qExec(new TestConnectionsManager, argc, argv) +
|
||||
QTest::qExec(new TestConfigManager, argc, argv) +
|
||||
QTest::qExec(new TestKeyModels, argc, argv) +
|
||||
QTest::qExec(new TestTreeOperations, argc, argv) +
|
||||
QTest::qExec(new TestAbstractKey, argc, argv);
|
||||
+ QTest::qExec(new TestConnectionsManager, argc, argv)
|
||||
+ QTest::qExec(new TestConfigManager, argc, argv)
|
||||
+ QTest::qExec(new TestKeyModels, argc, argv)
|
||||
+ QTest::qExec(new TestTreeOperations, argc, argv)
|
||||
;
|
||||
|
||||
if (allTestsResult == 0)
|
||||
qDebug() << "[Tests PASS]";
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
|
||||
#include "basetestcase.h"
|
||||
#include "models/connectionconf.h"
|
||||
|
||||
class RESPBaseTestCase : public BaseTestCase {
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
ServerConfig getDummyConfig(QString name = "test") {
|
||||
ServerConfig dummyConf("127.0.0.1", "",
|
||||
RedisClient::ConnectionConfig ::DEFAULT_REDIS_PORT,
|
||||
name);
|
||||
dummyConf.setTimeouts(2000, 2000);
|
||||
return dummyConf;
|
||||
}
|
||||
};
|
||||
@@ -4,9 +4,10 @@ APP_SRC_DIR = $$PWD/../../../../src/app/
|
||||
INCLUDEPATH += $$APP_SRC_DIR
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/test_*.h \
|
||||
$$files($$PWD/test_*.h) \
|
||||
$$APP_SRC_DIR/events.h \
|
||||
$$APP_SRC_DIR/apputils.h \
|
||||
$$APP_SRC_DIR/jsonutils.h \
|
||||
$$APP_SRC_DIR/models/connectionsmanager.h \
|
||||
$$APP_SRC_DIR/models/configmanager.h \
|
||||
$$APP_SRC_DIR/models/connectionconf.h \
|
||||
@@ -25,9 +26,10 @@ HEADERS += \
|
||||
$$APP_SRC_DIR/models/key-models/newkeyrequest.h \
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/test_*.cpp \
|
||||
$$files($$PWD/test_*.cpp) \
|
||||
$$APP_SRC_DIR/events.cpp \
|
||||
$$APP_SRC_DIR/apputils.cpp \
|
||||
$$APP_SRC_DIR/jsonutils.cpp \
|
||||
$$APP_SRC_DIR/models/connectionsmanager.cpp \
|
||||
$$APP_SRC_DIR/models/configmanager.cpp \
|
||||
$$APP_SRC_DIR/models/connectiongroup.cpp \
|
||||
@@ -42,7 +44,8 @@ SOURCES += \
|
||||
$$APP_SRC_DIR/models/key-models/sortedsetkey.cpp \
|
||||
$$APP_SRC_DIR/models/key-models/hashkey.cpp \
|
||||
$$APP_SRC_DIR/models/key-models/rejsonkey.cpp \
|
||||
$$APP_SRC_DIR/models/key-models/newkeyrequest.cpp \
|
||||
|
||||
OTHER_FILES += \
|
||||
connections.xml
|
||||
$$PWD/connections.json
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<connections>
|
||||
<connection name="local" host="localhost" port="7777" auth="foobared" />
|
||||
</connections>
|
||||
@@ -1,10 +0,0 @@
|
||||
#include <QtCore>
|
||||
#include <QTest>
|
||||
|
||||
#include "test_abstractkey.h"
|
||||
#include "app/models/key-models/abstractkey.h"
|
||||
|
||||
void TestAbstractKey::testValueToBinary()
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "basetestcase.h"
|
||||
|
||||
class TestAbstractKey : public BaseTestCase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void testValueToBinary();
|
||||
|
||||
};
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
void TestConfigManager::testGetApplicationConfigPath()
|
||||
{
|
||||
#ifdef Q_OS_MACX
|
||||
QSKIP("SKIP ON OSX");
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
QSKIP("SKIP ON Windows");
|
||||
#endif
|
||||
|
||||
@@ -10,12 +10,13 @@ TestConnectionsManager::TestConnectionsManager() {}
|
||||
|
||||
void TestConnectionsManager::loadConnectionsConfigFromFile() {
|
||||
// given
|
||||
// xml fixture
|
||||
// json fixture
|
||||
QString configTestFile = "./unit_tests/testcases/app/connections.json";
|
||||
auto events = QSharedPointer<Events>(new Events());
|
||||
|
||||
// when loads connections
|
||||
ConnectionsManager testManager(configTestFile, events);
|
||||
testManager.loadConnections();
|
||||
|
||||
// then
|
||||
QCOMPARE(testManager.size(), 1);
|
||||
@@ -42,13 +43,13 @@ void TestConnectionsManager::saveConnectionsConfigToFile() {
|
||||
testManager.addNewConnection(connectionConfig, true);
|
||||
// load everything from scratch
|
||||
ConnectionsManager testManagerNew(configTestFile, events);
|
||||
testManagerNew.loadConnections();
|
||||
QModelIndex testIndex = testManagerNew.index(0, 0, QModelIndex());
|
||||
QString actualConnectionName =
|
||||
testManagerNew.data(testIndex, ConnectionsTree::Model::itemName)
|
||||
.toString();
|
||||
auto metadata =
|
||||
testManagerNew.data(testIndex, ConnectionsTree::Model::itemMetaData).toHash();
|
||||
|
||||
// then
|
||||
qDebug() << "Actual name: " << actualConnectionName;
|
||||
// then
|
||||
QCOMPARE(QFile::exists(configTestFile), true);
|
||||
QCOMPARE(actualConnectionName, connectionName);
|
||||
QCOMPARE(testManagerNew.rowCount(), 1);
|
||||
QCOMPARE(metadata["name"], QVariant(connectionName));
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include "basetestcase.h"
|
||||
#include "respbasetestcase.h"
|
||||
#include "value-editor/tabsmodel.h"
|
||||
|
||||
class TestConnectionsManager : public BaseTestCase
|
||||
class TestConnectionsManager : public RESPBaseTestCase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -205,21 +205,36 @@ void TestKeyModels::testKeyModelModifyRows() {
|
||||
QFETCH(QStringList, testReplies);
|
||||
QFETCH(QVariantMap, row);
|
||||
QFETCH(int, role);
|
||||
bool rowsCountLoaded = false;
|
||||
auto dummyConnection = getRealConnectionWithDummyTransporter(testReplies);
|
||||
|
||||
// when
|
||||
QSharedPointer<ValueEditor::Model> keyModel = getKeyModel(dummyConnection);
|
||||
QVERIFY(keyModel.isNull() == false);
|
||||
keyModel->loadRows(0, 10, [](const QString&, unsigned long) { return; });
|
||||
keyModel->loadRowsCount([keyModel, &rowsCountLoaded](QString) {
|
||||
rowsCountLoaded = true;
|
||||
|
||||
keyModel->loadRows(0, 10, [](const QString& err, unsigned long) {
|
||||
if (!err.isEmpty()) {
|
||||
qWarning() << err;
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
wait(500);
|
||||
keyModel->addRow(row, [](QString) {});
|
||||
|
||||
row["value"] = "fakeUpdate";
|
||||
keyModel->updateRow(0, row, [](QString) {});
|
||||
wait(100);
|
||||
keyModel->updateRow(0, row, [](const QString& err) {
|
||||
if (!err.isEmpty()) {
|
||||
qWarning() << err;
|
||||
}
|
||||
});
|
||||
wait(500);
|
||||
|
||||
QVariant actualResult = keyModel->getData(0, role);
|
||||
keyModel->removeRow(0, [](QString) {});
|
||||
|
||||
// then
|
||||
QVERIFY(rowsCountLoaded);
|
||||
QVERIFY(actualResult.type() == QVariant::ByteArray);
|
||||
QCOMPARE(actualResult.toString(), QString("fakeUpdate"));
|
||||
}
|
||||
@@ -235,65 +250,58 @@ void TestKeyModels::testKeyModelModifyRows_data() {
|
||||
<< (QStringList() << "+string\r\n"
|
||||
<< ":-1\r\n"
|
||||
<< "$17\r\n__nice_test_data!\r\n"
|
||||
<< "+OK\r\n"
|
||||
<< "+OK\r\n")
|
||||
<< stringRow << Qt::UserRole + 1;
|
||||
|
||||
QVariantMap listRow;
|
||||
listRow["row"] = 0;
|
||||
listRow["rowNumber"] = 0;
|
||||
listRow["value"] = "test";
|
||||
QTest::newRow("Valid list model")
|
||||
<< (QStringList() << "+list\r\n"
|
||||
<< ":-1\r\n"
|
||||
<< ":2\r\n"
|
||||
<< "*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"
|
||||
<< "+OK\r\n"
|
||||
<< "*1\r\n$3\r\nfoo\r\n"
|
||||
<< "+OK\r\n"
|
||||
<< "*1\r\n$10\r\nfakeUpdate\r\n"
|
||||
<< "+OK\r\n"
|
||||
<< "+OK\r\n")
|
||||
<< listRow << Qt::UserRole + 2;
|
||||
|
||||
QVariantMap setRow;
|
||||
setRow["row"] = 0;
|
||||
setRow["rowNumber"] = 0;
|
||||
setRow["value"] = "test";
|
||||
QTest::newRow("Valid set model")
|
||||
<< (QStringList() << "+set\r\n"
|
||||
<< ":-1\r\n"
|
||||
<< ":2\r\n"
|
||||
<< "*2\r\n$1\r\n0\r\n*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"
|
||||
<< ":1\r\n"
|
||||
<< "+OK\r\n"
|
||||
<< ":1\r\n"
|
||||
<< "+OK\r\n")
|
||||
<< ":1\r\n")
|
||||
<< setRow << Qt::UserRole + 2;
|
||||
|
||||
QVariantMap zsetRow;
|
||||
zsetRow["row"] = 0;
|
||||
zsetRow["rowNumber"] = 0;
|
||||
zsetRow["value"] = "test";
|
||||
zsetRow["score"] = 1.1;
|
||||
QTest::newRow("Valid zset model")
|
||||
<< (QStringList()
|
||||
<< "+zset\r\n"
|
||||
<< ":-1\r\n"
|
||||
<< ":2\r\n"
|
||||
<< "*4\r\n$3\r\nfoo\r\n$1\r\n1\r\n$3\r\nbar\r\n$1\r\n1\r\n"
|
||||
<< ":1\r\n"
|
||||
<< ":1\r\n"
|
||||
<< ":1\r\n"
|
||||
<< ":1\r\n")
|
||||
<< zsetRow << Qt::UserRole + 2;
|
||||
|
||||
QVariantMap hashRow;
|
||||
hashRow["row"] = 0;
|
||||
hashRow["rowNumber"] = 0;
|
||||
hashRow["key"] = "test";
|
||||
hashRow["value"] = "test";
|
||||
QTest::newRow("Valid hash model")
|
||||
<< (QStringList() << "+hash\r\n"
|
||||
<< ":-1\r\n"
|
||||
<< ":2\r\n"
|
||||
<< "*2\r\n$1\r\n0\r\n*4\r\n$3\r\nfoo\r\n$1\r\n1\r\n$"
|
||||
"3\r\nbar\r\n$1\r\n1\r\n"
|
||||
<< ":1\r\n"
|
||||
<< ":1\r\n"
|
||||
<< ":1\r\n"
|
||||
<< ":1\r\n")
|
||||
<< hashRow << Qt::UserRole + 3;
|
||||
}
|
||||
|
||||
@@ -45,13 +45,14 @@ void TestTreeOperations::testGetDatabases() {
|
||||
TreeOperations operations(getDummyConfig(), events);
|
||||
operations.setConnection(connection);
|
||||
operations.getDatabases(
|
||||
[&callbackCalled, &result](const RedisClient::DatabaseList& r, const QString& err) {
|
||||
[&callbackCalled, &result](const RedisClient::DatabaseList& r, const QString&) {
|
||||
callbackCalled = true;
|
||||
result = r;
|
||||
});
|
||||
|
||||
// then
|
||||
wait(100);
|
||||
connection.clear();
|
||||
QCOMPARE(callbackCalled, true);
|
||||
QCOMPARE(result.size(), 13);
|
||||
}
|
||||
@@ -73,24 +74,16 @@ void TestTreeOperations::testLoadNamespaceItems() {
|
||||
new TreeOperations(getDummyConfig(), events));
|
||||
operations->setConnection(connection);
|
||||
|
||||
ConnectionsTree::Model dummyModel;
|
||||
QSharedPointer<ConnectionsTree::DatabaseItem> item(
|
||||
new ConnectionsTree::DatabaseItem(
|
||||
0, 1, operations, QWeakPointer<ConnectionsTree::TreeItem>(),
|
||||
dummyModel));
|
||||
|
||||
// when
|
||||
bool callbackCalled = false;
|
||||
|
||||
operations->loadNamespaceItems(
|
||||
qSharedPointerDynamicCast<ConnectionsTree::AbstractNamespaceItem>(item),
|
||||
QString(),
|
||||
[&callbackCalled](const QString& err) {
|
||||
0, QString("*"),
|
||||
[&callbackCalled](const QList<QByteArray>& keys, const QString& err) {
|
||||
// then - part 2
|
||||
callbackCalled = true;
|
||||
QVERIFY2(err.isEmpty(), qPrintable(err));
|
||||
},
|
||||
QSet<QByteArray>());
|
||||
});
|
||||
|
||||
// then - part 1
|
||||
wait(5);
|
||||
@@ -105,17 +98,17 @@ void TestTreeOperations::testLoadNamespaceItems_data() {
|
||||
QTest::addColumn<QList<QVariant> >("expectedScanResponses");
|
||||
QTest::addColumn<QStringList>("expectedResponses");
|
||||
QTest::newRow("SCAN execution")
|
||||
<< false << 0u << 1u
|
||||
<< 1u << 1u
|
||||
<< (QList<QVariant>()
|
||||
<< QVariant(QVariantList() << QString("test") << QString("test2")))
|
||||
<< (QStringList() << "");
|
||||
<< (QStringList() << "+OK\r\n");
|
||||
}
|
||||
|
||||
void TestTreeOperations::testFlushDb() {
|
||||
// given
|
||||
auto events = QSharedPointer<Events>(new Events());
|
||||
auto connection = getFakeConnection(QList<QVariant>() << QVariant(),
|
||||
QStringList() << "+OK");
|
||||
QStringList() << "+OK\r\n");
|
||||
|
||||
// when
|
||||
bool callbackCalled = false;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "basetestcase.h"
|
||||
#include "respbasetestcase.h"
|
||||
|
||||
class TestTreeOperations : public BaseTestCase
|
||||
class TestTreeOperations : public RESPBaseTestCase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
CONNECTIONS_TREE_SRC_DIR = $$PWD/../../../../src/modules/connections-tree/
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/*.h \
|
||||
$$PWD/mocks/*.h \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/items/*.h \
|
||||
$$PWD/mocks.h \
|
||||
$$files($$PWD/test_*.h) \
|
||||
$$files($$CONNECTIONS_TREE_SRC_DIR/items/*.h) \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/operations.h \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/utils.h \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/keysrendering.h \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/model.h \
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/*.cpp \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/items/*.cpp \
|
||||
$$PWD/mocks.cpp \
|
||||
$$files($$PWD/test_*.cpp) \
|
||||
$$files($$CONNECTIONS_TREE_SRC_DIR/items/*.cpp) \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/utils.cpp \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/keysrendering.cpp \
|
||||
$$CONNECTIONS_TREE_SRC_DIR/model.cpp \
|
||||
|
||||
OTHER_FILES += \
|
||||
connections.xml
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "mocks.h"
|
||||
|
||||
#include <qredisclient/connection.h>
|
||||
|
||||
#include <QFuture>
|
||||
|
||||
Mock<ConnectionsTree::Operations> getOperations() {
|
||||
Mock<ConnectionsTree::Operations> operations;
|
||||
When(Method(operations, getNamespaceSeparator)).AlwaysReturn(":");
|
||||
When(Method(operations, defaultFilter)).AlwaysReturn("*");
|
||||
When(Method(operations, mode)).AlwaysReturn("default");
|
||||
When(Method(operations, disconnect)).Return();
|
||||
When(Method(operations, notifyDbWasUnloaded)).Return();
|
||||
return operations;
|
||||
}
|
||||
|
||||
Mock<ConnectionsTree::Operations> getOperationsWithGetDatabases(
|
||||
RedisClient::DatabaseList db, const QString &err) {
|
||||
auto op = getOperations();
|
||||
|
||||
When(Method(op, getDatabases))
|
||||
.AlwaysDo([db,
|
||||
err](std::function<void(RedisClient::DatabaseList, const QString &)>
|
||||
cb) -> QFuture<void> {
|
||||
cb(db, err);
|
||||
return QFuture<void>();
|
||||
});
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
Mock<ConnectionsTree::Operations> getOperationsWithDbAndKeys(
|
||||
RedisClient::DatabaseList db, const QString &err, QList<QByteArray> keys) {
|
||||
auto op = getOperationsWithGetDatabases(db, err);
|
||||
|
||||
When(Method(op, loadNamespaceItems))
|
||||
.Do([keys, err](uint, const QString&,
|
||||
std::function<void(
|
||||
const RedisClient::Connection::RawKeysList &keylist,
|
||||
const QString &)>
|
||||
cb) -> void {
|
||||
cb(keys, err);
|
||||
});
|
||||
|
||||
return op;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <fakeit.hpp>
|
||||
|
||||
#include "connections-tree/operations.h"
|
||||
|
||||
using namespace fakeit;
|
||||
|
||||
static void fakeDeleter(ConnectionsTree::Operations*) {}
|
||||
|
||||
Mock<ConnectionsTree::Operations> getOperations();
|
||||
|
||||
Mock<ConnectionsTree::Operations> getOperationsWithGetDatabases(
|
||||
RedisClient::DatabaseList db, const QString& err);
|
||||
|
||||
Mock<ConnectionsTree::Operations> getOperationsWithDbAndKeys(
|
||||
RedisClient::DatabaseList db, const QString& err, QList<QByteArray> keys);
|
||||
@@ -1,106 +0,0 @@
|
||||
#pragma once
|
||||
#include <QFuture>
|
||||
#include "connections-tree/items/abstractnamespaceitem.h"
|
||||
#include "connections-tree/items/keyitem.h"
|
||||
#include "connections-tree/items/treeitem.h"
|
||||
#include "connections-tree/operations.h"
|
||||
|
||||
class ItemOperationsMock : public ConnectionsTree::Operations {
|
||||
public:
|
||||
ItemOperationsMock(bool positive_mode = true)
|
||||
: m_positive_mode(positive_mode) {}
|
||||
|
||||
QMap<int, int> databases;
|
||||
QString databaseLoadingError;
|
||||
|
||||
virtual QFuture<void> getDatabases(
|
||||
std::function<void(QMap<int, int>, const QString& err)> callback) override {
|
||||
if (m_positive_mode) {
|
||||
callback(databases, databaseLoadingError);
|
||||
return QFuture<void>();
|
||||
} else {
|
||||
return QFuture<void>();
|
||||
}
|
||||
}
|
||||
|
||||
QList<QByteArray> keys;
|
||||
void loadNamespaceItems(
|
||||
QSharedPointer<ConnectionsTree::AbstractNamespaceItem> parent,
|
||||
const QString&, std::function<void(const QString&)> callback,
|
||||
QSet<QByteArray>) override {
|
||||
if (m_positive_mode) {
|
||||
for (QByteArray key : keys) {
|
||||
parent->append(QSharedPointer<ConnectionsTree::KeyItem>(
|
||||
new ConnectionsTree::KeyItem(key, parent, parent->model())));
|
||||
}
|
||||
parent->notifyModel();
|
||||
|
||||
callback(QString());
|
||||
} else {
|
||||
throw ConnectionsTree::Operations::Exception("fake error");
|
||||
}
|
||||
}
|
||||
|
||||
QString namespaceSeparator = ":";
|
||||
QString getNamespaceSeparator() { return namespaceSeparator; }
|
||||
|
||||
QString defaultKeysFilter = "*";
|
||||
QString defaultFilter() { return defaultKeysFilter; }
|
||||
|
||||
void disconnect() {}
|
||||
|
||||
virtual void openKeyTab(QSharedPointer<ConnectionsTree::KeyItem>,
|
||||
bool) override {}
|
||||
|
||||
virtual void openConsoleTab(int dbIndex = 0) override {}
|
||||
|
||||
virtual void openServerStats() override {}
|
||||
|
||||
void openNewKeyDialog(int, std::function<void()>,
|
||||
QString = QString()) override {}
|
||||
|
||||
virtual void notifyDbWasUnloaded(int) override {}
|
||||
|
||||
virtual void deleteDbKey(ConnectionsTree::KeyItem&,
|
||||
std::function<void(const QString&)>) override {}
|
||||
|
||||
virtual void deleteDbNamespace(ConnectionsTree::NamespaceItem&) override {}
|
||||
|
||||
virtual void flushDb(int, std::function<void(const QString&)>) override {}
|
||||
|
||||
virtual QString mode() { return QString("fake"); }
|
||||
|
||||
virtual bool isConnected() const { return true; }
|
||||
|
||||
virtual void duplicateConnection() override {}
|
||||
|
||||
virtual QFuture<bool> connectionSupportsMemoryOperations() override {
|
||||
return QFuture<bool>();
|
||||
}
|
||||
|
||||
virtual void getUsedMemory(const QList<QByteArray>& keys, int dbIndex,
|
||||
std::function<void(qlonglong)> result,
|
||||
std::function<void(qlonglong)> progress) override {
|
||||
}
|
||||
|
||||
void resetConnection() override {}
|
||||
|
||||
void deleteDbKeys(ConnectionsTree::DatabaseItem &db) override {};
|
||||
void setTTL(ConnectionsTree::AbstractNamespaceItem &ns) override {};
|
||||
void copyKeys(ConnectionsTree::AbstractNamespaceItem &ns) override {};
|
||||
void importKeysFromRdb(ConnectionsTree::DatabaseItem &ns) override {};
|
||||
void openKeyIfExists(const QByteArray& key,
|
||||
QSharedPointer<ConnectionsTree::DatabaseItem> parent,
|
||||
std::function<void(const QString&, bool)> callback) override {};
|
||||
|
||||
QString connectionName() const override {
|
||||
return "test";
|
||||
}
|
||||
|
||||
QVariantMap getFilterHistory() override {
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool m_positive_mode;
|
||||
};
|
||||
@@ -1,66 +1,56 @@
|
||||
#include "test_databaseitem.h"
|
||||
#include "connections-tree/items/databaseitem.h"
|
||||
#include "connections-tree/items/serveritem.h"
|
||||
#include "connections-tree/model.h"
|
||||
#include "mocks/itemoperationsmock.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
#include <QtCore>
|
||||
|
||||
#include "connections-tree/items/databaseitem.h"
|
||||
#include "connections-tree/items/serveritem.h"
|
||||
#include "connections-tree/model.h"
|
||||
#include "mocks.h"
|
||||
|
||||
using namespace ConnectionsTree;
|
||||
|
||||
TestDatabaseItem::TestDatabaseItem(QObject* parent) : QObject(parent) {}
|
||||
|
||||
void TestDatabaseItem::testLoadKeys() {
|
||||
// given
|
||||
ItemOperationsMock* operations = new ItemOperationsMock();
|
||||
QSharedPointer<Operations> operations_(dynamic_cast<Operations*>(operations));
|
||||
operations->databases.insert(0, 55);
|
||||
|
||||
QList<QByteArray> keys;
|
||||
for (int i = 1; i < 100000; i++) {
|
||||
operations->keys.append(QString("test-%1-key").arg(i).toUtf8());
|
||||
keys.append(QString("test-%1-key").arg(i).toUtf8());
|
||||
}
|
||||
operations->keys.append("test-2-key");
|
||||
operations->keys.append("test-2-key:subkey");
|
||||
operations->keys.append("test-2-key:namespace:subkey2");
|
||||
keys.append("test-2-key");
|
||||
keys.append("test-2-key:subkey");
|
||||
keys.append("test-2-key:namespace:subkey2");
|
||||
|
||||
auto operations = getOperationsWithDbAndKeys({{0, 55}}, QString(), keys);
|
||||
|
||||
Operations& mock = operations.get();
|
||||
auto ptr = QSharedPointer<Operations>(&mock, fakeDeleter);
|
||||
|
||||
Model dummyModel;
|
||||
QSharedPointer<ServerItem> parentItem(
|
||||
new ServerItem(operations_, dummyModel));
|
||||
QSharedPointer<ServerItem> parentItem(new ServerItem(ptr, dummyModel));
|
||||
parentItem->setWeakPointer(parentItem.toWeakRef());
|
||||
|
||||
// when
|
||||
parentItem->handleEvent("click");
|
||||
QTest::qWait(150);
|
||||
qDebug() << parentItem->childCount();
|
||||
QSharedPointer<TreeItem> item = parentItem->child(0);
|
||||
|
||||
QSignalSpy spy(&dummyModel, &Model::itemChildsLoaded);
|
||||
item->handleEvent("click");
|
||||
|
||||
QTest::qWait(150);
|
||||
|
||||
// then
|
||||
QCOMPARE(spy.count(), 1);
|
||||
QCOMPARE(item->childCount(), (unsigned int)100002);
|
||||
// TODO: check mock calls
|
||||
// TODO: verify "load more" item is last
|
||||
// TODO: verify namespaces are rendered correctly
|
||||
QCOMPARE(item->childCount(), (unsigned int)1002);
|
||||
QCOMPARE(item->getDisplayName(), QString("db0 (55)"));
|
||||
QCOMPARE(item->getAllChilds().isEmpty(), false);
|
||||
QCOMPARE(item->isEnabled(), true);
|
||||
QCOMPARE(item->isLocked(), false);
|
||||
}
|
||||
|
||||
// FIXME: add test for reload instead
|
||||
// void TestDatabaseItem::testUnloadKeys()
|
||||
//{
|
||||
// //given
|
||||
// ItemOperationsMock* operations = new ItemOperationsMock();
|
||||
// Model model;
|
||||
// DatabaseItem item(0, 300,
|
||||
// QSharedPointer<Operations>(dynamic_cast<Operations*>(operations)),
|
||||
// QWeakPointer<ConnectionsTree::TreeItem>(), model);
|
||||
|
||||
// //when
|
||||
// item.unload();
|
||||
|
||||
// //then
|
||||
// QCOMPARE(item.childCount(), (unsigned int)0);
|
||||
// QCOMPARE(item.isLocked(), false);
|
||||
//}
|
||||
|
||||
@@ -7,6 +7,5 @@ class TestDatabaseItem : public QObject {
|
||||
explicit TestDatabaseItem(QObject *parent = 0);
|
||||
|
||||
private slots:
|
||||
void testLoadKeys();
|
||||
// void testUnloadKeys();
|
||||
void testLoadKeys();
|
||||
};
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
#include "test_model.h"
|
||||
#include <modeltest.h>
|
||||
#include "connections-tree/model.h"
|
||||
|
||||
void TestModel::testLoadImplementation()
|
||||
{
|
||||
// Given
|
||||
ConnectionsTree::Model m;
|
||||
#include <QAbstractItemModelTester>
|
||||
|
||||
// When
|
||||
ModelTest test((QAbstractItemModel *)&m);
|
||||
void TestModel::testLoadImplementation() {
|
||||
// Given
|
||||
ConnectionsTree::Model m;
|
||||
|
||||
// Then
|
||||
// No assertions
|
||||
Q_UNUSED(test);
|
||||
// When
|
||||
auto test =
|
||||
QScopedPointer<QAbstractItemModelTester>(new QAbstractItemModelTester(
|
||||
(QAbstractItemModel *)&m,
|
||||
QAbstractItemModelTester::FailureReportingMode::Fatal, this));
|
||||
|
||||
// Then
|
||||
// No assertions
|
||||
Q_UNUSED(test);
|
||||
}
|
||||
|
||||
@@ -1,104 +1,113 @@
|
||||
#include "test_serveritem.h"
|
||||
#include "mocks/itemoperationsmock.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
#include <QtCore>
|
||||
|
||||
#include "connections-tree/items/serveritem.h"
|
||||
#include "connections-tree/model.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QTest>
|
||||
#include <QSignalSpy>
|
||||
#include <QMenu>
|
||||
#include "mocks.h"
|
||||
|
||||
using namespace ConnectionsTree;
|
||||
using namespace fakeit;
|
||||
|
||||
TestServerItem::TestServerItem(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
TestServerItem::TestServerItem(QObject* parent) : QObject(parent) {}
|
||||
|
||||
void TestServerItem::testLoad() {
|
||||
// given
|
||||
QMap<int, int> databases = {{0, 55}};
|
||||
Mock<Operations> operations =
|
||||
getOperationsWithGetDatabases(databases, QString());
|
||||
Operations& mock = operations.get();
|
||||
auto ptr = QSharedPointer<Operations>(&mock, fakeDeleter);
|
||||
|
||||
QFETCH(QString, action);
|
||||
|
||||
Model dummyModel;
|
||||
ServerItem item{ptr, dummyModel};
|
||||
|
||||
// when
|
||||
item.handleEvent(action);
|
||||
|
||||
QTest::qWait(50);
|
||||
|
||||
// then
|
||||
QCOMPARE(item.childCount(), static_cast<uint>(1));
|
||||
QCOMPARE(item.child(0)->getDisplayName(), QString("db0 (55)"));
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.isDatabaseListLoaded(), true);
|
||||
}
|
||||
|
||||
void TestServerItem::testLoad()
|
||||
{
|
||||
//given
|
||||
ItemOperationsMock* operations = new ItemOperationsMock();
|
||||
operations->databases.insert(0, 55);
|
||||
Model dummyModel;
|
||||
ServerItem item {QSharedPointer<Operations>(dynamic_cast<Operations*>(operations)), dummyModel};
|
||||
QSignalSpy spy(&dummyModel, SIGNAL(itemChildsLoaded(QWeakPointer<TreeItem>)));
|
||||
|
||||
//when
|
||||
item.handleEvent("click");
|
||||
|
||||
//then
|
||||
QCOMPARE(spy.count(), 1);
|
||||
QCOMPARE(item.childCount(), static_cast<uint>(1));
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.isDatabaseListLoaded(), true);
|
||||
void TestServerItem::testLoad_data() {
|
||||
QTest::addColumn<QString>("action");
|
||||
QTest::newRow("load") << "click";
|
||||
QTest::newRow("reload") << "reload";
|
||||
}
|
||||
|
||||
void TestServerItem::testLoad_invalid()
|
||||
{
|
||||
//given
|
||||
ItemOperationsMock* operations = new ItemOperationsMock(false);
|
||||
Model dummyModel;
|
||||
ServerItem item {QSharedPointer<Operations>(dynamic_cast<Operations*>(operations)), dummyModel};
|
||||
void TestServerItem::testBasicMethods() {
|
||||
// given
|
||||
Mock<Operations> operations;
|
||||
When(Method(operations, connectionName)).Return("test");
|
||||
Operations& mock = operations.get();
|
||||
|
||||
//when
|
||||
item.handleEvent("click");
|
||||
auto ptr = QSharedPointer<Operations>(&mock, fakeDeleter);
|
||||
|
||||
//then
|
||||
QCOMPARE(item.childCount(), static_cast<uint>(0));
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.isDatabaseListLoaded(), false);
|
||||
Model dummyModel;
|
||||
|
||||
// when
|
||||
ServerItem item(ptr, dummyModel);
|
||||
|
||||
// then
|
||||
QCOMPARE(item.getDisplayName(), QString("test"));
|
||||
QCOMPARE(item.parent() == nullptr, true);
|
||||
QCOMPARE(item.isEnabled(), true);
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.child(0).isNull(), true);
|
||||
QCOMPARE(item.getAllChilds().isEmpty(), true);
|
||||
QCOMPARE(item.row(), 0);
|
||||
}
|
||||
|
||||
void TestServerItem::testUnload()
|
||||
{
|
||||
//given
|
||||
ItemOperationsMock* operations = new ItemOperationsMock();
|
||||
operations->databases.insert(0, 55);
|
||||
Model dummyModel;
|
||||
ServerItem item((QSharedPointer<Operations>(dynamic_cast<Operations*>(operations))), dummyModel);
|
||||
void TestServerItem::testLoad_invalid() {
|
||||
// given
|
||||
Mock<Operations> operations =
|
||||
getOperationsWithGetDatabases({}, QString("fake connection error"));
|
||||
Operations& mock = operations.get();
|
||||
auto ptr = QSharedPointer<Operations>(&mock, fakeDeleter);
|
||||
|
||||
//when
|
||||
item.handleEvent("unload");
|
||||
Model dummyModel;
|
||||
ServerItem item{ptr, dummyModel};
|
||||
|
||||
//then
|
||||
QCOMPARE(item.childCount(), static_cast<uint>(0));
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.isDatabaseListLoaded(), false);
|
||||
// when
|
||||
item.handleEvent("click");
|
||||
QTest::qWait(50);
|
||||
|
||||
// then
|
||||
// TODO: check mock calls
|
||||
QCOMPARE(item.childCount(), static_cast<uint>(0));
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.isDatabaseListLoaded(), false);
|
||||
}
|
||||
|
||||
void TestServerItem::testReload()
|
||||
{
|
||||
//given
|
||||
ItemOperationsMock* operations = new ItemOperationsMock();
|
||||
operations->databases.insert(0, 55);
|
||||
Model dummyModel;
|
||||
ServerItem item{(QSharedPointer<Operations>(dynamic_cast<Operations*>(operations))), dummyModel};
|
||||
QSignalSpy spy(&dummyModel, SIGNAL(itemChildsLoaded(QWeakPointer<TreeItem>)));
|
||||
void TestServerItem::testUnload() {
|
||||
// given
|
||||
QMap<int, int> databases = {{0, 55}};
|
||||
Mock<Operations> operations =
|
||||
getOperationsWithGetDatabases(databases, QString());
|
||||
Operations& mock = operations.get();
|
||||
auto ptr = QSharedPointer<Operations>(&mock, fakeDeleter);
|
||||
|
||||
//when
|
||||
item.handleEvent("reload");
|
||||
Model dummyModel;
|
||||
ServerItem item{ptr, dummyModel};
|
||||
|
||||
//then
|
||||
QCOMPARE(spy.count(), 1);
|
||||
// when
|
||||
item.handleEvent("click");
|
||||
QTest::qWait(50);
|
||||
item.handleEvent("unload");
|
||||
|
||||
// then
|
||||
// TODO: check mock calls
|
||||
QCOMPARE(item.childCount(), static_cast<uint>(0));
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.isDatabaseListLoaded(), false);
|
||||
}
|
||||
|
||||
void TestServerItem::testBasicMethods()
|
||||
{
|
||||
//given
|
||||
ItemOperationsMock* operations = new ItemOperationsMock();
|
||||
Model dummyModel;
|
||||
|
||||
//when
|
||||
ServerItem item((QSharedPointer<Operations>(dynamic_cast<Operations*>(operations))), dummyModel);
|
||||
|
||||
//then
|
||||
QCOMPARE(item.getDisplayName(), QString("test"));
|
||||
QCOMPARE(item.parent() == nullptr, true);
|
||||
QCOMPARE(item.isEnabled(), true);
|
||||
QCOMPARE(item.isLocked(), false);
|
||||
QCOMPARE(item.child(0).isNull(), true);
|
||||
QCOMPARE(item.getAllChilds().isEmpty(), true);
|
||||
QCOMPARE(item.row(), 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
|
||||
|
||||
class TestServerItem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -10,9 +9,11 @@ public:
|
||||
|
||||
private slots:
|
||||
void testLoad();
|
||||
void testLoad_data();
|
||||
|
||||
void testLoad_invalid();
|
||||
|
||||
void testUnload();
|
||||
void testReload();
|
||||
void testBasicMethods();
|
||||
|
||||
void testBasicMethods();
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
CONSOLE_SRC_DIR = $$PWD/../../../../src/modules/console/
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/*.h \
|
||||
$$files($$PWD/*.h) \
|
||||
$$CONSOLE_SRC_DIR/consolemodel.h \
|
||||
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/*.cpp \
|
||||
$$files($$PWD/*.cpp) \
|
||||
$$CONSOLE_SRC_DIR/consolemodel.cpp \
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#include <QJSValue>
|
||||
#include <QTest>
|
||||
#include "app/models/key-models/newkeyrequest.h"
|
||||
#include "modules/value-editor/abstractkeyfactory.h"
|
||||
#include "modules/value-editor/keymodel.h"
|
||||
|
||||
class FakeKeyModel : public ValueEditor::Model {
|
||||
public:
|
||||
FakeKeyModel() : m_notifier(new ValueEditor::ModelSignals()) {}
|
||||
|
||||
QString getKeyName() override { return QString("fake"); }
|
||||
|
||||
QString getKeyTitle() override { return QString("fake"); }
|
||||
|
||||
QString type() override { return QString("fake"); }
|
||||
|
||||
long long getTTL() override { return -1; }
|
||||
|
||||
QStringList getColumnNames() override { return QStringList() << "value"; }
|
||||
|
||||
QHash<int, QByteArray> getRoles() override {
|
||||
QHash<int, QByteArray> result;
|
||||
result[Qt::UserRole + 1] = "value";
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant getData(int rowIndex, int) override {
|
||||
if (rowIndex != 0) return QVariant();
|
||||
|
||||
return QVariant(QString("fake value"));
|
||||
}
|
||||
|
||||
void setKeyName(const QByteArray &, Callback) override {}
|
||||
|
||||
void setTTL(const long long, Callback) override {}
|
||||
|
||||
void removeKey(Callback) override {}
|
||||
|
||||
void addRow(const QVariantMap &, Callback) override {}
|
||||
|
||||
void updateRow(int, const QVariantMap &, Callback) override {}
|
||||
|
||||
unsigned long rowsCount() override { return 1; }
|
||||
|
||||
void loadRows(QVariant, unsigned long,
|
||||
std::function<void(const QString &, unsigned long)>) override {}
|
||||
|
||||
void clearRowCache() override {}
|
||||
|
||||
void removeRow(int, Callback) override {}
|
||||
|
||||
bool isRowLoaded(int) override { return true; }
|
||||
|
||||
bool isMultiRow() const override { return true; }
|
||||
|
||||
QSharedPointer<ValueEditor::ModelSignals> getConnector() const override {
|
||||
return m_notifier;
|
||||
}
|
||||
|
||||
QSharedPointer<RedisClient::Connection> getConnection() const override {
|
||||
return QSharedPointer<RedisClient::Connection>();
|
||||
}
|
||||
|
||||
unsigned int dbIndex() const override { return 0u; }
|
||||
|
||||
void loadRowsCount(Callback) override {}
|
||||
|
||||
private:
|
||||
QSharedPointer<ValueEditor::ModelSignals> m_notifier;
|
||||
};
|
||||
|
||||
class FakeKeyFactory : public ValueEditor::AbstractKeyFactory {
|
||||
public:
|
||||
void loadKey(
|
||||
QSharedPointer<RedisClient::Connection> connection,
|
||||
QByteArray keyFullPath, int dbIndex,
|
||||
std::function<void(QSharedPointer<ValueEditor::Model>, const QString &)>
|
||||
callback) override {
|
||||
loadKeyCalled++;
|
||||
QVERIFY(connection.isNull() == false);
|
||||
QVERIFY(keyFullPath.isEmpty() == false);
|
||||
QVERIFY(dbIndex >= 0);
|
||||
callback(QSharedPointer<ValueEditor::Model>(new FakeKeyModel()), QString());
|
||||
}
|
||||
|
||||
void submitNewKeyRequest(NewKeyRequest r, QJSValue jsCallback) {
|
||||
submitNewKeyRequestCalled++;
|
||||
}
|
||||
|
||||
uint loadKeyCalled;
|
||||
uint submitNewKeyRequestCalled;
|
||||
};
|
||||
@@ -1,11 +1,8 @@
|
||||
|
||||
VALUEEDITOR_SRC_DIR = $$PWD/../../../../src/modules/value-editor/
|
||||
|
||||
HEADERS += \
|
||||
#$$PWD/*.h \
|
||||
$$PWD/mocks/*.h \
|
||||
$$VALUEEDITOR_SRC_DIR/*.h \
|
||||
HEADERS += \
|
||||
$$files($$VALUEEDITOR_SRC_DIR/*.h) \
|
||||
|
||||
SOURCES += \
|
||||
#$$PWD/*.cpp \
|
||||
$$VALUEEDITOR_SRC_DIR/*.cpp \
|
||||
SOURCES += \
|
||||
$$files($$VALUEEDITOR_SRC_DIR/*.cpp) \
|
||||
|
||||
@@ -3,7 +3,7 @@ QT += core gui network concurrent widgets quick quickwidgets testlib
|
||||
TARGET = tests
|
||||
TEMPLATE = app
|
||||
|
||||
CONFIG += debug c++11
|
||||
CONFIG += debug c++17
|
||||
CONFIG-=app_bundle
|
||||
|
||||
PROJECT_ROOT = $$PWD/../..//
|
||||
@@ -11,22 +11,21 @@ SRC_DIR = $$PROJECT_ROOT/src//
|
||||
|
||||
HEADERS += \
|
||||
$$PROJECT_ROOT/3rdparty/qredisclient/tests/unit_tests/basetestcase.h \
|
||||
$$PROJECT_ROOT/3rdparty/qredisclient/tests/unit_tests/mocks/*.h \
|
||||
$$PROJECT_ROOT/src/modules/common/*.h \
|
||||
$$files($$PROJECT_ROOT/3rdparty/qredisclient/tests/unit_tests/mocks/*.h) \
|
||||
$$files($$PROJECT_ROOT/src/modules/common/*.h) \
|
||||
$$files($$PWD/*.h) \
|
||||
|
||||
SOURCES += \
|
||||
$$PROJECT_ROOT/3rdparty/qredisclient/tests/unit_tests/basetestcase.cpp \
|
||||
$$PROJECT_ROOT/src/modules/common/*.cpp \
|
||||
$$files($$PROJECT_ROOT/3rdparty/qredisclient/tests/unit_tests/mocks/*.cpp) \
|
||||
$$files($$PROJECT_ROOT/src/modules/common/*.cpp) \
|
||||
$$PWD/main.cpp \
|
||||
|
||||
|
||||
#RESOURCES += \
|
||||
# $$SRC_DIR/resources/rdm.qrc
|
||||
|
||||
INCLUDEPATH += $$SRC_DIR/modules/ \
|
||||
$$SRC_DIR/ \
|
||||
$$PWD/ \
|
||||
$$PROJECT_ROOT/3rdparty/qredisclient/tests/unit_tests/
|
||||
$$PROJECT_ROOT/3rdparty/qredisclient/tests/unit_tests/ \
|
||||
$$PROJECT_ROOT/3rdparty/fakeit/single_header/qtest/
|
||||
|
||||
DEFINES += INTEGRATION_TESTS
|
||||
|
||||
@@ -38,20 +37,9 @@ include($$PWD/testcases/value-editor/value-editor-tests.pri)
|
||||
#############
|
||||
include($$PROJECT_ROOT/3rdparty/3rdparty.pri)
|
||||
|
||||
HEADERS += $$PROJECT_ROOT/3rdparty/qt_modeltest/*.h
|
||||
SOURCES += $$PROJECT_ROOT/3rdparty/qt_modeltest/*.cpp
|
||||
INCLUDEPATH += $$PROJECT_ROOT/3rdparty/qt_modeltest/
|
||||
|
||||
release: DESTDIR = $$PROJECT_ROOT/bin/tests
|
||||
debug: DESTDIR = $$PROJECT_ROOT/bin/tests
|
||||
|
||||
unix:!mac {
|
||||
#code coverage
|
||||
QMAKE_CXXFLAGS += -g -fprofile-arcs -ftest-coverage -O0 -Wno-sign-compare
|
||||
QMAKE_LFLAGS += -g -fprofile-arcs -ftest-coverage -O0
|
||||
LIBS += -lgcov
|
||||
}
|
||||
|
||||
UI_DIR = $$DESTDIR/ui
|
||||
OBJECTS_DIR = $$DESTDIR/obj
|
||||
MOC_DIR = $$DESTDIR/obj
|
||||
|
||||
Reference in New Issue
Block a user