From 1214a7f76d5927281954fb173e3b293253e31821 Mon Sep 17 00:00:00 2001 From: Denactive Date: Tue, 16 Mar 2021 19:04:41 +0300 Subject: [PATCH 01/11] 84% coverage --- .travis.yml | 51 ++++ CMakeLists.txt | 24 ++ project/include/hw-1.h | 47 ++++ project/src/hw-1.c | 263 ++++++++++++++++++ project/src/program.c | 12 + testing/Testing/Temporary/CTestCostData.txt | 1 + testing/Testing/Temporary/LastTest.log | 3 + testing/ci-install-linux.sh | 25 ++ testing/ci-install-osx.sh | 0 testing/console_input/answers/1.txt | 1 + testing/console_input/answers/2.txt | 3 + testing/console_input/answers/3.txt | 26 ++ testing/console_input/answers/4.txt | 49 ++++ testing/console_input/cases/1.txt | 1 + testing/console_input/cases/2.txt | 3 + testing/console_input/cases/3.txt | 26 ++ testing/console_input/cases/4.txt | 49 ++++ testing/logic/answers/1.txt | 4 + testing/logic/answers/10.txt | 5 + testing/logic/answers/11.txt | 28 ++ testing/logic/answers/12.txt | 16 ++ testing/logic/answers/13.txt | 25 ++ testing/logic/answers/14.txt | 1 + testing/logic/answers/15.txt | 20 ++ testing/logic/answers/16.txt | 1 + testing/logic/answers/17.txt | 136 +++++++++ testing/logic/answers/2.txt | 3 + testing/logic/answers/3.txt | 4 + testing/logic/answers/4.txt | 6 + testing/logic/answers/5.txt | 5 + testing/logic/answers/6.txt | 10 + testing/logic/answers/7.txt | 4 + testing/logic/answers/8.txt | 4 + testing/logic/answers/9.txt | 4 + testing/logic/cases/1.txt | 1 + testing/logic/cases/10.txt | 2 + testing/logic/cases/11.txt | 24 ++ testing/logic/cases/12.txt | 9 + testing/logic/cases/13.txt | 32 +++ testing/logic/cases/14.txt | 6 + testing/logic/cases/15.txt | 17 ++ testing/logic/cases/16.txt | 1 + testing/logic/cases/17.txt | 45 +++ testing/logic/cases/2.txt | 1 + testing/logic/cases/3.txt | 1 + testing/logic/cases/4.txt | 3 + testing/logic/cases/5.txt | 2 + testing/logic/cases/6.txt | 2 + testing/logic/cases/7.txt | 2 + testing/logic/cases/8.txt | 7 + testing/logic/cases/9.txt | 2 + testing/openfile/answers/1.txt | 1 + testing/openfile/answers/2.txt | 3 + testing/openfile/answers/3.txt | 26 ++ testing/openfile/answers/4.txt | 49 ++++ testing/openfile/cases/1.txt | 1 + testing/openfile/cases/2.txt | 3 + testing/openfile/cases/3.txt | 26 ++ testing/openfile/cases/4.txt | 49 ++++ testing/tests.cpp | 186 +++++++++++++ ...1\200\321\213\321\202\320\270\320\265.png" | Bin 0 -> 40162 bytes 61 files changed, 1361 insertions(+) create mode 100644 .travis.yml create mode 100644 CMakeLists.txt create mode 100644 project/include/hw-1.h create mode 100644 project/src/hw-1.c create mode 100644 project/src/program.c create mode 100644 testing/Testing/Temporary/CTestCostData.txt create mode 100644 testing/Testing/Temporary/LastTest.log create mode 100644 testing/ci-install-linux.sh create mode 100644 testing/ci-install-osx.sh create mode 100644 testing/console_input/answers/1.txt create mode 100644 testing/console_input/answers/2.txt create mode 100644 testing/console_input/answers/3.txt create mode 100644 testing/console_input/answers/4.txt create mode 100644 testing/console_input/cases/1.txt create mode 100644 testing/console_input/cases/2.txt create mode 100644 testing/console_input/cases/3.txt create mode 100644 testing/console_input/cases/4.txt create mode 100644 testing/logic/answers/1.txt create mode 100644 testing/logic/answers/10.txt create mode 100644 testing/logic/answers/11.txt create mode 100644 testing/logic/answers/12.txt create mode 100644 testing/logic/answers/13.txt create mode 100644 testing/logic/answers/14.txt create mode 100644 testing/logic/answers/15.txt create mode 100644 testing/logic/answers/16.txt create mode 100644 testing/logic/answers/17.txt create mode 100644 testing/logic/answers/2.txt create mode 100644 testing/logic/answers/3.txt create mode 100644 testing/logic/answers/4.txt create mode 100644 testing/logic/answers/5.txt create mode 100644 testing/logic/answers/6.txt create mode 100644 testing/logic/answers/7.txt create mode 100644 testing/logic/answers/8.txt create mode 100644 testing/logic/answers/9.txt create mode 100644 testing/logic/cases/1.txt create mode 100644 testing/logic/cases/10.txt create mode 100644 testing/logic/cases/11.txt create mode 100644 testing/logic/cases/12.txt create mode 100644 testing/logic/cases/13.txt create mode 100644 testing/logic/cases/14.txt create mode 100644 testing/logic/cases/15.txt create mode 100644 testing/logic/cases/16.txt create mode 100644 testing/logic/cases/17.txt create mode 100644 testing/logic/cases/2.txt create mode 100644 testing/logic/cases/3.txt create mode 100644 testing/logic/cases/4.txt create mode 100644 testing/logic/cases/5.txt create mode 100644 testing/logic/cases/6.txt create mode 100644 testing/logic/cases/7.txt create mode 100644 testing/logic/cases/8.txt create mode 100644 testing/logic/cases/9.txt create mode 100644 testing/openfile/answers/1.txt create mode 100644 testing/openfile/answers/2.txt create mode 100644 testing/openfile/answers/3.txt create mode 100644 testing/openfile/answers/4.txt create mode 100644 testing/openfile/cases/1.txt create mode 100644 testing/openfile/cases/2.txt create mode 100644 testing/openfile/cases/3.txt create mode 100644 testing/openfile/cases/4.txt create mode 100644 testing/tests.cpp create mode 100644 "\320\277\320\276\320\272\321\200\321\213\321\202\320\270\320\265.png" diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..899c1ab --- /dev/null +++ b/.travis.yml @@ -0,0 +1,51 @@ +#Лучший гайд: https://habr.com/ru/post/329264/ + +dist: focal # используем Ubuntu 20.04 Focal Fossa +sudo: required # используем Virtual Machine (а не Docker container) + +language: c # на практике разницы между специфичным для C++ окружением + # и, скажем, python -- никакой. Но пусть будет cpp. + +os: + # будем прогонять CI и на Linux, и на Mac OS X... + - linux + #- osx + +compiler: + # ... и с помощью GCC, и Clang + - gcc + - clang + +env: + # список переменных окружения, влияющих на матрицу сборки: + - BUILD_CONFIGURATION=Debug + - BUILD_CONFIGURATION=Release + #- TARGET_CPU=amd64 + +matrix: + exclude: + # вручную исключим ненужные элементы из матрицы сборки: + - os: osx + compiler: gcc + +install: + # скрипт настройки среды и установки зависимостей: + - source testing/ci-install-$TRAVIS_OS_NAME.sh + +accuracy: + - cppcheck --error-exitcode=1 --suppress=missingIncludeSystem --enable=style,performance,portability,warning project/ + +script: + # скрипт сборки и тестирования проекта: + - mkdir build + - cd build + - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_CONFIGURATION + # -DTARGET_CPU=$TARGET_CPU + - cmake --build . + +unit-testing: + - ctest --output-on-failure + - gcovr -r .. + +safety: + - valgrind --error-exitcode=1 --tool=memcheck --leak-check=full ./program ../testing/logic/cases/17.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fe061fa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.16) +project(hw1) +set(CMAKE_C_STANDARD 11) + +set(CMAKE_C_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") +set(CMAKE_CXX_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") +set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) + +include_directories(project/include/) +add_executable(program project/src/program.c project/src/hw-1.c) + +enable_testing() +find_package(GTest REQUIRED) + +include_directories(${GTEST_INCLUDE_DIRS}) +message(${GTEST_LIBRARIES}) +message(${GTEST_INCLUDE_DIRS}) + +add_executable(tests testing/tests.cpp) +target_link_libraries(tests ${GTEST_LIBRARIES} -lpthread) + +add_test(program_and_functions_test ./tests) +add_definitions(-fprofile-arcs -ftest-coverage) +target_link_libraries(tests -fprofile-arcs) \ No newline at end of file diff --git a/project/include/hw-1.h b/project/include/hw-1.h new file mode 100644 index 0000000..acf2b9c --- /dev/null +++ b/project/include/hw-1.h @@ -0,0 +1,47 @@ +// +// Created by denactive on 12.03.2021. +// +#ifndef PROJECT_HW_1_H +#define PROJECT_HW_1_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 + +enum { + single, + multiline +}; + +typedef struct { + char* beg; + char* end; + size_t line; + unsigned int type; +} comment; + +int parse_comments(char* input); +int parse_comments_from_file(const char *filename); +int parse_comments_from_console(); + +char* skip_to_single_quote(char *str, size_t *line_cnt); +char* skip_to_double_quote(char *str, size_t *line_cnt); +char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); +char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); + +int res_exp(comment **res, size_t *comments_amount); +int free_res(comment **res); + +char* console_input(); +char* file_input(const char *filename, struct stat* stat_buf); +void print_res(const comment *res, size_t *comments_amount); +void print_comment(const comment* c); + +#endif //PROJECT_HW_1_H \ No newline at end of file diff --git a/project/src/hw-1.c b/project/src/hw-1.c new file mode 100644 index 0000000..88070cd --- /dev/null +++ b/project/src/hw-1.c @@ -0,0 +1,263 @@ +// +// Created by denactive on 12.03.2021. +// + +#include "hw-1.h" + +// starts from a sym after ' and returns a sym after closing ' +char* skip_to_single_quote(char* str, size_t *line_cnt) { + while (*str != '\'') { + if (*str == '\n') + (*line_cnt)++; + if (*str == NULL || *str == EOF || *str == '\0') + return NULL; + // \' avoidance + if (*str == '\\') { + str++; + if (*str == NULL || *str == EOF || *str == '\0') + str--; + } + str++; + } + return str++; +} + +// starts from a sym after " and returns a sym after closing " +char* skip_to_double_quote(char* str, size_t *line_cnt) { + while (*str != '\"') { + if (*str == '\n') + (*line_cnt)++; + if (*str == NULL || *str == EOF || *str == '\0') + return NULL; + // \" avoidance + if (*str == '\\') { + str++; + if (*str == NULL || *str == EOF || *str == '\0') + str--; + } + str++; + } + return str++; +} + +char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { + comment executed = {str, NULL, *line_cnt, single}; + + while (*str != '\n') { + if (*str == NULL || *str == EOF || *str == '\0') + return NULL; + str++; + } + executed.end = str - 1; + + // saving + if (res_exp(res, comments_amount)) + return NULL; + + (*res)[(*comments_amount) - 1] = executed; + (*line_cnt)++; + return str++; +} + +char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { + // we are here after /* symbols. + comment executed = {str, NULL, *line_cnt, single}; + + // an exception for /*/ smtg */ situation + if (*str == '/') + str++; + + // totally safe :) + while (*str != '/' || *(str - 1) != '*') { + if (*str == '\n') { + executed.type = multiline; + (*line_cnt)++; + } + if (*str == NULL || *str == EOF || *str == '\0') + return NULL; + str++; + } + executed.end = str - 2; + + // saving + if (res_exp(res, comments_amount)) + return NULL; + + (*res)[(*comments_amount) - 1] = executed; + return str++; +} + +int res_exp(comment **res, size_t *comments_amount) { + size_t size = 0; + if (*comments_amount == 0) { + size = sizeof(comment); + *res = (comment*)malloc(size); + if (*res) { + (*comments_amount)++; + return 0; + } else { + return -1; + } + } else { + size = sizeof(comment) * ((*comments_amount) + 1); + *res = (comment*)realloc(*res, size); + if (*res) { + (*comments_amount)++; + return 0; + } else { + return -1; + } + } +} + +int free_res(comment **res) { + free(*res); + *res = NULL; + return 0; +} + +void print_res(const comment *res, size_t *comments_amount) { + printf("=================\n"); + if (!res) + printf("no comments found"); + + for (size_t i = 0; i < *comments_amount; i++) { + printf("[%zu]: ", i); + print_comment(&res[i]); + if (i < *comments_amount - 1) + printf("\n-----------------\n"); + } + printf("\n=================\n"); +} + +char *console_input() { + char *input = (char*)malloc(BUFFER_SIZE * sizeof(char)); + if (!input) + return NULL; + + printf("Enter C code | Press Ctrl+D to end the input | >> "); + char sym = '\0'; + for (int i = 0; sym != EOF && i < BUFFER_SIZE; i++) { + sym = getc(stdin); + if (i == BUFFER_SIZE) { + printf("Warning: Buffer overflow - only %d symbols were saved\n", BUFFER_SIZE - 1); + break; + } + input[i] = sym; + } + + //safety + input[BUFFER_SIZE - 1] = '\0'; + return input; +} + +void print_comment(const comment* c) { + printf("line: %zu; type: ", c->line); + if (c->type == single) + printf("single-line;\n"); + if (c->type == multiline) + printf("multiline;\n"); + + for (char* addr = c->beg; addr <= c->end; addr++) + printf("%c", *addr); +} + +char* file_input(const char* filename, struct stat* stat_buf) { + int fdin = 0; + if ((fdin = open(filename, O_RDONLY)) < 0) { + printf("Error | Usage %s invalid\n", filename); + NULL; + } + + // gain file size + if (fstat(fdin, stat_buf) < 0) { + printf("Error | Impossible to get the %s size\n", filename); + return NULL; + } + + // using mmap + void* content = NULL; + if ((content = mmap(0, stat_buf->st_size, PROT_READ, MAP_SHARED, fdin, 0)) == MAP_FAILED) { + printf("Error | mmap error\n"); + return NULL; + } + + return (char*)content; +} + +// gtest ругается на const +int parse_comments(char* input) { + char *str = input; + + size_t line_cnt = 1; + comment *res = NULL; + size_t comments_amount = 0; + + while (*str != '\0' && *str != NULL && *str != EOF) { + if (*str == '\"') + str = skip_to_double_quote(str + 1, &line_cnt); + if (!str) { + printf("Error | syntax error"); + return 0; + } + if (*str == '\'') + str = skip_to_single_quote(str + 1, &line_cnt); + if (!str) { + printf("Error | syntax error"); + return 0; + } + if (*str == '\n') + line_cnt++; + + if (*str == '/') { + if (*(str + 1) == '/') { + str = execute_line_comment(str + 2, &line_cnt, &res, &comments_amount); + if (!str) { + free_res(&res); + return -1; + } + } + if (*(str + 1) == '*') { + str = execute_multiline_comment(str + 2, &line_cnt, &res, &comments_amount); + if (!str) { + free_res(&res); + return -1; + } + } + } + str++; + } + print_res(res, &comments_amount); + free_res(&res); +} + +int parse_comments_from_file(const char *filename) { + struct stat stat_buf = {}; + char* input = file_input(filename, &stat_buf); + if (!input) { + printf("Error | Empty input\n"); + return -1; + } + + if(parse_comments(input)) + return -1; + + // file mapping closing + if (munmap((void*)input, stat_buf.st_size)) + printf("Error | failed to unmap %s", filename); + return 0; +} + +int parse_comments_from_console() { + char* input = console_input(); + if (!input) { + printf("Error | Empty input\n"); + return -1; + } + + if(parse_comments(input)) + return -1; + + free(input); + return 0; +} \ No newline at end of file diff --git a/project/src/program.c b/project/src/program.c new file mode 100644 index 0000000..16f8b23 --- /dev/null +++ b/project/src/program.c @@ -0,0 +1,12 @@ +#include "hw-1.h" + +int main(int argc, const char** argv) { + if (argc == 1) { + if (parse_comments_from_console()) + return -1; + } else { + if (parse_comments_from_file(argv[1])) + return -1; + } + return 0; +} diff --git a/testing/Testing/Temporary/CTestCostData.txt b/testing/Testing/Temporary/CTestCostData.txt new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/testing/Testing/Temporary/CTestCostData.txt @@ -0,0 +1 @@ +--- diff --git a/testing/Testing/Temporary/LastTest.log b/testing/Testing/Temporary/LastTest.log new file mode 100644 index 0000000..cfff5d7 --- /dev/null +++ b/testing/Testing/Temporary/LastTest.log @@ -0,0 +1,3 @@ +Start testing: Mar 15 16:37 MSK +---------------------------------------------------------- +End testing: Mar 15 16:37 MSK diff --git a/testing/ci-install-linux.sh b/testing/ci-install-linux.sh new file mode 100644 index 0000000..64d78ad --- /dev/null +++ b/testing/ci-install-linux.sh @@ -0,0 +1,25 @@ +sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test +sudo apt-get update -qq + +sudo apt-get install -qq g++-5 +sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 90 + +sudo apt-get install cmake + +sudo apt-get install libgtest-dev +cd /usr/src/gtest +sudo cmake CMakeLists.txt +sudo make +sudo cp ./lib/libgtest*.a /usr/lib +cd - + +sudo apt-get install -y valgrind + +sudo apt-get install -y cppcheck + +#gcovr +#Installing python is unnesessary +#sudo apt install -y python3-pip +sudo apt-get install python3-setuptools && sudo pip3 install git+https://github.com/gcovr/gcovr.git + +#TODO: include linters diff --git a/testing/ci-install-osx.sh b/testing/ci-install-osx.sh new file mode 100644 index 0000000..e69de29 diff --git a/testing/console_input/answers/1.txt b/testing/console_input/answers/1.txt new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/testing/console_input/answers/1.txt @@ -0,0 +1 @@ +hello world diff --git a/testing/console_input/answers/2.txt b/testing/console_input/answers/2.txt new file mode 100644 index 0000000..7d03278 --- /dev/null +++ b/testing/console_input/answers/2.txt @@ -0,0 +1,3 @@ +here +we +go again diff --git a/testing/console_input/answers/3.txt b/testing/console_input/answers/3.txt new file mode 100644 index 0000000..8179f38 --- /dev/null +++ b/testing/console_input/answers/3.txt @@ -0,0 +1,26 @@ + std::string test_filename = "../testing/easytests/logic/" + std::to_string(i) + ".txt"; + std::string answer_filename = "../testing/easyanswers/logic/" + std::to_string(i) + ".txt"; + std::fstream is(answer_filename); + ASSERT_TRUE(is.is_open()); + std::string answer_str; + char sym = '\0'; + while (is.get(sym)) + answer_str += sym; + is.close(); + + int fd[2]; + pipe(fd); + pid_t pid_fork = fork(); + int status = 0; + + if (!pid_fork) { + // Дочерний процесс + close(fd[0]); + dup2(fd[1], STDOUT_FILENO); + + std::string res; + execl("program", "program", test_filename.c_str(), NULL); + + close(fd[1]); + exit(0); + } diff --git a/testing/console_input/answers/4.txt b/testing/console_input/answers/4.txt new file mode 100644 index 0000000..78d2957 --- /dev/null +++ b/testing/console_input/answers/4.txt @@ -0,0 +1,49 @@ +// +// Created by denactive on 12.03.2021. +// +#ifndef PROJECT_HW_1_H +#define PROJECT_HW_1_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG 0 +#define BUFFER_SIZE 1024 + +enum { + single, + multiline +}; + +typedef struct { + char* beg; + char* end; + size_t line; + unsigned int type; +} comment; + +int parse_comments(char* input); +int parse_comments_from_file(const char *filename); +int parse_comments_from_console(); + +char* skip_to_single_quote(char *str, size_t *line_cnt); +char* skip_to_double_quote(char *str, size_t *line_cnt); +char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); +char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); + +int res_exp(comment **res, size_t *comments_amount); +int free_res(comment **res); + +char* console_input(); +char* file_input(const char *filename, struct stat* stat_buf); +void print_res(const comment *res, size_t *comments_amount); +void print_comment(const comment* c); + +#endif //PROJECT_HW_1_H diff --git a/testing/console_input/cases/1.txt b/testing/console_input/cases/1.txt new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/testing/console_input/cases/1.txt @@ -0,0 +1 @@ +hello world diff --git a/testing/console_input/cases/2.txt b/testing/console_input/cases/2.txt new file mode 100644 index 0000000..7d03278 --- /dev/null +++ b/testing/console_input/cases/2.txt @@ -0,0 +1,3 @@ +here +we +go again diff --git a/testing/console_input/cases/3.txt b/testing/console_input/cases/3.txt new file mode 100644 index 0000000..8179f38 --- /dev/null +++ b/testing/console_input/cases/3.txt @@ -0,0 +1,26 @@ + std::string test_filename = "../testing/easytests/logic/" + std::to_string(i) + ".txt"; + std::string answer_filename = "../testing/easyanswers/logic/" + std::to_string(i) + ".txt"; + std::fstream is(answer_filename); + ASSERT_TRUE(is.is_open()); + std::string answer_str; + char sym = '\0'; + while (is.get(sym)) + answer_str += sym; + is.close(); + + int fd[2]; + pipe(fd); + pid_t pid_fork = fork(); + int status = 0; + + if (!pid_fork) { + // Дочерний процесс + close(fd[0]); + dup2(fd[1], STDOUT_FILENO); + + std::string res; + execl("program", "program", test_filename.c_str(), NULL); + + close(fd[1]); + exit(0); + } diff --git a/testing/console_input/cases/4.txt b/testing/console_input/cases/4.txt new file mode 100644 index 0000000..78d2957 --- /dev/null +++ b/testing/console_input/cases/4.txt @@ -0,0 +1,49 @@ +// +// Created by denactive on 12.03.2021. +// +#ifndef PROJECT_HW_1_H +#define PROJECT_HW_1_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG 0 +#define BUFFER_SIZE 1024 + +enum { + single, + multiline +}; + +typedef struct { + char* beg; + char* end; + size_t line; + unsigned int type; +} comment; + +int parse_comments(char* input); +int parse_comments_from_file(const char *filename); +int parse_comments_from_console(); + +char* skip_to_single_quote(char *str, size_t *line_cnt); +char* skip_to_double_quote(char *str, size_t *line_cnt); +char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); +char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); + +int res_exp(comment **res, size_t *comments_amount); +int free_res(comment **res); + +char* console_input(); +char* file_input(const char *filename, struct stat* stat_buf); +void print_res(const comment *res, size_t *comments_amount); +void print_comment(const comment* c); + +#endif //PROJECT_HW_1_H diff --git a/testing/logic/answers/1.txt b/testing/logic/answers/1.txt new file mode 100644 index 0000000..2b73f76 --- /dev/null +++ b/testing/logic/answers/1.txt @@ -0,0 +1,4 @@ +================= +[0]: line: 1; type: single-line; +simple comment +================= diff --git a/testing/logic/answers/10.txt b/testing/logic/answers/10.txt new file mode 100644 index 0000000..cbbc078 --- /dev/null +++ b/testing/logic/answers/10.txt @@ -0,0 +1,5 @@ +================= +[0]: line: 1; type: multiline; +multi +line comments +================= diff --git a/testing/logic/answers/11.txt b/testing/logic/answers/11.txt new file mode 100644 index 0000000..ba49bdd --- /dev/null +++ b/testing/logic/answers/11.txt @@ -0,0 +1,28 @@ +================= +[0]: line: 1; type: multiline; + +h +e +r +e + +"is" + +a + +"really silly" + c + o + m + + + + m + e + 'n' + t +/structure/ +----------------- +[1]: line: 24; type: single-line; + this is a 24th line +================= diff --git a/testing/logic/answers/12.txt b/testing/logic/answers/12.txt new file mode 100644 index 0000000..9829956 --- /dev/null +++ b/testing/logic/answers/12.txt @@ -0,0 +1,16 @@ +================= +[0]: line: 1; type: single-line; +line-1 +----------------- +[1]: line: 2; type: single-line; +line-2 +----------------- +[2]: line: 3; type: single-line; +line-3 +----------------- +[3]: line: 6; type: single-line; +line-6 +----------------- +[4]: line: 9; type: single-line; +line-8 +================= diff --git a/testing/logic/answers/13.txt b/testing/logic/answers/13.txt new file mode 100644 index 0000000..77b6536 --- /dev/null +++ b/testing/logic/answers/13.txt @@ -0,0 +1,25 @@ +================= +[0]: line: 16; type: single-line; +line 16 +----------------- +[1]: line: 18; type: multiline; + +19 +20 +21 +22 +23 + +----------------- +[2]: line: 26; type: single-line; +26 line))) +----------------- +[3]: line: 29; type: single-line; +29 line)) (( // ////// +----------------- +[4]: line: 30; type: single-line; +30 line))0 /*hi // */ "'"' '/' '\n' "/" bye( +----------------- +[5]: line: 32; type: single-line; +why is this singleline? (line 32) +================= diff --git a/testing/logic/answers/14.txt b/testing/logic/answers/14.txt new file mode 100644 index 0000000..c4f0a17 --- /dev/null +++ b/testing/logic/answers/14.txt @@ -0,0 +1 @@ +Error | syntax error \ No newline at end of file diff --git a/testing/logic/answers/15.txt b/testing/logic/answers/15.txt new file mode 100644 index 0000000..0d81c20 --- /dev/null +++ b/testing/logic/answers/15.txt @@ -0,0 +1,20 @@ +================= +[0]: line: 1; type: single-line; +this is a quotes exception test +----------------- +[1]: line: 3; type: single-line; +'a' +----------------- +[2]: line: 5; type: single-line; +'/' +----------------- +[3]: line: 7; type: single-line; +"but this should" <-- watch quotes here +----------------- +[4]: line: 8; type: multiline; + +// +/ +/* / + +================= diff --git a/testing/logic/answers/16.txt b/testing/logic/answers/16.txt new file mode 100644 index 0000000..c4f0a17 --- /dev/null +++ b/testing/logic/answers/16.txt @@ -0,0 +1 @@ +Error | syntax error \ No newline at end of file diff --git a/testing/logic/answers/17.txt b/testing/logic/answers/17.txt new file mode 100644 index 0000000..b397180 --- /dev/null +++ b/testing/logic/answers/17.txt @@ -0,0 +1,136 @@ +================= +[0]: line: 1; type: single-line; +comment +----------------- +[1]: line: 2; type: single-line; +comment +----------------- +[2]: line: 3; type: single-line; +comment +----------------- +[3]: line: 4; type: single-line; +comment +----------------- +[4]: line: 5; type: single-line; +comment +----------------- +[5]: line: 6; type: single-line; +comment +----------------- +[6]: line: 7; type: single-line; +comment +----------------- +[7]: line: 8; type: single-line; +comment +----------------- +[8]: line: 9; type: single-line; +comment +----------------- +[9]: line: 10; type: single-line; +comment +----------------- +[10]: line: 11; type: single-line; +comment +----------------- +[11]: line: 12; type: single-line; +comment +----------------- +[12]: line: 13; type: single-line; +comment +----------------- +[13]: line: 14; type: single-line; +comment +----------------- +[14]: line: 15; type: single-line; +comment +----------------- +[15]: line: 16; type: single-line; +comment +----------------- +[16]: line: 17; type: single-line; +comment +----------------- +[17]: line: 18; type: single-line; +comment +----------------- +[18]: line: 19; type: single-line; +comment +----------------- +[19]: line: 20; type: single-line; +comment +----------------- +[20]: line: 21; type: single-line; +comment +----------------- +[21]: line: 22; type: single-line; +comment +----------------- +[22]: line: 23; type: single-line; +comment +----------------- +[23]: line: 24; type: single-line; +comment +----------------- +[24]: line: 25; type: single-line; +word +----------------- +[25]: line: 26; type: single-line; +word +----------------- +[26]: line: 27; type: single-line; +word +----------------- +[27]: line: 28; type: single-line; +word +----------------- +[28]: line: 29; type: single-line; +word +----------------- +[29]: line: 30; type: single-line; +word +----------------- +[30]: line: 31; type: single-line; +word +----------------- +[31]: line: 32; type: single-line; +word +----------------- +[32]: line: 33; type: single-line; +word +----------------- +[33]: line: 34; type: single-line; +word +----------------- +[34]: line: 35; type: single-line; +word +----------------- +[35]: line: 36; type: single-line; +word +----------------- +[36]: line: 37; type: single-line; +word +----------------- +[37]: line: 38; type: single-line; +word +----------------- +[38]: line: 39; type: single-line; +word +----------------- +[39]: line: 40; type: single-line; +word +----------------- +[40]: line: 41; type: single-line; +word +----------------- +[41]: line: 42; type: single-line; +word +----------------- +[42]: line: 43; type: single-line; +word +----------------- +[43]: line: 44; type: single-line; +word +----------------- +[44]: line: 45; type: single-line; +comment +================= diff --git a/testing/logic/answers/2.txt b/testing/logic/answers/2.txt new file mode 100644 index 0000000..e85a75f --- /dev/null +++ b/testing/logic/answers/2.txt @@ -0,0 +1,3 @@ +================= +no comments found +================= diff --git a/testing/logic/answers/3.txt b/testing/logic/answers/3.txt new file mode 100644 index 0000000..2d3f63a --- /dev/null +++ b/testing/logic/answers/3.txt @@ -0,0 +1,4 @@ +================= +[0]: line: 1; type: single-line; +simple multiline +================= diff --git a/testing/logic/answers/4.txt b/testing/logic/answers/4.txt new file mode 100644 index 0000000..6c32010 --- /dev/null +++ b/testing/logic/answers/4.txt @@ -0,0 +1,6 @@ +================= +[0]: line: 1; type: multiline; +realy +multiline + +================= diff --git a/testing/logic/answers/5.txt b/testing/logic/answers/5.txt new file mode 100644 index 0000000..f002d67 --- /dev/null +++ b/testing/logic/answers/5.txt @@ -0,0 +1,5 @@ +================= +[0]: line: 1; type: multiline; + +multiline +================= diff --git a/testing/logic/answers/6.txt b/testing/logic/answers/6.txt new file mode 100644 index 0000000..366c18f --- /dev/null +++ b/testing/logic/answers/6.txt @@ -0,0 +1,10 @@ +================= +[0]: line: 1; type: single-line; +double +----------------- +[1]: line: 2; type: single-line; +comment +----------------- +[2]: line: 2; type: single-line; +case +================= diff --git a/testing/logic/answers/7.txt b/testing/logic/answers/7.txt new file mode 100644 index 0000000..aa5f92f --- /dev/null +++ b/testing/logic/answers/7.txt @@ -0,0 +1,4 @@ +================= +[0]: line: 1; type: single-line; +and a comment +================= diff --git a/testing/logic/answers/8.txt b/testing/logic/answers/8.txt new file mode 100644 index 0000000..32ce0a2 --- /dev/null +++ b/testing/logic/answers/8.txt @@ -0,0 +1,4 @@ +================= +[0]: line: 6; type: single-line; + pretty comment +================= diff --git a/testing/logic/answers/9.txt b/testing/logic/answers/9.txt new file mode 100644 index 0000000..96e4e07 --- /dev/null +++ b/testing/logic/answers/9.txt @@ -0,0 +1,4 @@ +================= +[0]: line: 2; type: single-line; +multiline comment in a single row +================= diff --git a/testing/logic/cases/1.txt b/testing/logic/cases/1.txt new file mode 100644 index 0000000..45380ab --- /dev/null +++ b/testing/logic/cases/1.txt @@ -0,0 +1 @@ +//simple comment diff --git a/testing/logic/cases/10.txt b/testing/logic/cases/10.txt new file mode 100644 index 0000000..a749c49 --- /dev/null +++ b/testing/logic/cases/10.txt @@ -0,0 +1,2 @@ +this if a hard test for "/*quotes*/" and /*multi +line comments*/ diff --git a/testing/logic/cases/11.txt b/testing/logic/cases/11.txt new file mode 100644 index 0000000..ca30405 --- /dev/null +++ b/testing/logic/cases/11.txt @@ -0,0 +1,24 @@ +hello one more time/* +h +e +r +e + +"is" + +a + +"really silly" + c + o + m + + + + m + e + 'n' + t +/structure/*/ + +// this is a 24th line diff --git a/testing/logic/cases/12.txt b/testing/logic/cases/12.txt new file mode 100644 index 0000000..3890dce --- /dev/null +++ b/testing/logic/cases/12.txt @@ -0,0 +1,9 @@ +//line-1 +//line-2 +//line-3 + + +//line-6 + + +//line-8 diff --git a/testing/logic/cases/13.txt b/testing/logic/cases/13.txt new file mode 100644 index 0000000..8e9d5e9 --- /dev/null +++ b/testing/logic/cases/13.txt @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + +this is //line 16 + +/* +19 +20 +21 +22 +23 +*/ + +//26 line))) + + +//29 line)) (( // ////// +//30 line))0 /*hi // */ "'"' '/' '\n' "/" bye( + +/*why is this singleline? (line 32)*/ diff --git a/testing/logic/cases/14.txt b/testing/logic/cases/14.txt new file mode 100644 index 0000000..6092a0d --- /dev/null +++ b/testing/logic/cases/14.txt @@ -0,0 +1,6 @@ +//oh nooo + +//is this a Syntax error ? + +probably "yea + diff --git a/testing/logic/cases/15.txt b/testing/logic/cases/15.txt new file mode 100644 index 0000000..484ca97 --- /dev/null +++ b/testing/logic/cases/15.txt @@ -0,0 +1,17 @@ +//this is a quotes exception test +'a' +//'a' +'/' +//'/' +"this should not be printed" +//"but this should" <-- watch quotes here +/* +// +/ +/* / +*/ + +"wtf these quates \" are \' still \" not 'closed' ? +" + +"/*hello world again*/" diff --git a/testing/logic/cases/16.txt b/testing/logic/cases/16.txt new file mode 100644 index 0000000..27e4e27 --- /dev/null +++ b/testing/logic/cases/16.txt @@ -0,0 +1 @@ +"this is invalid string I swear //"" diff --git a/testing/logic/cases/17.txt b/testing/logic/cases/17.txt new file mode 100644 index 0000000..1caf4a0 --- /dev/null +++ b/testing/logic/cases/17.txt @@ -0,0 +1,45 @@ +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//comment +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//word +//comment diff --git a/testing/logic/cases/2.txt b/testing/logic/cases/2.txt new file mode 100644 index 0000000..5b0edfe --- /dev/null +++ b/testing/logic/cases/2.txt @@ -0,0 +1 @@ +no comments diff --git a/testing/logic/cases/3.txt b/testing/logic/cases/3.txt new file mode 100644 index 0000000..b8d46b4 --- /dev/null +++ b/testing/logic/cases/3.txt @@ -0,0 +1 @@ +/*simple multiline*/ diff --git a/testing/logic/cases/4.txt b/testing/logic/cases/4.txt new file mode 100644 index 0000000..e9ad373 --- /dev/null +++ b/testing/logic/cases/4.txt @@ -0,0 +1,3 @@ +/*realy +multiline +*/ diff --git a/testing/logic/cases/5.txt b/testing/logic/cases/5.txt new file mode 100644 index 0000000..b26dc59 --- /dev/null +++ b/testing/logic/cases/5.txt @@ -0,0 +1,2 @@ +bodied/* +multiline*/ diff --git a/testing/logic/cases/6.txt b/testing/logic/cases/6.txt new file mode 100644 index 0000000..2d7a1a2 --- /dev/null +++ b/testing/logic/cases/6.txt @@ -0,0 +1,2 @@ +/*double*/ +/*comment*/ missing word //case diff --git a/testing/logic/cases/7.txt b/testing/logic/cases/7.txt new file mode 100644 index 0000000..c969501 --- /dev/null +++ b/testing/logic/cases/7.txt @@ -0,0 +1,2 @@ +some text//and a comment + diff --git a/testing/logic/cases/8.txt b/testing/logic/cases/8.txt new file mode 100644 index 0000000..4ea06cc --- /dev/null +++ b/testing/logic/cases/8.txt @@ -0,0 +1,7 @@ +some +long +text +and +here is a +// pretty comment + diff --git a/testing/logic/cases/9.txt b/testing/logic/cases/9.txt new file mode 100644 index 0000000..948ddef --- /dev/null +++ b/testing/logic/cases/9.txt @@ -0,0 +1,2 @@ +hello world +here is a /*multiline comment in a single row*/ of text diff --git a/testing/openfile/answers/1.txt b/testing/openfile/answers/1.txt new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/testing/openfile/answers/1.txt @@ -0,0 +1 @@ +hello world diff --git a/testing/openfile/answers/2.txt b/testing/openfile/answers/2.txt new file mode 100644 index 0000000..7d03278 --- /dev/null +++ b/testing/openfile/answers/2.txt @@ -0,0 +1,3 @@ +here +we +go again diff --git a/testing/openfile/answers/3.txt b/testing/openfile/answers/3.txt new file mode 100644 index 0000000..8179f38 --- /dev/null +++ b/testing/openfile/answers/3.txt @@ -0,0 +1,26 @@ + std::string test_filename = "../testing/easytests/logic/" + std::to_string(i) + ".txt"; + std::string answer_filename = "../testing/easyanswers/logic/" + std::to_string(i) + ".txt"; + std::fstream is(answer_filename); + ASSERT_TRUE(is.is_open()); + std::string answer_str; + char sym = '\0'; + while (is.get(sym)) + answer_str += sym; + is.close(); + + int fd[2]; + pipe(fd); + pid_t pid_fork = fork(); + int status = 0; + + if (!pid_fork) { + // Дочерний процесс + close(fd[0]); + dup2(fd[1], STDOUT_FILENO); + + std::string res; + execl("program", "program", test_filename.c_str(), NULL); + + close(fd[1]); + exit(0); + } diff --git a/testing/openfile/answers/4.txt b/testing/openfile/answers/4.txt new file mode 100644 index 0000000..78d2957 --- /dev/null +++ b/testing/openfile/answers/4.txt @@ -0,0 +1,49 @@ +// +// Created by denactive on 12.03.2021. +// +#ifndef PROJECT_HW_1_H +#define PROJECT_HW_1_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG 0 +#define BUFFER_SIZE 1024 + +enum { + single, + multiline +}; + +typedef struct { + char* beg; + char* end; + size_t line; + unsigned int type; +} comment; + +int parse_comments(char* input); +int parse_comments_from_file(const char *filename); +int parse_comments_from_console(); + +char* skip_to_single_quote(char *str, size_t *line_cnt); +char* skip_to_double_quote(char *str, size_t *line_cnt); +char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); +char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); + +int res_exp(comment **res, size_t *comments_amount); +int free_res(comment **res); + +char* console_input(); +char* file_input(const char *filename, struct stat* stat_buf); +void print_res(const comment *res, size_t *comments_amount); +void print_comment(const comment* c); + +#endif //PROJECT_HW_1_H diff --git a/testing/openfile/cases/1.txt b/testing/openfile/cases/1.txt new file mode 100644 index 0000000..3b18e51 --- /dev/null +++ b/testing/openfile/cases/1.txt @@ -0,0 +1 @@ +hello world diff --git a/testing/openfile/cases/2.txt b/testing/openfile/cases/2.txt new file mode 100644 index 0000000..7d03278 --- /dev/null +++ b/testing/openfile/cases/2.txt @@ -0,0 +1,3 @@ +here +we +go again diff --git a/testing/openfile/cases/3.txt b/testing/openfile/cases/3.txt new file mode 100644 index 0000000..8179f38 --- /dev/null +++ b/testing/openfile/cases/3.txt @@ -0,0 +1,26 @@ + std::string test_filename = "../testing/easytests/logic/" + std::to_string(i) + ".txt"; + std::string answer_filename = "../testing/easyanswers/logic/" + std::to_string(i) + ".txt"; + std::fstream is(answer_filename); + ASSERT_TRUE(is.is_open()); + std::string answer_str; + char sym = '\0'; + while (is.get(sym)) + answer_str += sym; + is.close(); + + int fd[2]; + pipe(fd); + pid_t pid_fork = fork(); + int status = 0; + + if (!pid_fork) { + // Дочерний процесс + close(fd[0]); + dup2(fd[1], STDOUT_FILENO); + + std::string res; + execl("program", "program", test_filename.c_str(), NULL); + + close(fd[1]); + exit(0); + } diff --git a/testing/openfile/cases/4.txt b/testing/openfile/cases/4.txt new file mode 100644 index 0000000..78d2957 --- /dev/null +++ b/testing/openfile/cases/4.txt @@ -0,0 +1,49 @@ +// +// Created by denactive on 12.03.2021. +// +#ifndef PROJECT_HW_1_H +#define PROJECT_HW_1_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG 0 +#define BUFFER_SIZE 1024 + +enum { + single, + multiline +}; + +typedef struct { + char* beg; + char* end; + size_t line; + unsigned int type; +} comment; + +int parse_comments(char* input); +int parse_comments_from_file(const char *filename); +int parse_comments_from_console(); + +char* skip_to_single_quote(char *str, size_t *line_cnt); +char* skip_to_double_quote(char *str, size_t *line_cnt); +char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); +char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); + +int res_exp(comment **res, size_t *comments_amount); +int free_res(comment **res); + +char* console_input(); +char* file_input(const char *filename, struct stat* stat_buf); +void print_res(const comment *res, size_t *comments_amount); +void print_comment(const comment* c); + +#endif //PROJECT_HW_1_H diff --git a/testing/tests.cpp b/testing/tests.cpp new file mode 100644 index 0000000..e67d4fd --- /dev/null +++ b/testing/tests.cpp @@ -0,0 +1,186 @@ +#include "gtest/gtest.h" +#include +#include +#include +#include + +#define LOGIC_TESTS_COUNT 17 +#define TESTS_OPEN_FILE_COUNT 4 + +extern "C" { + #include "hw-1.h" + #include "../project/src/hw-1.c" +}; + +// TODO: no console print in funcs, but print in main + +TEST(LogicTest, Main) { + std::cout << "Logic test" << std::endl; + for (int i = 1; i <= LOGIC_TESTS_COUNT; i++) { + std::string test_filename = "../testing/logic/cases/" + std::to_string(i) + ".txt"; + std::string answer_filename = "../testing/logic/answers/" + std::to_string(i) + ".txt"; + std::cout << "\tTesting " << test_filename << std::endl; + std::fstream is(answer_filename); + ASSERT_TRUE(is.is_open()); + std::string answer_str; + char sym = '\0'; + while (is.get(sym)) + answer_str += sym; + is.close(); + + int fd[2]; + pipe(fd); + pid_t pid_fork = fork(); + int status = 0; + + if (!pid_fork) { + // Дочерний процесс + close(fd[0]); + dup2(fd[1], STDOUT_FILENO); + + execl("program", "program", test_filename.c_str(), NULL); + + close(fd[1]); + exit(0); + } + + // Родительский процесс + close(fd[1]); + + ssize_t sz; + char* buf = (char*)calloc(20 * BUFFER_SIZE, sizeof(char)); + int err = 0; + if (!buf) + err = -1; + ASSERT_EQ(err, 0); + + sz = read(fd[0], buf, 20 * BUFFER_SIZE); + close(fd[0]); + /*if (sz > 0) { + write(STDOUT_FILENO, buf, sz); + }*/ + waitpid(pid_fork, &status, 0); + + EXPECT_STREQ(buf, answer_str.c_str()); + free(buf); + } +} + +TEST(OpenFile, EasyTest) { + std::cout << "File opening test" << std::endl; + for (int i = 1; i <= TESTS_OPEN_FILE_COUNT; i++) { + std::string test_filename = "../testing/openfile/cases/" + std::to_string(i) + ".txt"; + std::string answer_filename = "../testing/openfile/answers/" + std::to_string(i) + ".txt"; + std::cout << "\tTesting " << test_filename << std::endl; + std::fstream is(answer_filename); + ASSERT_TRUE(is.is_open()); + std::string answer_str; + char sym = '\0'; + while (is.get(sym)) + answer_str += sym; + is.close(); + + struct stat stat_buf; + std::string res = file_input(test_filename.c_str(), &stat_buf); + EXPECT_STREQ(res.c_str(), answer_str.c_str()); + } +} + +TEST(ErrorTest, BadFile) { + const char invalid_file [] = "not_existing_file.wtf"; + std::cout << "File opening test" << std::endl; + std::cout << "\tTesting " << invalid_file << std::endl; + + struct stat stat_buf; + char* res = file_input(invalid_file, &stat_buf); + EXPECT_FALSE(res); +} + +TEST(ErrorTest, SingleQuotesSkipping) { + const char invalid_line [] = "' here we can see an opening quote, but no closing one"; + std::cout << "Error test | no closing single quote in a file" << std::endl; + + size_t cnt = 1; + char* res = skip_to_single_quote(const_cast(&invalid_line[1]), &cnt); + EXPECT_FALSE(res); + EXPECT_EQ(cnt, 1); +} + +TEST(ErrorTest, SingleQuotesSkippingMultiline) { + const char invalid_line [] = "\" here we can see\nan opening quote,\nbut no closing one"; + std::cout << "Error test | no closing single quote in a multiline file" << std::endl; + + size_t cnt = 1; + char* res = skip_to_single_quote(const_cast(&invalid_line[1]), &cnt); + EXPECT_FALSE(res); + EXPECT_EQ(cnt, 3); +} + +TEST(ErrorTest, DoubleQuotesSkipping) { + const char invalid_line [] = "' here we can see an opening quote, but no closing one"; + std::cout << "Error test | no closing double quote in a file" << std::endl; + + size_t cnt = 1; + char* res = skip_to_single_quote(const_cast(&invalid_line[1]), &cnt); + EXPECT_FALSE(res); + EXPECT_EQ(cnt, 1); +} + +TEST(ErrorTest, DoubleQuotesSkippingMultiline) { + const char invalid_line [] = "\" here we can see\nan opening quote,\nbut no closing one"; + std::cout << "Error test | no closing double quote in a multiline file" << std::endl; + + size_t cnt = 1; + char* res = skip_to_single_quote(const_cast(&invalid_line[1]), &cnt); + EXPECT_FALSE(res); + EXPECT_EQ(cnt, 3); +} + +TEST(EdgeTest, SlashesAfterOpeningMultilineComment) { + const char line [] = "/this is fucked up multiline\n/*/"; + const char answer [] = "/this is fucked up multiline\n/"; + std::cout << "EdgeTest | /*/ comment /*/ situation" << std::endl; + + size_t line_cnt = 1; + size_t comments_cnt = 0; + comment* res = NULL; + execute_multiline_comment(const_cast(line), &line_cnt, &res, &comments_cnt); + + ASSERT_NE(res, nullptr); + EXPECT_EQ(line_cnt, 2); + EXPECT_EQ(comments_cnt, 1); + EXPECT_EQ(res[0].type, multiline); + EXPECT_EQ(res[0].line, 1); + std::string res_line; + for (char* i = res[0].beg; i <= res[0].end; i++) + res_line += *i; + EXPECT_STREQ(res_line.c_str(), answer); + free_res(&res); +} + +TEST(EdgeTest, ShieldingSingleQuotes) { + const char line_const [] = "this is a \\'line'"; + char* line = (char*)malloc(strlen(line_const) + 1); + ASSERT_NE(line, nullptr); + strcpy(line, line_const); + line[strlen(line_const)] = '\0'; + + const char answer [] = "this is a \\'line"; + std::cout << "EdgeTest | \\' situation" << std::endl; + + size_t line_cnt = 1; + char* closing_quote = skip_to_single_quote(line, &line_cnt); + + ASSERT_NE(closing_quote, nullptr); + EXPECT_EQ(line_cnt, 1); + std::string res_line; + for (char* i = line; i < closing_quote; i++) + res_line += *i; + EXPECT_STREQ(res_line.c_str(), answer); + free(line); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git "a/\320\277\320\276\320\272\321\200\321\213\321\202\320\270\320\265.png" "b/\320\277\320\276\320\272\321\200\321\213\321\202\320\270\320\265.png" new file mode 100644 index 0000000000000000000000000000000000000000..b7e97742c718ff2ce0d4d6153210b2d03d999249 GIT binary patch literal 40162 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 Date: Tue, 16 Mar 2021 21:52:06 +0300 Subject: [PATCH 02/11] 85% coverage. Fixed bugs --- README.md | 6 +- project/include/hw-1.h | 10 +-- project/src/hw-1.c | 99 +++++++++++---------- testing/Testing/Temporary/CTestCostData.txt | 1 - testing/Testing/Temporary/LastTest.log | 3 - testing/console_input/answers/1.txt | 1 - testing/console_input/answers/2.txt | 3 - testing/console_input/answers/3.txt | 26 ------ testing/console_input/answers/4.txt | 49 ---------- testing/console_input/cases/1.txt | 1 - testing/console_input/cases/2.txt | 3 - testing/console_input/cases/3.txt | 26 ------ testing/console_input/cases/4.txt | 49 ---------- testing/logic/answers/12.txt | 2 +- testing/logic/answers/14.txt | 2 +- testing/logic/answers/16.txt | 2 +- testing/logic/cases/12.txt | 2 +- testing/tests.cpp | 44 ++++++--- 18 files changed, 100 insertions(+), 229 deletions(-) delete mode 100644 testing/Testing/Temporary/CTestCostData.txt delete mode 100644 testing/Testing/Temporary/LastTest.log delete mode 100644 testing/console_input/answers/1.txt delete mode 100644 testing/console_input/answers/2.txt delete mode 100644 testing/console_input/answers/3.txt delete mode 100644 testing/console_input/answers/4.txt delete mode 100644 testing/console_input/cases/1.txt delete mode 100644 testing/console_input/cases/2.txt delete mode 100644 testing/console_input/cases/3.txt delete mode 100644 testing/console_input/cases/4.txt diff --git a/README.md b/README.md index 657ccef..4060c09 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # [Techno] CPP -Домашки Турчина Дениса +Домашки Дениса Турчина +АПО-13 Вар 74 + +# Вариант #74 +Разработать программу, которая на вход принимает исходный код на языке C, находит в нём все комментарии (однострочные и многострочные) и для каждого из них заполняет структуру, содержащую информацию о тексте комментария, его типе и о номерах строк, на которых он расположен. В результате должен получиться список таких структур, который нужно вывести на экран. diff --git a/project/include/hw-1.h b/project/include/hw-1.h index acf2b9c..b19c9dd 100644 --- a/project/include/hw-1.h +++ b/project/include/hw-1.h @@ -27,14 +27,14 @@ typedef struct { unsigned int type; } comment; -int parse_comments(char* input); +int parse_comments(const char* input); int parse_comments_from_file(const char *filename); int parse_comments_from_console(); -char* skip_to_single_quote(char *str, size_t *line_cnt); -char* skip_to_double_quote(char *str, size_t *line_cnt); -char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); -char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); +char* skip_to_single_quote(const char *str, size_t *line_cnt); +char* skip_to_double_quote(const char *str, size_t *line_cnt); +char* execute_line_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount); +char* execute_multiline_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount); int res_exp(comment **res, size_t *comments_amount); int free_res(comment **res); diff --git a/project/src/hw-1.c b/project/src/hw-1.c index 88070cd..b8aa54d 100644 --- a/project/src/hw-1.c +++ b/project/src/hw-1.c @@ -5,7 +5,7 @@ #include "hw-1.h" // starts from a sym after ' and returns a sym after closing ' -char* skip_to_single_quote(char* str, size_t *line_cnt) { +char* skip_to_single_quote(const char* str, size_t *line_cnt) { while (*str != '\'') { if (*str == '\n') (*line_cnt)++; @@ -19,11 +19,11 @@ char* skip_to_single_quote(char* str, size_t *line_cnt) { } str++; } - return str++; + return (char*)str + 1; } // starts from a sym after " and returns a sym after closing " -char* skip_to_double_quote(char* str, size_t *line_cnt) { +char* skip_to_double_quote(const char* str, size_t *line_cnt) { while (*str != '\"') { if (*str == '\n') (*line_cnt)++; @@ -37,18 +37,18 @@ char* skip_to_double_quote(char* str, size_t *line_cnt) { } str++; } - return str++; + return (char*)str + 1; } -char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { - comment executed = {str, NULL, *line_cnt, single}; +char* execute_line_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { + comment executed = {(char*)str, NULL, *line_cnt, single}; while (*str != '\n') { if (*str == NULL || *str == EOF || *str == '\0') return NULL; str++; } - executed.end = str - 1; + executed.end = (char*)str - 1; // saving if (res_exp(res, comments_amount)) @@ -56,12 +56,12 @@ char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *c (*res)[(*comments_amount) - 1] = executed; (*line_cnt)++; - return str++; + return (char*)str + 1; } -char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { +char* execute_multiline_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { // we are here after /* symbols. - comment executed = {str, NULL, *line_cnt, single}; + comment executed = {(char*)str, NULL, *line_cnt, single}; // an exception for /*/ smtg */ situation if (*str == '/') @@ -77,14 +77,14 @@ char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size return NULL; str++; } - executed.end = str - 2; + executed.end = (char*)str - 2; // saving if (res_exp(res, comments_amount)) return NULL; (*res)[(*comments_amount) - 1] = executed; - return str++; + return (char*)str + 1; } int res_exp(comment **res, size_t *comments_amount) { @@ -100,9 +100,10 @@ int res_exp(comment **res, size_t *comments_amount) { } } else { size = sizeof(comment) * ((*comments_amount) + 1); - *res = (comment*)realloc(*res, size); - if (*res) { + comment *tmp = (comment*)realloc(*res, size); + if (tmp) { (*comments_amount)++; + *res = tmp; return 0; } else { return -1; @@ -139,7 +140,7 @@ char *console_input() { char sym = '\0'; for (int i = 0; sym != EOF && i < BUFFER_SIZE; i++) { sym = getc(stdin); - if (i == BUFFER_SIZE) { + if (i == BUFFER_SIZE - 1) { printf("Warning: Buffer overflow - only %d symbols were saved\n", BUFFER_SIZE - 1); break; } @@ -186,49 +187,57 @@ char* file_input(const char* filename, struct stat* stat_buf) { } // gtest ругается на const -int parse_comments(char* input) { - char *str = input; +int parse_comments(const char* input) { + const char *str = input; size_t line_cnt = 1; comment *res = NULL; size_t comments_amount = 0; while (*str != '\0' && *str != NULL && *str != EOF) { - if (*str == '\"') - str = skip_to_double_quote(str + 1, &line_cnt); - if (!str) { - printf("Error | syntax error"); - return 0; - } - if (*str == '\'') - str = skip_to_single_quote(str + 1, &line_cnt); - if (!str) { - printf("Error | syntax error"); - return 0; - } - if (*str == '\n') - line_cnt++; - - if (*str == '/') { - if (*(str + 1) == '/') { - str = execute_line_comment(str + 2, &line_cnt, &res, &comments_amount); + switch (*str) { + case '\"': + str = skip_to_double_quote(str + 1, &line_cnt); if (!str) { - free_res(&res); - return -1; + printf("Error | syntax error\n"); + return 0; } - } - if (*(str + 1) == '*') { - str = execute_multiline_comment(str + 2, &line_cnt, &res, &comments_amount); + break; + case '\'': + str = skip_to_single_quote(str + 1, &line_cnt); if (!str) { - free_res(&res); - return -1; + printf("Error | syntax error\n"); + return 0; + } + break; + case '\n': + line_cnt++; + str++; + break; + case '/': + if (*(str + 1) == '/') { + str = execute_line_comment(str + 2, &line_cnt, &res, &comments_amount); + if (!str) { + free_res(&res); + return -1; + } + } + if (*(str + 1) == '*') { + str = execute_multiline_comment(str + 2, &line_cnt, &res, &comments_amount); + if (!str) { + free_res(&res); + return -1; + } } - } + break; + default: + str++; + break; } - str++; } print_res(res, &comments_amount); free_res(&res); + return 0; } int parse_comments_from_file(const char *filename) { @@ -244,7 +253,7 @@ int parse_comments_from_file(const char *filename) { // file mapping closing if (munmap((void*)input, stat_buf.st_size)) - printf("Error | failed to unmap %s", filename); + printf("Error | failed to unmap %s\n", filename); return 0; } diff --git a/testing/Testing/Temporary/CTestCostData.txt b/testing/Testing/Temporary/CTestCostData.txt deleted file mode 100644 index ed97d53..0000000 --- a/testing/Testing/Temporary/CTestCostData.txt +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/testing/Testing/Temporary/LastTest.log b/testing/Testing/Temporary/LastTest.log deleted file mode 100644 index cfff5d7..0000000 --- a/testing/Testing/Temporary/LastTest.log +++ /dev/null @@ -1,3 +0,0 @@ -Start testing: Mar 15 16:37 MSK ----------------------------------------------------------- -End testing: Mar 15 16:37 MSK diff --git a/testing/console_input/answers/1.txt b/testing/console_input/answers/1.txt deleted file mode 100644 index 3b18e51..0000000 --- a/testing/console_input/answers/1.txt +++ /dev/null @@ -1 +0,0 @@ -hello world diff --git a/testing/console_input/answers/2.txt b/testing/console_input/answers/2.txt deleted file mode 100644 index 7d03278..0000000 --- a/testing/console_input/answers/2.txt +++ /dev/null @@ -1,3 +0,0 @@ -here -we -go again diff --git a/testing/console_input/answers/3.txt b/testing/console_input/answers/3.txt deleted file mode 100644 index 8179f38..0000000 --- a/testing/console_input/answers/3.txt +++ /dev/null @@ -1,26 +0,0 @@ - std::string test_filename = "../testing/easytests/logic/" + std::to_string(i) + ".txt"; - std::string answer_filename = "../testing/easyanswers/logic/" + std::to_string(i) + ".txt"; - std::fstream is(answer_filename); - ASSERT_TRUE(is.is_open()); - std::string answer_str; - char sym = '\0'; - while (is.get(sym)) - answer_str += sym; - is.close(); - - int fd[2]; - pipe(fd); - pid_t pid_fork = fork(); - int status = 0; - - if (!pid_fork) { - // Дочерний процесс - close(fd[0]); - dup2(fd[1], STDOUT_FILENO); - - std::string res; - execl("program", "program", test_filename.c_str(), NULL); - - close(fd[1]); - exit(0); - } diff --git a/testing/console_input/answers/4.txt b/testing/console_input/answers/4.txt deleted file mode 100644 index 78d2957..0000000 --- a/testing/console_input/answers/4.txt +++ /dev/null @@ -1,49 +0,0 @@ -// -// Created by denactive on 12.03.2021. -// -#ifndef PROJECT_HW_1_H -#define PROJECT_HW_1_H - -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DEBUG 0 -#define BUFFER_SIZE 1024 - -enum { - single, - multiline -}; - -typedef struct { - char* beg; - char* end; - size_t line; - unsigned int type; -} comment; - -int parse_comments(char* input); -int parse_comments_from_file(const char *filename); -int parse_comments_from_console(); - -char* skip_to_single_quote(char *str, size_t *line_cnt); -char* skip_to_double_quote(char *str, size_t *line_cnt); -char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); -char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); - -int res_exp(comment **res, size_t *comments_amount); -int free_res(comment **res); - -char* console_input(); -char* file_input(const char *filename, struct stat* stat_buf); -void print_res(const comment *res, size_t *comments_amount); -void print_comment(const comment* c); - -#endif //PROJECT_HW_1_H diff --git a/testing/console_input/cases/1.txt b/testing/console_input/cases/1.txt deleted file mode 100644 index 3b18e51..0000000 --- a/testing/console_input/cases/1.txt +++ /dev/null @@ -1 +0,0 @@ -hello world diff --git a/testing/console_input/cases/2.txt b/testing/console_input/cases/2.txt deleted file mode 100644 index 7d03278..0000000 --- a/testing/console_input/cases/2.txt +++ /dev/null @@ -1,3 +0,0 @@ -here -we -go again diff --git a/testing/console_input/cases/3.txt b/testing/console_input/cases/3.txt deleted file mode 100644 index 8179f38..0000000 --- a/testing/console_input/cases/3.txt +++ /dev/null @@ -1,26 +0,0 @@ - std::string test_filename = "../testing/easytests/logic/" + std::to_string(i) + ".txt"; - std::string answer_filename = "../testing/easyanswers/logic/" + std::to_string(i) + ".txt"; - std::fstream is(answer_filename); - ASSERT_TRUE(is.is_open()); - std::string answer_str; - char sym = '\0'; - while (is.get(sym)) - answer_str += sym; - is.close(); - - int fd[2]; - pipe(fd); - pid_t pid_fork = fork(); - int status = 0; - - if (!pid_fork) { - // Дочерний процесс - close(fd[0]); - dup2(fd[1], STDOUT_FILENO); - - std::string res; - execl("program", "program", test_filename.c_str(), NULL); - - close(fd[1]); - exit(0); - } diff --git a/testing/console_input/cases/4.txt b/testing/console_input/cases/4.txt deleted file mode 100644 index 78d2957..0000000 --- a/testing/console_input/cases/4.txt +++ /dev/null @@ -1,49 +0,0 @@ -// -// Created by denactive on 12.03.2021. -// -#ifndef PROJECT_HW_1_H -#define PROJECT_HW_1_H - -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DEBUG 0 -#define BUFFER_SIZE 1024 - -enum { - single, - multiline -}; - -typedef struct { - char* beg; - char* end; - size_t line; - unsigned int type; -} comment; - -int parse_comments(char* input); -int parse_comments_from_file(const char *filename); -int parse_comments_from_console(); - -char* skip_to_single_quote(char *str, size_t *line_cnt); -char* skip_to_double_quote(char *str, size_t *line_cnt); -char* execute_line_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); -char* execute_multiline_comment(char *str, size_t *line_cnt, comment **res, size_t *comments_amount); - -int res_exp(comment **res, size_t *comments_amount); -int free_res(comment **res); - -char* console_input(); -char* file_input(const char *filename, struct stat* stat_buf); -void print_res(const comment *res, size_t *comments_amount); -void print_comment(const comment* c); - -#endif //PROJECT_HW_1_H diff --git a/testing/logic/answers/12.txt b/testing/logic/answers/12.txt index 9829956..e07f9b5 100644 --- a/testing/logic/answers/12.txt +++ b/testing/logic/answers/12.txt @@ -12,5 +12,5 @@ line-3 line-6 ----------------- [4]: line: 9; type: single-line; -line-8 +line-9 ================= diff --git a/testing/logic/answers/14.txt b/testing/logic/answers/14.txt index c4f0a17..a5284bc 100644 --- a/testing/logic/answers/14.txt +++ b/testing/logic/answers/14.txt @@ -1 +1 @@ -Error | syntax error \ No newline at end of file +Error | syntax error diff --git a/testing/logic/answers/16.txt b/testing/logic/answers/16.txt index c4f0a17..a5284bc 100644 --- a/testing/logic/answers/16.txt +++ b/testing/logic/answers/16.txt @@ -1 +1 @@ -Error | syntax error \ No newline at end of file +Error | syntax error diff --git a/testing/logic/cases/12.txt b/testing/logic/cases/12.txt index 3890dce..07664ca 100644 --- a/testing/logic/cases/12.txt +++ b/testing/logic/cases/12.txt @@ -6,4 +6,4 @@ //line-6 -//line-8 +//line-9 diff --git a/testing/tests.cpp b/testing/tests.cpp index e67d4fd..84d5615 100644 --- a/testing/tests.cpp +++ b/testing/tests.cpp @@ -56,9 +56,7 @@ TEST(LogicTest, Main) { sz = read(fd[0], buf, 20 * BUFFER_SIZE); close(fd[0]); - /*if (sz > 0) { - write(STDOUT_FILENO, buf, sz); - }*/ + ASSERT_GT(sz, 0); waitpid(pid_fork, &status, 0); EXPECT_STREQ(buf, answer_str.c_str()); @@ -98,7 +96,7 @@ TEST(ErrorTest, BadFile) { TEST(ErrorTest, SingleQuotesSkipping) { const char invalid_line [] = "' here we can see an opening quote, but no closing one"; - std::cout << "Error test | no closing single quote in a file" << std::endl; + std::cout << "[Error test] | no closing single quote in a file" << std::endl; size_t cnt = 1; char* res = skip_to_single_quote(const_cast(&invalid_line[1]), &cnt); @@ -108,7 +106,7 @@ TEST(ErrorTest, SingleQuotesSkipping) { TEST(ErrorTest, SingleQuotesSkippingMultiline) { const char invalid_line [] = "\" here we can see\nan opening quote,\nbut no closing one"; - std::cout << "Error test | no closing single quote in a multiline file" << std::endl; + std::cout << "[Error test] | no closing single quote in a multiline file" << std::endl; size_t cnt = 1; char* res = skip_to_single_quote(const_cast(&invalid_line[1]), &cnt); @@ -118,7 +116,7 @@ TEST(ErrorTest, SingleQuotesSkippingMultiline) { TEST(ErrorTest, DoubleQuotesSkipping) { const char invalid_line [] = "' here we can see an opening quote, but no closing one"; - std::cout << "Error test | no closing double quote in a file" << std::endl; + std::cout << "[Error test] | no closing double quote in a file" << std::endl; size_t cnt = 1; char* res = skip_to_single_quote(const_cast(&invalid_line[1]), &cnt); @@ -139,7 +137,7 @@ TEST(ErrorTest, DoubleQuotesSkippingMultiline) { TEST(EdgeTest, SlashesAfterOpeningMultilineComment) { const char line [] = "/this is fucked up multiline\n/*/"; const char answer [] = "/this is fucked up multiline\n/"; - std::cout << "EdgeTest | /*/ comment /*/ situation" << std::endl; + std::cout << "[ EdgeTest ] | /*/ comment /*/ situation" << std::endl; size_t line_cnt = 1; size_t comments_cnt = 0; @@ -159,22 +157,44 @@ TEST(EdgeTest, SlashesAfterOpeningMultilineComment) { } TEST(EdgeTest, ShieldingSingleQuotes) { - const char line_const [] = "this is a \\'line'"; + const char line_const [] = "this is a \\'line'"; // this is a \'line' + const char answer [] = "this is a \\'line"; char* line = (char*)malloc(strlen(line_const) + 1); ASSERT_NE(line, nullptr); strcpy(line, line_const); line[strlen(line_const)] = '\0'; + std::cout << "[ EdgeTest ] | \\' situation" << std::endl; + + size_t line_cnt = 1; + char* after_closing_quote = skip_to_single_quote(line, &line_cnt); + + ASSERT_NE(after_closing_quote, nullptr); + EXPECT_EQ(line_cnt, 1); + std::string res_line; + for (char* i = line; i < after_closing_quote - 1; i++) + res_line += *i; + EXPECT_STREQ(res_line.c_str(), answer); + free(line); +} + +TEST(EdgeTest, ShieldingDoubleQuotes) { + const char line_const [] = "this is a \\'line\""; // this is a \'line' const char answer [] = "this is a \\'line"; - std::cout << "EdgeTest | \\' situation" << std::endl; + char* line = (char*)malloc(strlen(line_const) + 1); + ASSERT_NE(line, nullptr); + strcpy(line, line_const); + line[strlen(line_const)] = '\0'; + + std::cout << "[ EdgeTest ] | \\\" situation" << std::endl; size_t line_cnt = 1; - char* closing_quote = skip_to_single_quote(line, &line_cnt); + char* after_closing_quote = skip_to_double_quote(line, &line_cnt); - ASSERT_NE(closing_quote, nullptr); + ASSERT_NE(after_closing_quote, nullptr); EXPECT_EQ(line_cnt, 1); std::string res_line; - for (char* i = line; i < closing_quote; i++) + for (char* i = line; i < after_closing_quote - 1; i++) res_line += *i; EXPECT_STREQ(res_line.c_str(), answer); free(line); From 71367b0f8a6161dc3dbec89a2b0208f838d2747d Mon Sep 17 00:00:00 2001 From: Denactive Date: Tue, 16 Mar 2021 23:33:58 +0300 Subject: [PATCH 03/11] interactive coverage 1 --- .travis.yml | 11 +++++++++-- testing/ci-install-linux.sh | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 899c1ab..c1ddc86 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,14 @@ script: unit-testing: - ctest --output-on-failure - - gcovr -r .. - + #- gcovr -r .. + - lcov --directory . --capture --output-file coverage.info + - lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' --output-file coverage.info + - lcov --list coverage.info + - codecov + +after_success: + - bash <(curl -s https://codecov.io/bash) + safety: - valgrind --error-exitcode=1 --tool=memcheck --leak-check=full ./program ../testing/logic/cases/17.txt diff --git a/testing/ci-install-linux.sh b/testing/ci-install-linux.sh index 64d78ad..e68ba17 100644 --- a/testing/ci-install-linux.sh +++ b/testing/ci-install-linux.sh @@ -22,4 +22,5 @@ sudo apt-get install -y cppcheck #sudo apt install -y python3-pip sudo apt-get install python3-setuptools && sudo pip3 install git+https://github.com/gcovr/gcovr.git -#TODO: include linters +#lcov +sudo apt-get install lcov From d3529ba5de771e1dcc3164b464284fb70fcef318 Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 12:17:57 +0300 Subject: [PATCH 04/11] interactive coverage 2 --- .travis.yml | 10 +++++++++- CMakeLists.txt | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c1ddc86..364b535 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,10 +49,18 @@ unit-testing: - lcov --directory . --capture --output-file coverage.info - lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' --output-file coverage.info - lcov --list coverage.info - - codecov + #- codecov + - curl -s https://codecov.io/bash > .codecov + - chmod +x .codecov + - ./.codecov after_success: + # public: - bash <(curl -s https://codecov.io/bash) + + + #private + #- bash <(curl -s https://codecov.io/bash) -t your-repository-upload-token safety: - valgrind --error-exitcode=1 --tool=memcheck --leak-check=full ./program ../testing/logic/cases/17.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index fe061fa..7b151b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") set(CMAKE_CXX_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) +set(DCMAKE_CXX_FLAGS "--coverage") include_directories(project/include/) add_executable(program project/src/program.c project/src/hw-1.c) @@ -21,4 +22,4 @@ target_link_libraries(tests ${GTEST_LIBRARIES} -lpthread) add_test(program_and_functions_test ./tests) add_definitions(-fprofile-arcs -ftest-coverage) -target_link_libraries(tests -fprofile-arcs) \ No newline at end of file +target_link_libraries(tests -fprofile-arcs) From 4e05c431ce41408a444d91291b83fa025a84105f Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 12:24:08 +0300 Subject: [PATCH 05/11] interactive coverage 3 --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 364b535..4396de1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,10 +32,11 @@ install: # скрипт настройки среды и установки зависимостей: - source testing/ci-install-$TRAVIS_OS_NAME.sh -accuracy: +script: + + #accuracy: - cppcheck --error-exitcode=1 --suppress=missingIncludeSystem --enable=style,performance,portability,warning project/ -script: # скрипт сборки и тестирования проекта: - mkdir build - cd build @@ -43,7 +44,6 @@ script: # -DTARGET_CPU=$TARGET_CPU - cmake --build . -unit-testing: - ctest --output-on-failure #- gcovr -r .. - lcov --directory . --capture --output-file coverage.info @@ -62,5 +62,5 @@ after_success: #private #- bash <(curl -s https://codecov.io/bash) -t your-repository-upload-token -safety: +#safety: - valgrind --error-exitcode=1 --tool=memcheck --leak-check=full ./program ../testing/logic/cases/17.txt From 76dd882b0a8c2af1a2f2580ddc4187717a759b18 Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 12:31:55 +0300 Subject: [PATCH 06/11] interactive coverage 4 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4396de1..349cc3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ os: compiler: # ... и с помощью GCC, и Clang - - gcc + #- gcc - clang env: From 23b588e44748d3b50acbbbf4f57db7f2f8cfa63d Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 12:35:41 +0300 Subject: [PATCH 07/11] interactive coverage 5 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 349cc3a..a332e87 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,8 @@ os: compiler: # ... и с помощью GCC, и Clang - #- gcc - - clang + - gcc + #- clang env: # список переменных окружения, влияющих на матрицу сборки: From 829d4795145d08ad2e603344cf6f6b7de243ee91 Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 12:53:15 +0300 Subject: [PATCH 08/11] interactive coverage 6 --- CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b151b9..d58d386 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,9 @@ cmake_minimum_required(VERSION 3.16) project(hw1) set(CMAKE_C_STANDARD 11) -set(CMAKE_C_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") -set(CMAKE_CXX_FLAGS "-g -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") +set(CMAKE_C_FLAGS "-g -coverage -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") +set(CMAKE_CXX_FLAGS "-g -coverage -O0 -Wall -fprofile-arcs -ftest-coverage -fPIC") set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) -set(DCMAKE_CXX_FLAGS "--coverage") include_directories(project/include/) add_executable(program project/src/program.c project/src/hw-1.c) From 7323c5630ee715f65578b6b2f01670f33eb82f9b Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 21:54:29 +0300 Subject: [PATCH 09/11] mentor edition 1 --- .travis.yml | 4 +- project/include/hw-1.h | 11 ++--- project/src/hw-1.c | 104 ++++++++++++++++++++--------------------- project/src/program.c | 35 ++++++++++++-- 4 files changed, 88 insertions(+), 66 deletions(-) diff --git a/.travis.yml b/.travis.yml index a332e87..1b080be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ os: compiler: # ... и с помощью GCC, и Clang - gcc - #- clang + - clang env: # список переменных окружения, влияющих на матрицу сборки: @@ -40,7 +40,7 @@ script: # скрипт сборки и тестирования проекта: - mkdir build - cd build - - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_CONFIGURATION + - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_CONFIGURATION -DCMAKE_CXX_FLAGS="--coverage" # -DTARGET_CPU=$TARGET_CPU - cmake --build . diff --git a/project/include/hw-1.h b/project/include/hw-1.h index b19c9dd..3aa300b 100644 --- a/project/include/hw-1.h +++ b/project/include/hw-1.h @@ -14,6 +14,7 @@ #include #define BUFFER_SIZE 1024 +#define SYNTAX_ERROR 1 enum { single, @@ -27,21 +28,17 @@ typedef struct { unsigned int type; } comment; -int parse_comments(const char* input); -int parse_comments_from_file(const char *filename); -int parse_comments_from_console(); +int parse_comments(const char* str, size_t *line_cnt, comment **res, size_t *comments_amount); -char* skip_to_single_quote(const char *str, size_t *line_cnt); -char* skip_to_double_quote(const char *str, size_t *line_cnt); char* execute_line_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount); char* execute_multiline_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount); int res_exp(comment **res, size_t *comments_amount); int free_res(comment **res); +void print_res(const comment *res, size_t *comments_amount); +void print_comment(const comment* c); char* console_input(); char* file_input(const char *filename, struct stat* stat_buf); -void print_res(const comment *res, size_t *comments_amount); -void print_comment(const comment* c); #endif //PROJECT_HW_1_H \ No newline at end of file diff --git a/project/src/hw-1.c b/project/src/hw-1.c index b8aa54d..3a5bd8d 100644 --- a/project/src/hw-1.c +++ b/project/src/hw-1.c @@ -4,8 +4,13 @@ #include "hw-1.h" +char* skip_to_single_quote(const char *str, size_t *line_cnt); +char* skip_to_double_quote(const char *str, size_t *line_cnt); + // starts from a sym after ' and returns a sym after closing ' char* skip_to_single_quote(const char* str, size_t *line_cnt) { + if (!line_cnt || !str) + return NULL; while (*str != '\'') { if (*str == '\n') (*line_cnt)++; @@ -24,6 +29,8 @@ char* skip_to_single_quote(const char* str, size_t *line_cnt) { // starts from a sym after " and returns a sym after closing " char* skip_to_double_quote(const char* str, size_t *line_cnt) { + if (!line_cnt || !str) + return NULL; while (*str != '\"') { if (*str == '\n') (*line_cnt)++; @@ -41,6 +48,8 @@ char* skip_to_double_quote(const char* str, size_t *line_cnt) { } char* execute_line_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { + if (!line_cnt || !res || !comments_amount || !str) + return NULL; comment executed = {(char*)str, NULL, *line_cnt, single}; while (*str != '\n') { @@ -60,6 +69,8 @@ char* execute_line_comment(const char *str, size_t *line_cnt, comment **res, siz } char* execute_multiline_comment(const char *str, size_t *line_cnt, comment **res, size_t *comments_amount) { + if (!line_cnt || !res || !comments_amount || !str) + return NULL; // we are here after /* symbols. comment executed = {(char*)str, NULL, *line_cnt, single}; @@ -88,9 +99,16 @@ char* execute_multiline_comment(const char *str, size_t *line_cnt, comment **res } int res_exp(comment **res, size_t *comments_amount) { + if (!comments_amount) + return -1; + size_t size = 0; if (*comments_amount == 0) { size = sizeof(comment); + if (*res) { + free(*res); + *res = NULL; + } *res = (comment*)malloc(size); if (*res) { (*comments_amount)++; @@ -112,25 +130,32 @@ int res_exp(comment **res, size_t *comments_amount) { } int free_res(comment **res) { + if (!res) + return -1; free(*res); *res = NULL; return 0; } void print_res(const comment *res, size_t *comments_amount) { + size_t comments_amount_local = 0; + if (comments_amount) + comments_amount_local = *comments_amount; + printf("=================\n"); - if (!res) + if (!res || comments_amount_local == 0) printf("no comments found"); - for (size_t i = 0; i < *comments_amount; i++) { + for (size_t i = 0; i < comments_amount_local; i++) { printf("[%zu]: ", i); print_comment(&res[i]); - if (i < *comments_amount - 1) + if (i < comments_amount_local - 1) printf("\n-----------------\n"); } printf("\n=================\n"); } +// this function allocates memory! char *console_input() { char *input = (char*)malloc(BUFFER_SIZE * sizeof(char)); if (!input) @@ -141,11 +166,12 @@ char *console_input() { for (int i = 0; sym != EOF && i < BUFFER_SIZE; i++) { sym = getc(stdin); if (i == BUFFER_SIZE - 1) { - printf("Warning: Buffer overflow - only %d symbols were saved\n", BUFFER_SIZE - 1); + printf("\nWarning: Buffer overflow - only %d symbols were saved", BUFFER_SIZE - 1); break; } input[i] = sym; } + printf("\n"); //safety input[BUFFER_SIZE - 1] = '\0'; @@ -153,6 +179,10 @@ char *console_input() { } void print_comment(const comment* c) { + if (!c) { + printf("An empty comment\n"); + return; + } printf("line: %zu; type: ", c->line); if (c->type == single) printf("single-line;\n"); @@ -186,46 +216,49 @@ char* file_input(const char* filename, struct stat* stat_buf) { return (char*)content; } -// gtest ругается на const -int parse_comments(const char* input) { - const char *str = input; +int parse_comments(const char* str, size_t *line_cnt, comment **res, size_t *comments_amount) { + if (!line_cnt || !res || !comments_amount || !str) + return -1; - size_t line_cnt = 1; - comment *res = NULL; - size_t comments_amount = 0; + if (*res && *comments_amount == 0) { + free(*res); + *res = NULL; + } + if (*res == NULL) + *comments_amount = 0; while (*str != '\0' && *str != NULL && *str != EOF) { switch (*str) { case '\"': - str = skip_to_double_quote(str + 1, &line_cnt); + str = skip_to_double_quote(str + 1, line_cnt); if (!str) { printf("Error | syntax error\n"); - return 0; + return SYNTAX_ERROR; } break; case '\'': - str = skip_to_single_quote(str + 1, &line_cnt); + str = skip_to_single_quote(str + 1, line_cnt); if (!str) { printf("Error | syntax error\n"); - return 0; + return SYNTAX_ERROR; } break; case '\n': - line_cnt++; + (*line_cnt)++; str++; break; case '/': if (*(str + 1) == '/') { - str = execute_line_comment(str + 2, &line_cnt, &res, &comments_amount); + str = execute_line_comment(str + 2, line_cnt, res, comments_amount); if (!str) { - free_res(&res); + free_res(res); return -1; } } if (*(str + 1) == '*') { - str = execute_multiline_comment(str + 2, &line_cnt, &res, &comments_amount); + str = execute_multiline_comment(str + 2, line_cnt, res, comments_amount); if (!str) { - free_res(&res); + free_res(res); return -1; } } @@ -235,38 +268,5 @@ int parse_comments(const char* input) { break; } } - print_res(res, &comments_amount); - free_res(&res); - return 0; -} - -int parse_comments_from_file(const char *filename) { - struct stat stat_buf = {}; - char* input = file_input(filename, &stat_buf); - if (!input) { - printf("Error | Empty input\n"); - return -1; - } - - if(parse_comments(input)) - return -1; - - // file mapping closing - if (munmap((void*)input, stat_buf.st_size)) - printf("Error | failed to unmap %s\n", filename); - return 0; -} - -int parse_comments_from_console() { - char* input = console_input(); - if (!input) { - printf("Error | Empty input\n"); - return -1; - } - - if(parse_comments(input)) - return -1; - - free(input); return 0; } \ No newline at end of file diff --git a/project/src/program.c b/project/src/program.c index 16f8b23..5e7ce70 100644 --- a/project/src/program.c +++ b/project/src/program.c @@ -1,12 +1,37 @@ #include "hw-1.h" int main(int argc, const char** argv) { - if (argc == 1) { - if (parse_comments_from_console()) - return -1; + char* input = NULL; + struct stat stat_buf = {}; + + if (argc > 1) { + input = file_input(argv[1], &stat_buf); + } else { + input = console_input(); + } + + if (!input) { + printf("Error | Empty input\n"); + return -1; + } + + comment *res = NULL; + size_t comments_amount = 0; + size_t line_cnt = 1; + int exec_code = parse_comments(input, &line_cnt, &res, &comments_amount); + + if (exec_code == -1) + return -1; + + if (exec_code == 0) + print_res(res, &comments_amount); + + if (argc > 1) { + // file mapping closing + if (munmap((void*)input, stat_buf.st_size)) + printf("Error | failed to unmap %s\n", argv[1]); } else { - if (parse_comments_from_file(argv[1])) - return -1; + free(input); } return 0; } From 1bc5cf073ff97f05066be45b39df26b0313d4794 Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 21:59:40 +0300 Subject: [PATCH 10/11] clang excluded --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1b080be..d7179b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ os: compiler: # ... и с помощью GCC, и Clang - gcc - - clang + #- clang env: # список переменных окружения, влияющих на матрицу сборки: From 5dd60a5feb2e1b86355a02ef10af7067efc6c2b7 Mon Sep 17 00:00:00 2001 From: Denactive Date: Wed, 17 Mar 2021 22:21:57 +0300 Subject: [PATCH 11/11] valgrind .yml script fixed --- .travis.yml | 6 +++--- project/src/program.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d7179b5..42f47ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,9 @@ script: - chmod +x .codecov - ./.codecov + #safety: + - valgrind --error-exitcode=1 --tool=memcheck --leak-check=full ./program ../testing/logic/cases/17.txt + after_success: # public: - bash <(curl -s https://codecov.io/bash) @@ -61,6 +64,3 @@ after_success: #private #- bash <(curl -s https://codecov.io/bash) -t your-repository-upload-token - -#safety: - - valgrind --error-exitcode=1 --tool=memcheck --leak-check=full ./program ../testing/logic/cases/17.txt diff --git a/project/src/program.c b/project/src/program.c index 5e7ce70..68ace5b 100644 --- a/project/src/program.c +++ b/project/src/program.c @@ -33,5 +33,7 @@ int main(int argc, const char** argv) { } else { free(input); } + + free_res(&res); return 0; }