Merge branch 'dev' into 'master'

Sprint - Unit Tests sind cool

See merge request link/projekte/ws19/vkvm-new/gui!3
This commit is contained in:
Julian Hinxlage 2020-01-07 15:09:14 +00:00
commit 9d224651c4
16 changed files with 478 additions and 28 deletions

32
.ci/clang-tidy.sh Normal file
View File

@ -0,0 +1,32 @@
#!/bin/sh
echo "Doing clang-tidy..."
bool=false
# explicitly set IFS to contain only a line feed
IFS='
'
filelist="$(find . -not \( -path './*build*' -prune \) -not \( -path './include' -prune \) -not \( -path './lib' -prune \) -type f ! -name "$(printf "*\n*")")"
for file in $filelist; do
if echo "$file" | grep -q -E ".*(\.cpp|\.h|\.hpp)$" ; then
#Extra check missing dependencies due to clang-tidy doesn't toggle exit code.
clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' "$file" -- -I. -std=c++14 2>&1)"
for tidy_line in $clang_tidy_lib_check; do
echo "$tidy_line" | grep -q -v -E "^Error while processing*"
if [ $? -eq 1 ]; then
bool=true
fi
echo "$tidy_line" | grep -q -v -E ".* error: .*"
if [ $? -eq 1 ]; then
bool=true
fi
echo "$tidy_line"
done
fi
done
if $bool; then
exit 1
else
echo "No clang-tidy errors found."
fi
exit 0

2
.clang-tidy Normal file
View File

@ -0,0 +1,2 @@
Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers'
WarningsAsErrors: 'true'

77
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,77 @@
---
image: samueldebruyn/debian-git:latest
stages:
- style
- test
- build
clang_tidy:
image: joethei/clang_tidy
stage: style
tags:
- docker-ci
script:
- mkdir current
- ls -d .[!.]* | grep -v current | xargs mv -t current
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git
- mkdir library/build
- cd library/build
- cmake ..
- make
- cd ../../current/.ci
- sh clang-tidy.sh
make_test:
stage: test
tags:
- docker-ci
script:
- apt-get update
- apt-get install -y g++ make cmake clang-tidy libfltk1.3 libfltk1.3-dev
- mkdir current
- ls | grep -v current | xargs mv -t current
- git clone https://github.com/catchorg/Catch2.git
- cd Catch2
- cmake -Bbuild -H. -DBUILD_TESTING=OFF
- cmake --build build/ --target install
- cd ..
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git
- mkdir library/build
- cd library/build
- cmake ..
- make
- cd ../../current
- mkdir build
- cd build
- cmake ..
- make
- make test
cmake_build:
stage: build
tags:
- docker-ci
script:
- apt-get update
- apt-get install -y g++ make cmake clang-tidy libfltk1.3 libfltk1.3-dev
- mkdir current
- ls | grep -v current | xargs mv -t current
- git clone https://github.com/catchorg/Catch2.git
- cd Catch2
- cmake -Bbuild -H. -DBUILD_TESTING=OFF
- cmake --build build/ --target install
- cd ..
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git
- mkdir library/build
- cd library/build
- cmake ..
- make
- cd ../../current
- mkdir build
- cd build
- cmake ..
- make

View File

@ -8,15 +8,15 @@ if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
endif()
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "bin" "doc" "CMakeFiles" "lib" "include")
project(GUI)
set(CMAKE_CXX_STANDARD 14)
# enable clang_tidy
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*")
set(CMAKE_CXX_CLANG_TIDY clang-tidy;-header-filter=.;-checks=*;)
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;")
set(CMAKE_CXX_CLANG_TIDY clang-tidy;-header-filter=.;)
file(GLOB_RECURSE SOURCES src/*.cpp)
file(GLOB_RECURSE HEADERS src/*.h)
file(GLOB_RECURSE HEADERS src/*.hpp)
file(GLOB_RECURSE TESTS test/*.cpp)
set(LIB_PATH "${CMAKE_SOURCE_DIR}/../library")
@ -26,13 +26,25 @@ add_executable(GUI ${SOURCES} ${HEADERS} main/main.cpp)
target_link_libraries(GUI ${LIB_PATH}/lib/liblibrary.a)
#TODO: add fltk here
set(FLTK_SKIP_FLUID true)
if(FALSE)
include_directories(../fltk-1.3.5/FL)
link_directories(${PROJECT_NAME} ../fltk-1.3.5/lib)
target_link_libraries(${PROJECT_NAME} fltk)
else()
find_package(FLTK REQUIRED)
include_directories(${FLTK_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${FLTK_PLATFORM_DEPENDENT_LIBS} ${FLTK_LIBRARIES} ${OPENGL_LIBRARIES})
endif()
enable_testing()
find_package(Catch2 REQUIRED)
add_executable(UnitTests ${SOURCES} ${HEADERS} ${TESTS})
target_link_libraries(UnitTests Catch2::Catch2)
target_link_libraries(UnitTests ${LIB_PATH}/lib/liblibrary.a)
target_link_libraries(UnitTests ${FLTK_PLATFORM_DEPENDENT_LIBS} ${FLTK_LIBRARIES} ${OPENGL_LIBRARIES})
include(CTest)
include(Catch)
catch_discover_tests(UnitTests)

View File

@ -1,5 +1,7 @@
# vKVM GUI
The GUI is based on the FLTK (Fast Light Toolkit) and creates a window,
which processes incoming signals from the Shared Memory into an visual image.
The image refreshes on each change within the Shared Memory and periodically by itself.
## Installation
Use the installation script provided in the Scripts repository

View File

@ -1,5 +1,10 @@
#include "../src/demo.h"
#include "../src/GUI.hpp"
/** main
* The main function executes the functions of the GUI.
*/
int main(int argc, char **argv) {
GUI_run(argc,argv);
int main() {
return test();
}

64
src/GUI.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "GUI.hpp"
/** GUI_run
* The GUI_run-function starts all functions needed for the GUI.
*/
auto GUI_run(int argc, char **argv) -> int {
vkvm::initialize(0);
int window_height, window_width;
window_height = vkvm::getHeight();
window_width = vkvm::getWidth();
char *resolusion = get_resolusion(window_height, window_width);
std::cout << resolusion << std::endl;
auto *window = new GUI_Window(window_width, window_height + 30, "example");
Statusbar *status[5];
//Dummy-Values TBD
window->begin();
auto *image = new Image(0, 30, window_width, window_height);
status[0] = new Statusbar(0, 0, 300, 30, resolusion);
status[1] = new Statusbar(300, 0, 170, 30, "Event:");
status[2] = new Statusbar(470, 0, 200, 30, "Mouse Position:");
vkvm::registerEvent(vkvm::EventType::Redraw, [image]() {
redraw(image);
});
vkvm::registerEvent(vkvm::EventType::UpdateControlRegisters, [image]() {
image->setDelay(vkvm::getRedrawInterval());
});
Fl::repeat_timeout(image->getDelay(), get_new_image, image);
window->end();
window->show(argc, argv);
return Fl::run();
}
char *get_resolusion(int window_height, int window_width) {
char *resolusion = new char[25];
std::string str_temp;
strcpy(resolusion, "Resolution Height:");
str_temp = std::to_string(window_height);
strcat(resolusion, str_temp.c_str());
strcat(resolusion, " Width:");
str_temp = std::to_string(window_width);
strcat(resolusion, str_temp.c_str());
return resolusion;
}
void redraw(Image *image) {
image->getPixels();
image->redraw();
}
void get_new_image(void *pointer) {
Image *image = ((Image *) pointer);
image->getPixels();
Fl::repeat_timeout(image->getDelay(), refresh_image, pointer);
}
void refresh_image(void *pointer) {
((Image *) pointer)->redraw();
get_new_image(pointer);
}

79
src/GUI.hpp Normal file
View File

@ -0,0 +1,79 @@
#include <iostream>
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Export.H>
#include <FL/Fl_Window.H>
#include <FL/fl_draw.H>
#include <unistd.h>
#include "Mouse_Status.hpp"
#include "vkvm.hpp"
#include "internal.hpp"
#ifndef GUI_GUI_HPP
#define GUI_GUI_HPP
/** GUI_Window
* The GUI_Window-class generates a window, within the window it recognizes the curretn mouse-position.
* It also recognizes if a button is pushed on the keyboard or the mouse. Furthermore the class depict the
* content of the Image-class and provides functions to refresh it.
* @param x The mouse-position on the x-axis.
* @param y The mouse-position on the y-axis.
* @param button The button that was pushed last.
*/
class GUI_Window : public Fl_Window {
int x, y, button,lastX,lastY,mouse_status;
vkvm::KeyCode keyCode;
int handle(int e) override;
static char *position_to_string(int x, int y);
public:
GUI_Window(int x, int y, const char *l);
};
/** The constructor of the image class, get additional
* @param x: The mouse-position on the x-axis.
* @param y: The mouse-position on the y-axis:
* @param w: The width of a single pixel,
* @param h: The height of a single pixel.
*/
class Image : public Fl_Widget {
uchar *buf;
double delay;
public:
Image(int x, int y, int w, int h);
void draw() override;
void getPixels();
void setDelay(double delay);
double getDelay();
};
/** Statusbar
* The class inherits a char *text from the Fl_Box. It also shows the window-resolution and the mouse-position.
* @param text: A pointer to a char-array, that can contain a text like a status or whatever you want.
*/
class Statusbar : public Fl_Box {
char* text;
public:
Statusbar(int x, int y, int w, int h, char *text);
};
char *get_resolusion(int window_height, int window_width);
void refresh_image(void *pointer);
void get_new_image(void *pointer);
void redraw(Image *image);
int GUI_run(int argc, char **argv);
#endif //GUI_GUI_HPP

127
src/GUI_Window.cpp Normal file
View File

@ -0,0 +1,127 @@
#include "GUI.hpp"
/*Function to handle the input*/
auto GUI_Window::handle(int e) -> int {
switch (e) {
/*Mousebutton*/
case FL_PUSH:
x = Fl::event_x();
y = Fl::event_y();
vkvm::setMousePosition(x, y);
if (Fl::event_button() == FL_LEFT_MOUSE) {
mouse_status |= Mouse_Status::left_down;
this->child(2)->label("Event:Mouse Left Down");
vkvm::callEvent(vkvm::EventType::MouseLeftDown);
// std::cout<<mouse_status<<std::endl;
} else if (Fl::event_button() == FL_RIGHT_MOUSE) {
mouse_status |= Mouse_Status::right_down;
this->child(2)->label("Event:Mouse Right Down");
vkvm::callEvent(vkvm::EventType::MouseRightDown);
// std::cout<<mouse_status<<std::endl;
} else {
mouse_status |= Mouse_Status::middle_down;
this->child(2)->label("Event:Mouse Middle Down");
vkvm::callEvent(vkvm::EventType::MouseMiddleDown);
// std::cout<<mouse_status<<std::endl;
}
return 1;
/*Mousebutton and movement*/
case FL_RELEASE:
x = Fl::event_x();
y = Fl::event_y();
vkvm::setMousePosition(x, y);
if (Fl::event_button() == FL_LEFT_MOUSE) {
mouse_status &= Mouse_Status::left_up;
this->child(2)->label("Event:Mouse Left Up");
vkvm::callEvent(vkvm::EventType::MouseLeftUp);
// std::cout<<mouse_status<<std::endl;
} else if (Fl::event_button() == FL_RIGHT_MOUSE) {
mouse_status &= Mouse_Status::right_up;
this->child(2)->label("Event:Mouse Right Up");
vkvm::callEvent(vkvm::EventType::MouseRightUp);
// std::cout<<mouse_status<<std::endl;
} else {
mouse_status &= Mouse_Status::middle_up;
this->child(2)->label("Event:Mouse Middle Up");
vkvm::callEvent(vkvm::EventType::MouseMiddleUp);
// std::cout<<mouse_status<<std::endl;
}
return 1;
case FL_DRAG:
x = Fl::event_x();
y = Fl::event_y();
vkvm::setMousePosition(x, y);
this->child(3)->label(position_to_string(x, y));
switch (mouse_status) {
case Mouse_Status::left_down :
this->child(2)->label("Event:Mouse Left Drag");
vkvm::callEvent(vkvm::EventType::MouseMove);
break;
case Mouse_Status::right_down :
this->child(2)->label("Event:Mouse Right Drag");
vkvm::callEvent(vkvm::EventType::MouseMove);
break;
case Mouse_Status::middle_down :
this->child(2)->label("Event:Mouse Middle Drag");
vkvm::callEvent(vkvm::EventType::MouseMove);
}
return 1;
/*Mousemovement*/
case FL_MOVE:
if (mouse_status == 0) {
x = Fl::event_x();
y = Fl::event_y();
if (lastX != x || lastY != y) {
lastX = x;
lastY = y;
vkvm::setMousePosition(x, y);
vkvm::callEvent(vkvm::EventType::MouseMove);
this->child(2)->label("Event:Mouse Move");
this->child(3)->label(position_to_string(x, y));
}
} else {
handle(FL_DRAG);
}
return 1;
/*keyboardbutton*/
case FL_KEYBOARD:
button = Fl::event_button();
keyCode = vkvm::KeyCode(button);
vkvm::buttonPressed(keyCode);
vkvm::callEvent(vkvm::EventType::KeyDown);
this->child(2)->label("Event:Key Down");
return 1;
case FL_KEYUP:
button = Fl::event_button();
std::cout << button << std::endl;
keyCode = vkvm::KeyCode(button);
vkvm::buttonPressed(keyCode);
vkvm::callEvent(vkvm::EventType::KeyUp);
this->child(2)->label("Event:Key Up");
return 1;
}
return -1;
}
GUI_Window::GUI_Window(int x, int y, const char *l) : Fl_Window(x, y, l) {
lastX = 0;
lastY = 0;
mouse_status = 0;
}
auto GUI_Window::position_to_string(int x, int y) -> char * {
auto *str = new char[25];
std::string str_temp;
str = strcpy(str, "Mouse Position X:");
str_temp = std::to_string(x);
str = strcat(str, str_temp.c_str());
str = strcat(str, " Y:");
str_temp = std::to_string(y);
str = strcat(str, str_temp.c_str());
return str;
}

37
src/Image.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "GUI.hpp"
/** Image
* The Image-class draws the bitmap that it get from the Shared Memory.
* @param *buf: A pointer to the bitmap, that the image-class has to draw. Three chars are needed to get the RGB-value of a pixel, so the size equals window_height * window_width * 3.
*/
//Function to draw a bitmap
auto Image::draw() -> void {
fl_draw_image(buf, x(), y(), w(), h());
}
Image::Image(int x, int y, int w, int h) :
Fl_Widget(x, y, w, h, nullptr) {
buf = new uchar[w * h * 3];
delay = ((double)vkvm::getRedrawInterval())/1000;
}
/*A function to change the colors of the image-class. It reads the colors from the Shared Memory-Class*/
auto Image::getPixels() -> void {
for (int i = 0; i < h(); i++) {
for (int j = 0; j < w(); j++) {
vkvm::Color c = vkvm::getPixel(j, i);
buf[(i * w() + j) * 3 + 0] = c.getRed();
buf[(i * w() + j) * 3 + 1] = c.getGreen();
buf[(i * w() + j) * 3 + 2] = c.getBlue();
}
}
}
auto Image::getDelay() -> double {
return delay;
}
auto Image::setDelay(double delay) -> void {
this->delay = delay;
}

12
src/Mouse_Status.hpp Normal file
View File

@ -0,0 +1,12 @@
enum Mouse_Status {
left_down = 0b100,
right_down = 0b010,
middle_down = 0b001,
left_up = 0b011,
right_up = 0b101,
middle_up = 0b110,
};

14
src/Statusbar.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "GUI.hpp"
/** The constructor of Statusbar has to get additional parameters.
* @param x: The mouse-position on the x-axis.
* @param y: The mouse-position on the y-axis:
* @param w: The width of a single pixel,
* @param h: The height of a single pixel.
*/
Statusbar::Statusbar(int x, int y, int w, int h, char *text) :
Fl_Box(x, y, w, h, text) {
this->text = text;
};

View File

@ -1,5 +0,0 @@
#include "demo.h"
int test() {
return 42;
}

View File

@ -1,8 +0,0 @@
#ifndef SHARED_MEMORY_DEMO_H
#define SHARED_MEMORY_DEMO_H
int test();
#endif //SHARED_MEMORY_DEMO_H

6
test/test_GUI.cpp Normal file
View File

@ -0,0 +1,6 @@
#include <catch2/catch.hpp>
#include "../src/GUI.hpp"
TEST_CASE("GUI Test") {
REQUIRE(42 == 42);
}

View File

@ -1,6 +0,0 @@
#include <catch2/catch.hpp>
#include "../src/demo.h"
TEST_CASE("Demo test") {
REQUIRE(test() == 42);
}