Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Test Suite #1345

Draft
wants to merge 17 commits into
base: dev
Choose a base branch
from
2 changes: 2 additions & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ build_script:
-DCUTTER_PACKAGE_JSDEC=ON
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON
-DCUTTER_ENABLE_CRASH_REPORTS=ON
-DCUTTER_ENABLE_TESTS=ON
-DCMAKE_PREFIX_PATH=%CUTTER_DEPS%\\pyside
-DCPACK_PACKAGE_FILE_NAME=%PACKAGE_NAME%
-G Ninja
.."
- cmd: cmake --build . --config Release
- cmd: cmake --build . --config Release --target package
- cmd: src/test/CutterTest

# Tests
test: off
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/ccpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ jobs:
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON \
-DCUTTER_ENABLE_GRAPHVIZ=OFF \
-DCUTTER_ENABLE_CRASH_REPORTS=ON \
-DCUTTER_ENABLE_TESTS=ON \
-DCUTTER_USE_BUNDLED_RIZIN=ON \
-DCUTTER_APPIMAGE_BUILD=ON \
-DCUTTER_ENABLE_PACKAGING=ON \
Expand All @@ -131,9 +132,12 @@ jobs:
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCUTTER_USE_BUNDLED_RIZIN=ON \
-DCUTTER_ENABLE_TESTS=ON \
..
fi
ninja
export QT_QPA_PLATFORM=minimal
./test/CutterTest
if [[ "${{ matrix.package || false }}" = "true" ]]
then
export CUTTER_VERSION=$(python ../scripts/get_version.py)
Expand Down Expand Up @@ -185,6 +189,7 @@ jobs:
-DCUTTER_ENABLE_CRASH_REPORTS=ON \
-DCUTTER_USE_BUNDLED_RIZIN=ON \
-DCUTTER_ENABLE_PACKAGING=ON \
-DCUTTER_ENABLE_TESTS=ON \
-DCUTTER_PACKAGE_DEPENDENCIES=ON \
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON \
-DCUTTER_PACKAGE_RZ_GHIDRA=ON \
Expand All @@ -198,7 +203,8 @@ jobs:
make package
export CUTTER_VERSION=$(python3 ../scripts/get_version.py)
echo PACKAGE_NAME=${PACKAGE_NAME}.dmg >> $GITHUB_ENV
echo UPLOAD_ASSET_TYPE=application/x-apple-diskimage >> $GITHUB_ENV
echo UPLOAD_ASSET_TYPE=application/x-apple-diskimage >> $GITHUB_ENVV
./test/CutterTest;
- name: windows dependencies
if: contains(matrix.os, 'windows')
shell: bash
Expand All @@ -222,6 +228,7 @@ jobs:
cmake ^
-DCMAKE_BUILD_TYPE=Release ^
-DCUTTER_USE_BUNDLED_RIZIN=ON ^
-DCUTTER_ENABLE_TESTS=ON ^
-DCUTTER_ENABLE_PYTHON=ON ^
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON ^
-DCUTTER_ENABLE_PACKAGING=ON ^
Expand All @@ -237,6 +244,7 @@ jobs:
..
cmake --build . --config Release
cmake --build . --config Release --target package
cd test; CutterTest
echo PACKAGE_NAME=%PACKAGE_NAME%.zip >> %GITHUB_ENV%
echo UPLOAD_ASSET_TYPE=application/zip >> %GITHUB_ENV%
- uses: actions/upload-artifact@v2
Expand Down
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ option(CUTTER_PACKAGE_DEPENDENCIES "During install step include the third party
option(CUTTER_PACKAGE_RZ_GHIDRA "Compile and install rz-ghidra during install step." OFF)
option(CUTTER_PACKAGE_RZ_LIBSWIFT, "Compile and install rz-libswift demangler during the install step." OFF)
option(CUTTER_PACKAGE_JSDEC "Compile and install jsdec during install step." OFF)
option(CUTTER_ENABLE_TESTS "Build QtTest tests" OFF)
OPTION(CUTTER_QT6 "Use QT6" OFF)

if(NOT CUTTER_ENABLE_PYTHON)
Expand Down Expand Up @@ -135,3 +136,7 @@ add_subdirectory(src)
if(CUTTER_ENABLE_PACKAGING)
add_subdirectory(dist)
endif()

if(CUTTER_ENABLE_TESTS)
add_subdirectory(test)
endif()
41 changes: 24 additions & 17 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
set_source_files_properties(${BINDINGS_SOURCE} PROPERTIES COMPILE_FLAGS -w)
endif()


add_executable(Cutter ${OPTIONS} ${UI_FILES} ${QRC_FILES} ${PLATFORM_RESOURCES} ${SOURCES} ${HEADER_FILES} ${BINDINGS_SOURCE})
list(REMOVE_ITEM SOURCES Main.cpp)
add_library(CutterLib STATIC ${UI_FILES} ${QRC_FILES} ${PLATFORM_RESOURCES} ${SOURCES} ${HEADER_FILES} ${BINDINGS_SOURCE})
add_executable(Cutter ${OPTIONS} Main.cpp)
set_target_properties(Cutter PROPERTIES
OUTPUT_NAME cutter
RUNTIME_OUTPUT_DIRECTORY ..
Expand All @@ -458,33 +459,39 @@ foreach(_dir ${CUTTER_INCLUDE_DIRECTORIES})
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${_dir}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cutter/${_dir}>
)
target_include_directories(CutterLib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${_dir}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cutter/${_dir}>
)
endforeach()
target_link_libraries(Cutter CutterLib)

if (TARGET Graphviz::GVC)
target_link_libraries(Cutter PRIVATE Graphviz::GVC)
target_compile_definitions(Cutter PRIVATE CUTTER_ENABLE_GRAPHVIZ)
target_link_libraries(CutterLib PRIVATE Graphviz::GVC)
target_compile_definitions(CutterLib PRIVATE CUTTER_ENABLE_GRAPHVIZ)
endif()

if(CUTTER_ENABLE_CRASH_REPORTS)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(Cutter PRIVATE Threads::Threads)
target_link_libraries(CutterLib PRIVATE Threads::Threads)

add_definitions(-DCUTTER_ENABLE_CRASH_REPORTS)
if (NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")
endif()
find_package(Breakpad REQUIRED)
target_link_libraries(Cutter PRIVATE Breakpad::client)
target_link_libraries(CutterLib PRIVATE Breakpad::client)
endif()

target_link_libraries(Cutter PUBLIC ${QT_PREFIX}::Core ${QT_PREFIX}::Widgets ${QT_PREFIX}::Gui PRIVATE ${QT_PREFIX}::Svg ${QT_PREFIX}::Network)
target_link_libraries(CutterLib PUBLIC ${QT_PREFIX}::Core ${QT_PREFIX}::Widgets ${QT_PREFIX}::Gui PRIVATE ${QT_PREFIX}::Svg ${QT_PREFIX}::Network)
if (CUTTER_QT6)
target_link_libraries(Cutter PUBLIC Qt6::Core5Compat Qt6::SvgWidgets)
target_link_libraries(Cutter PRIVATE Qt6::OpenGLWidgets)
target_link_libraries(CutterLib PUBLIC Qt6::Core5Compat Qt6::SvgWidgets)
target_link_libraries(CutterLib PRIVATE Qt6::OpenGLWidgets)
endif()

target_link_libraries(Cutter PUBLIC ${RIZIN_TARGET})
target_link_libraries(CutterLib PUBLIC ${RIZIN_TARGET})

if(CUTTER_ENABLE_PYTHON)
if (WIN32)
# On windows some of the Python STABLE API functions are in seperate library
Expand All @@ -494,15 +501,15 @@ if(CUTTER_ENABLE_PYTHON)
if((NOT _PYTHON_LIBRARY STREQUAL "optimized") AND (NOT _PYTHON_LIBRARY STREQUAL "debug"))
get_filename_component(_PYTHON_LIB_DIR ${_PYTHON_LIBRARY} DIRECTORY)
message(STATUS "Add extra library dir for Python: ${_PYTHON_LIB_DIR}")
target_link_directories(Cutter PRIVATE ${_PYTHON_LIB_DIR})
target_link_directories(CutterLib PRIVATE ${_PYTHON_LIB_DIR})
endif()
endforeach()
endif()
target_link_libraries(Cutter PRIVATE ${PYTHON_LIBRARIES})
target_link_libraries(CutterLib PRIVATE ${PYTHON_LIBRARIES})
if(CUTTER_ENABLE_PYTHON_BINDINGS)
target_link_libraries(Cutter PRIVATE Shiboken2::libshiboken PySide2::pyside2)
target_link_libraries(CutterLib PRIVATE Shiboken2::libshiboken PySide2::pyside2)

get_target_property(RAW_BINDINGS_INCLUDE_DIRS Cutter INCLUDE_DIRECTORIES)
get_target_property(RAW_BINDINGS_INCLUDE_DIRS CutterLib INCLUDE_DIRECTORIES)
if(NOT CUTTER_USE_BUNDLED_RIZIN)
get_target_property(RAW_RIZIN_INCLUDE_DIRS ${RIZIN_TARGET} INTERFACE_INCLUDE_DIRECTORIES)
list(APPEND RAW_BINDINGS_INCLUDE_DIRS "${RAW_RIZIN_INCLUDE_DIRS}")
Expand Down Expand Up @@ -535,8 +542,8 @@ if(CUTTER_ENABLE_PYTHON)
endif()

if(TARGET KF5::SyntaxHighlighting)
target_link_libraries(Cutter PRIVATE KF5::SyntaxHighlighting)
target_compile_definitions(Cutter PRIVATE CUTTER_ENABLE_KSYNTAXHIGHLIGHTING)
target_link_libraries(CutterLib PRIVATE KF5::SyntaxHighlighting)
target_compile_definitions(CutterLib PRIVATE CUTTER_ENABLE_KSYNTAXHIGHLIGHTING)
endif()

if (CUTTER_APPIMAGE_BUILD)
Expand All @@ -558,7 +565,7 @@ endif()
include(Translations)

# Install files
install(TARGETS Cutter
install(TARGETS Cutter CutterLib
EXPORT CutterTargets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
BUNDLE DESTINATION "." # needs to be tested
Expand Down
8 changes: 4 additions & 4 deletions src/CutterApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#define CUTTER_COMPILE_TIME_RZ_VERSION "" RZ_VERSION
#endif

CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc, argv)
CutterApplication::CutterApplication(int &argc, char **argv, bool test) : QApplication(argc, argv)
{
// Setup application information
setApplicationVersion(CUTTER_VERSION_FULL);
Expand Down Expand Up @@ -135,23 +135,23 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
plugin->registerDecompilers();
}

mainWindow = new MainWindow();
mainWindow = new MainWindow(nullptr, test);
installEventFilter(mainWindow);

// set up context menu shortcut display fix
#if QT_VERSION_CHECK(5, 10, 0) < QT_VERSION
setStyle(new CutterProxyStyle());
#endif // QT_VERSION_CHECK(5, 10, 0) < QT_VERSION

if (clOptions.args.empty() && clOptions.fileOpenOptions.projectFile.isEmpty()) {
if (clOptions.args.empty() && clOptions.fileOpenOptions.projectFile.isEmpty() && !test) {
// check if this is the first execution of Cutter in this computer
// Note: the execution after the preferences been reset, will be considered as
// first-execution
if (Config()->isFirstExecution()) {
mainWindow->displayWelcomeDialog();
}
mainWindow->displayNewFileDialog();
} else { // filename specified as positional argument
} else if (!test) { // filename specified as positional argument
bool askOptions = (clOptions.analysisLevel != AutomaticAnalysisLevel::Ask)
|| !clOptions.fileOpenOptions.projectFile.isEmpty();
mainWindow->openNewFile(clOptions.fileOpenOptions, askOptions);
Expand Down
2 changes: 1 addition & 1 deletion src/CutterApplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class CutterApplication : public QApplication
Q_OBJECT

public:
CutterApplication(int &argc, char **argv);
CutterApplication(int &argc, char **argv, bool test = false);
~CutterApplication();

MainWindow *getMainWindow() { return mainWindow; }
Expand Down
10 changes: 8 additions & 2 deletions src/core/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,18 @@ T *getNewInstance(MainWindow *m)

using namespace Cutter;

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), core(Core()), ui(new Ui::MainWindow)
MainWindow::MainWindow(QWidget *parent, bool testMode) :
QMainWindow(parent),
core(Core()),
testMode(testMode),
ui(new Ui::MainWindow)
{
tabsOnTop = false;
configuration = Config();

initUI();
if (!testMode) {
initUI();
}
}

MainWindow::~MainWindow() {}
Expand Down
4 changes: 3 additions & 1 deletion src/core/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class CUTTER_EXPORT MainWindow : public QMainWindow
public:
bool responsive;

explicit MainWindow(QWidget *parent = nullptr);
explicit MainWindow(QWidget *parent = nullptr, bool testMode = false);
~MainWindow() override;

void openNewFile(InitialOptions &options, bool skipOptionsDialog = false);
Expand Down Expand Up @@ -213,6 +213,8 @@ private slots:
private:
CutterCore *core;

bool testMode;

bool tabsOnTop;
ut64 hexdumpTopOffset;
ut64 hexdumpBottomOffset;
Expand Down
73 changes: 73 additions & 0 deletions test/AutoTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

#ifndef AUTOTEST_H
#define AUTOTEST_H

// see http://qtcreator.blogspot.de/2009/10/running-multiple-unit-tests.html

#include <QTest>
#include <QList>
#include <QString>
#include <QSharedPointer>

namespace AutoTest
{
typedef QList<QObject *> TestList;

inline TestList &testList()
{
static TestList list;
return list;
}

inline bool findObject(QObject *object)
{
TestList &list = testList();
if (list.contains(object)) {
return true;
}

for (QObject *test : list) {
if (test->objectName() == object->objectName()) {
return true;
}
}
return false;
}

inline void addTest(QObject *object)
{
TestList &list = testList();
if (!findObject(object)) {
list.append(object);
}
}

inline int run(int argc, char *argv[])
{
int ret = 0;

for (QObject *test : testList()) {
ret += QTest::qExec(test, argc, argv);
}

return ret;
}
}

template<class T>
class Test
{
public:
QSharedPointer<T> child;

explicit Test(const QString &name)
: child(new T)
{
child->setObjectName(name);
AutoTest::addTest(child.data());
}
};

#define DECLARE_TEST(className) static Test<className> t(#className);

#endif //AUTOTEST_H
13 changes: 13 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
find_package(Qt5 REQUIRED COMPONENTS Test)

set(TEST_HEADER_FILES
AutoTest.h
CutterTest.h)

set(TEST_SOURCE_FILES
main.cpp
CutterTest.cpp
TestHexdumpWidget.cpp)

add_executable(CutterTest ${TEST_SOURCE_FILES} ${TEST_HEADER_FILES})
target_link_libraries(CutterTest CutterLib Qt5::Test)
13 changes: 13 additions & 0 deletions test/CutterTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

#include "CutterTest.h"

void CutterTest::initTestCase()
{
qDebug("CutterTest::initTestCase()");
}

void CutterTest::cleanupTestCase()
{
qDebug("CutterTest::cleanupTestCase()");
}

16 changes: 16 additions & 0 deletions test/CutterTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

#ifndef CUTTERTEST_H
#define CUTTERTEST_H

#include <QObject>

class CutterTest: public QObject
{
Q_OBJECT

protected slots:
virtual void initTestCase();
virtual void cleanupTestCase();
};

#endif //CUTTERTEST_H
Loading