summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt10
-rw-r--r--inc/fact.h6
-rw-r--r--inc/logger.h25
-rw-r--r--src/fact/fact.cc7
-rw-r--r--src/logger/logger.cc79
-rw-r--r--src/main.cc56
-rw-r--r--src/repl/repl.py10
-rw-r--r--src/rv.cc33
-rw-r--r--tests/logger.cc65
-rw-r--r--tests/tests.cc10
11 files changed, 232 insertions, 70 deletions
diff --git a/.gitignore b/.gitignore
index c8346bd..728f14e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@
# generated
__pycache__
/build/
+*.log
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e36b290..17ec29f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,20 +16,22 @@ include_directories(
# gather source files
file(GLOB_RECURSE SRCS "src/*.cc")
-list(REMOVE_ITEM SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/rv.cc")
+list(REMOVE_ITEM SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc")
# find python3 components
find_package(Python3 COMPONENTS Development REQUIRED)
# binary executable
-add_executable(${PROJECT_NAME} ${SRCS} src/rv.cc)
+add_executable(${PROJECT_NAME} ${SRCS} src/main.cc)
target_link_libraries(${PROJECT_NAME} PRIVATE Python3::Python)
find_package(Catch2 REQUIRED)
-set(TESTDIR tests)
+
+#gather test files
+file(GLOB_RECURSE TESTS "tests/*.cc")
# test executable
-add_executable(tests ${SRCS} ${TESTDIR}/tests.cc)
+add_executable(tests ${SRCS} ${TESTS})
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain PRIVATE Python3::Python)
# test discovery
diff --git a/inc/fact.h b/inc/fact.h
deleted file mode 100644
index de1220a..0000000
--- a/inc/fact.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef FACT_H
-#define FACT_H
-
-unsigned int factorial(unsigned int);
-
-#endif
diff --git a/inc/logger.h b/inc/logger.h
new file mode 100644
index 0000000..5ecdc7e
--- /dev/null
+++ b/inc/logger.h
@@ -0,0 +1,25 @@
+#ifndef LOGGER_H
+#define LOGGER_H
+#include <fstream>
+#include <sstream>
+using namespace std;
+
+enum LogLevel { DEBUG, INFO, WARNING, ERROR, CRITICAL };
+
+class Logger
+{
+ public:
+ Logger(const string &);
+ ~Logger();
+
+ void setLevel(LogLevel);
+ void log(LogLevel, const string &);
+
+ private:
+ LogLevel level = INFO;
+ ofstream logFile;
+ string levelToString(LogLevel);
+ int levelToInt(LogLevel);
+};
+
+#endif /* LOGGER_H_INCLUDED */
diff --git a/src/fact/fact.cc b/src/fact/fact.cc
deleted file mode 100644
index 026ad94..0000000
--- a/src/fact/fact.cc
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "fact.h"
-
-unsigned int
-factorial(unsigned int number)
-{
- return number <= 1 ? number : factorial(number-1)*number;
-}
diff --git a/src/logger/logger.cc b/src/logger/logger.cc
new file mode 100644
index 0000000..fb5052a
--- /dev/null
+++ b/src/logger/logger.cc
@@ -0,0 +1,79 @@
+#include "logger.h"
+#include <ctime>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+using namespace std;
+
+Logger::Logger(const string &filename)
+{
+ if (!filename.empty()) {
+ logFile.open(filename, ios::app);
+ if (!logFile.is_open()) {
+ cerr << "Error opening log file." << endl;
+ }
+ }
+}
+
+Logger::~Logger() { logFile.close(); }
+
+void Logger::setLevel(LogLevel level) { this->level = level; }
+
+void Logger::log(LogLevel level, const string &message)
+{
+ if (levelToInt(level) > levelToInt(this->level)) {
+ return;
+ }
+
+ time_t now = time(0);
+ tm *timeinfo = localtime(&now);
+ char timestamp[20];
+ strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeinfo);
+
+ ostringstream logEntry;
+ logEntry << "[" << timestamp << "] " << levelToString(level) << ": "
+ << message << endl;
+
+ cout << logEntry.str();
+
+ if (logFile.is_open()) {
+ logFile << logEntry.str();
+ logFile.flush();
+ }
+}
+
+string Logger::levelToString(LogLevel level)
+{
+ switch (level) {
+ case DEBUG:
+ return "DEBUG";
+ case INFO:
+ return "INFO";
+ case WARNING:
+ return "WARNING";
+ case ERROR:
+ return "ERROR";
+ case CRITICAL:
+ return "CRITICAL";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int Logger::levelToInt(LogLevel level)
+{
+ switch (level) {
+ case DEBUG:
+ return 5;
+ case INFO:
+ return 4;
+ case WARNING:
+ return 3;
+ case ERROR:
+ return 2;
+ case CRITICAL:
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/src/main.cc b/src/main.cc
new file mode 100644
index 0000000..6871fb9
--- /dev/null
+++ b/src/main.cc
@@ -0,0 +1,56 @@
+#include "logger.h"
+#include <getopt.h>
+#include <iostream>
+
+void err()
+{
+ std::cerr << "Usage:\n\trisc_vector [OPTIONS]\nOptions:\n\t--debug,\t-d: "
+ "turn on verbose output\n\t--no-python,\t-p: run without GUI\n"
+ << std::endl;
+}
+
+void parseArguments(int argc, char **argv, Logger &logger, bool &python)
+{
+ struct option long_options[] = {
+ {"debug", no_argument, 0, 'd'},
+ {"no-python", no_argument, 0, 'p'},
+ {0, 0, 0, 0}};
+
+ python = true;
+
+ int opt;
+
+ while ((opt = getopt_long(argc, argv, "d:p", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'd':
+ logger.setLevel(DEBUG);
+ logger.log(DEBUG, "DEBUG output enabled.");
+ break;
+ case 'p':
+ logger.log(INFO, "Python will NOT be started!");
+ python = false;
+ break;
+ default:
+ err();
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+
+ Logger logger("vector.log");
+ logger.log(INFO, "Initializing...");
+
+ bool python = true;
+ parseArguments(argc, argv, logger, python);
+
+ if (python) {
+ // fork off python here
+ ;
+ logger.log(INFO, "Python started.");
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/repl/repl.py b/src/repl/repl.py
deleted file mode 100644
index d78986d..0000000
--- a/src/repl/repl.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from code import InteractiveConsole
-
-def start(user):
- header =f"Press C-d to close."
- footer = f"See you later, {user}!"
-
- scope_vars = {"cache_size": 12}
-
- InteractiveConsole(locals=scope_vars).interact(header, "")
- return footer
diff --git a/src/rv.cc b/src/rv.cc
deleted file mode 100644
index 02d95e2..0000000
--- a/src/rv.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <Python.h>
-#include <iostream>
-
-int main() {
- Py_Initialize();
- PyRun_SimpleString("import sys; sys.path.append('src/')");
- PyObject *pName = PyUnicode_DecodeFSDefault("repl.repl");
- PyObject *pModule = PyImport_Import(pName);
- Py_DECREF(pName);
-
- if (pModule != nullptr) {
- PyObject *pFunc = PyObject_GetAttrString(pModule, "start");
- if (pFunc && PyCallable_Check(pFunc)) {
- PyObject *pArgs = PyTuple_Pack(1, PyUnicode_FromString("World"));
- PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
- Py_DECREF(pArgs);
- if (pValue != nullptr) {
- std::cout << PyUnicode_AsUTF8(pValue) << std::endl;
- Py_DECREF(pValue);
- } else {
- PyErr_Print();
- std::cerr << "Call failed" << std::endl;
- }
- Py_DECREF(pFunc);
- }
- Py_DECREF(pModule);
- } else {
- PyErr_Print();
- std::cerr << "Failed to load \"hello\"" << std::endl;
- }
- Py_Finalize();
- return 0;
-}
diff --git a/tests/logger.cc b/tests/logger.cc
new file mode 100644
index 0000000..18e4fab
--- /dev/null
+++ b/tests/logger.cc
@@ -0,0 +1,65 @@
+#include "logger.h"
+#include <catch2/catch_test_macros.hpp>
+#include <iostream>
+#include <regex>
+#include <sstream>
+
+TEST_CASE("Logger logs higher log level")
+{
+ std::streambuf *coutBuffer = std::cout.rdbuf();
+ std::ostringstream oss;
+ std::cout.rdbuf(oss.rdbuf());
+
+ Logger logger("");
+ logger.setLevel(INFO);
+
+ logger.log(ERROR, "foo bar baz qux");
+
+ std::cout.rdbuf(coutBuffer);
+
+ std::string actual = oss.str();
+ std::regex expected(
+ "\\[\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\] ERROR: "
+ "foo bar baz qux\\n");
+
+ REQUIRE(std::regex_match(actual, expected));
+}
+
+TEST_CASE("Logger logs equal log level")
+{
+ std::streambuf *coutBuffer = std::cout.rdbuf();
+ std::ostringstream oss;
+ std::cout.rdbuf(oss.rdbuf());
+
+ Logger logger("");
+ logger.setLevel(INFO);
+
+ logger.log(INFO, "foo bar baz qux");
+
+ std::cout.rdbuf(coutBuffer);
+
+ std::string actual = oss.str();
+ std::regex expected("\\[\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\] INFO: "
+ "foo bar baz qux\\n");
+
+ REQUIRE(std::regex_match(actual, expected));
+}
+
+TEST_CASE("Logger ignores lower log level")
+{
+ std::streambuf *coutBuffer = std::cout.rdbuf();
+ std::ostringstream oss;
+ std::cout.rdbuf(oss.rdbuf());
+
+ Logger logger("");
+ logger.setLevel(INFO);
+
+ logger.log(DEBUG, "foo bar baz qux");
+
+ std::cout.rdbuf(coutBuffer);
+
+ std::string actual = oss.str();
+ std::string expected("");
+
+ REQUIRE(actual == expected);
+}
diff --git a/tests/tests.cc b/tests/tests.cc
index 8a23c4d..7817006 100644
--- a/tests/tests.cc
+++ b/tests/tests.cc
@@ -1,11 +1 @@
#define CATCH_CONFIG_MAIN
-#include "fact.h"
-#include<catch2/catch_test_macros.hpp>
-
-TEST_CASE( "factorials are computed", "[factorial]")
-{
- REQUIRE( factorial(1) == 1 );
- REQUIRE( factorial(2) == 2 );
- REQUIRE( factorial(3) == 6 );
- REQUIRE( factorial(10) == 3628800 );
-}