Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions 05_hw/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.tmp
*.log

/build/
/dist/

config.ini
secret.txt
11 changes: 11 additions & 0 deletions 05_hw/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
cmake_minimum_required(VERSION 3.10)
project(stack)

SET(GCC_COVERAGE_COMPILE_FLAGS "-g -O0 -coverage -fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS "-coverage -lgcov")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")

add_library(stack stack.c)

add_executable(main main.c)

target_link_libraries(main stack)
add_executable(tests tests.c stack.c)
target_link_libraries(tests stack gcov)
add_executable(benchmark benchmark.c stack.c)
target_link_libraries(benchmark stack gcov)
29 changes: 10 additions & 19 deletions 05_hw/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
# Домашнее задание

Данная работа над заданием была выполнена Дубковым Иваном, м23ИВТ-1
Файлы stack.c и stack.h являются простой реализацией стека, хранящего целые числа.
В коде есть баги и ошибки.

Необходимо привести код в порядок.

* Исправить ошибки;
* Покрыть код тестами;
* Проверить покрытие кода тестами (убедиться, что все функции и условия протестированы);
* Выбрать статический анализатор и запустить его (исправить ошибки, если будут);
* Запустить тесты с санитайзерами (исправить ошибки, если будут);
* Для базовых функций (push / pop) написать бенчмарки;
* Изучить возможности Github Actions и настроить CI для тестирования (*).

Во время рефакторинга разрешается изменять не только код функций, но и их c сигнатуры,
если это будет оправдано с точки зрения использования/тестирования этих функций.

Решение - Pull Request с исправлением. Желательно разбивать изменения на атомарные коммиты
с целью повышения качества ревью и ускорения получения фидбека.

(*) - необязательное задание.
В коде были исправлены баги и ошибки, а также проведен ряд работ:

* Код был покрыт тестами - при помощи файла tests.c;
* Проверить покрытие кода тестами (убедиться, что все функции и условия протестированы) - покрытие проверили при помощи модуля gcov;
* Был выбран статический анализатор Cppcheck, и при его помощи была проведена проверка на ошибки (существенных ошибок было не выявлено)
* Были запущены тесты с санитайзерами (Address Sanitiser) - при его помощи была обнаружена ошибка в работе кода, исправлено
* Для базовых функций (push / pop) были написаны бенчмарки - былва выявлена закономерность их поведения при различном количестве затраченных операций;

В качестве решения предоставляется пулл-реквест с протестированным репозиторием. Результаты тестов прилагаются в подробном отчете формата .docx
57 changes: 57 additions & 0 deletions 05_hw/benchmark.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "stack.h"

void benchmark_push(Stack* stack, int num_operations) {
clock_t start = clock();

for (int i = 0; i < num_operations; i++) {
push(stack, i);
}

clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("Pushed %d times in %f seconds\n", num_operations, time_spent);
}

void benchmark_pop(Stack* stack, int num_operations) {
clock_t start = clock();

for (int i = 0; i < num_operations; i++) {
pop(stack);
}

clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf("Pushed %d times in %f seconds\n", num_operations, time_spent);
}

int main() {
Stack stack;
initStack(&stack);
int iterations = 1000000;

printf("Benchmarking push:\n");
for (int i = 1000; i <= iterations; i *= 10) {
benchmark_push(&stack, i);

while (!isEmpty(&stack)) {
pop(&stack);
}
}

for (int i = 0; i < iterations; i++) {
push(&stack, i);
}
printf("\nBenchmarking pop:\n");

for (int i = 1000; i <= iterations; i *= 10) {
benchmark_pop(&stack, i);
for (int i = 0; i < iterations; i++) {
push(&stack, i);
}
}
destroyStack(&stack);
return 0;
}
16 changes: 12 additions & 4 deletions 05_hw/stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void destroyStack(Stack* stack) {
current = current->next;
free(tmp);
}
stack->top = NULL;
}

void push(Stack* stack, int data) {
Expand All @@ -31,7 +32,10 @@ void push(Stack* stack, int data) {

void pop(Stack* stack) {
Node* temp = stack->top;
stack->top = stack->top->next;
if (temp != NULL) {
stack->top = stack->top->next;
free(temp);
}
}

Node* searchByValue(Stack* stack, int value) {
Expand All @@ -40,10 +44,12 @@ Node* searchByValue(Stack* stack, int value) {
if (current->data == value) {
return current;
}
current = current->next;
}
return NULL;
}


Node* searchByIndex(Stack* stack, int index) {
Node* current = stack->top;
int count = 0;
Expand Down Expand Up @@ -72,7 +78,9 @@ void traverseStack(Stack* stack) {
}

bool isEmpty(Stack* stack) {
free(stack->top);
return stack->top == NULL;
bool temp = false;
if(stack->top == NULL){
temp = true;
}
return temp;
}

177 changes: 177 additions & 0 deletions 05_hw/tests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#include "stack.h"
#include <assert.h>
#include <stdio.h>

void test_createNode() {
Node* node = createNode(123);

assert(node != NULL);
assert(node->data == 123);
assert(node->next == NULL);

free(node);
printf("test_createNode passed.\n");
}

void test_initStack() {
Stack stack;
initStack(&stack);

assert(isEmpty(&stack) == true);
printf("test_initStack passed.\n");
}

void test_destroyStack() {
Stack stack;
initStack(&stack);

push(&stack, 4);
push(&stack, 5);

destroyStack(&stack);

assert(isEmpty(&stack) == true);
printf("test_destroyStack passed.\n");
}

void test_push() {
Stack stack;
initStack(&stack);

push(&stack, 3);
assert(getTop(&stack)->data == 3);

push(&stack, -2);
assert(getTop(&stack)->data == -2);

destroyStack(&stack);
printf("test_push passed.\n");
}

void test_pop() {
Stack stack;
initStack(&stack);

push(&stack, 1);
push(&stack, 2);

assert(getTop(&stack)->data == 2);
pop(&stack);
assert(getTop(&stack)->data == 1);
pop(&stack);

assert(isEmpty(&stack) == true);

destroyStack(&stack);
printf("test_pop passed.\n");
}

void test_searchByValue() {
Stack stack;
initStack(&stack);

push(&stack, 15);
push(&stack, 2);
push(&stack, -12);
push(&stack, 14);
push(&stack, 12);
push(&stack, 5);

Node* result = searchByValue(&stack, 12);
assert(result != NULL && result->data == 12);

result = searchByValue(&stack, -12);
assert(result != NULL && result->data == -12);

assert(searchByValue(&stack, 33) == NULL);

destroyStack(&stack);
printf("test_searchByValue passed.\n");
}

void test_searchByIndex() {
Stack stack;
initStack(&stack);

push(&stack, 1);
push(&stack, 2);
push(&stack, 3);
push(&stack, 4);
push(&stack, 5);

Node* result = searchByIndex(&stack, 0);
assert(result != NULL && result->data == 5);

result = searchByIndex(&stack, 2);
assert(result != NULL && result->data == 3);

assert(searchByIndex(&stack, 12) == NULL);

destroyStack(&stack);
printf("test_searchByIndex passed.\n");
}

void test_traverseStack() {
Stack stack;
initStack(&stack);

push(&stack, 11);
push(&stack, 12);
push(&stack, 13);

// Ожидаем, что будет выведено: 30 20 10
printf("Expected values: Stack elements: 13 12 11\n");
printf("Actual values: ");

traverseStack(&stack);

destroyStack(&stack);
printf("test_traverseStack passed.\n");
}

void test_isEmpty() {
Stack stack;
initStack(&stack);

assert(isEmpty(&stack) == true);

push(&stack, 42);
assert(isEmpty(&stack) == false);

pop(&stack);
assert(isEmpty(&stack) == true);
destroyStack(&stack);
printf("test_isEmpty passed.\n");
}


void test_getTop() {
Stack stack;
initStack(&stack);

push(&stack, 100);
assert(getTop(&stack)->data == 100);

push(&stack, 200);
assert(getTop(&stack)->data == 200);

destroyStack(&stack);
printf("test_getTop passed.\n");
}

int main() {
test_createNode();
test_initStack();
test_destroyStack();
test_push();
test_pop();
test_searchByValue();
test_searchByIndex();
test_traverseStack();
test_isEmpty();
test_getTop();

printf("All tests passed.\n");

return 0;
}
Binary file added 05_hw/ЛР1_Дубков_М23ИВТ-1.docx
Binary file not shown.