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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
build/
.vscode/
googletest/
benchmark/
20 changes: 17 additions & 3 deletions 05_hw/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
cmake_minimum_required(VERSION 3.10)
project(stack)

add_library(stack stack.c)
set(GOOGLETEST_VERSION 1.15.2)
enable_testing()
add_subdirectory(googletest)
include_directories(googletest/include)

add_executable(main main.c)
target_link_libraries(main stack)
add_library(stack stack.cpp)
add_executable(tests tests.cpp)
target_link_libraries(tests PRIVATE gtest stack)

set(BENCHMARK_ENABLE_TESTING OFF)
add_subdirectory(benchmark)
include_directories(benchmark/include)

add_executable(benchmark benchmark.cpp)
target_link_libraries(bench PRIVATE benchmark::benchmark stack)

add_executable(main main.cpp)
target_link_libraries(main stack)
61 changes: 61 additions & 0 deletions 05_hw/benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <benchmark/benchmark.h>
#include "stack.h"

class StackBench : public benchmark::Fixture
{
// Метод, который выполняется перед каждым бенчмарком
void SetUp(::benchmark::State& state)
{
stack = new Stack(); // Создаем новый экземпляр стека
}

// Метод, который выполняется после каждого бенчмарка
void TearDown(::benchmark::State& state)
{
delete stack; // Удаляем стек, освобождая память
}

public:
Stack* stack; // Указатель на стек, который будет использоваться в бенчмарках
};

// Определяем бенчмарк для измерения времени выполнения операции добавления элементов в стек
BENCHMARK_DEFINE_F(StackBench, PushBench)(benchmark::State& st)
{
for (auto _ : st) // Цикл для повторного выполнения теста
{
for(int i = 0; i < st.range(0); i++) // Внутренний цикл для добавления элементов в стек
push(stack, i); // Добавляем элемент i в стек
}
}

// Определяем бенчмарк для измерения времени выполнения операции удаления элементов из стека
BENCHMARK_DEFINE_F(StackBench, PopBench)(benchmark::State& st)
{
for(int i = 0; i < st.range(0); i++) // Сначала заполняем стек элементами
push(stack, i); // Добавляем элемент i в стек

for (auto _ : st) // Цикл для повторного выполнения теста
{
for(int i = 0; i < st.range(0); i++) // Внутренний цикл для удаления элементов из стека
pop(stack); // Удаляем верхний элемент из стека
}
}

// Регистрируем бенчмарки с различными аргументами (размером стека)
BENCHMARK_REGISTER_F(StackBench, PushBench)
->Arg(100) // Размер стека 100
->Arg(1000) // Размер стека 1000
->Arg(10000) // Размер стека 10000
->Arg(100000) // Размер стека 100000
->Arg(1000000); // Размер стека 1000000

// Регистрируем бенчмарк для удаления элементов с теми же аргументами
BENCHMARK_REGISTER_F(StackBench, PopBench)
->Arg(100)
->Arg(1000)
->Arg(10000)
->Arg(100000)
->Arg(1000000);

BENCHMARK_MAIN();
8 changes: 7 additions & 1 deletion 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 @@ -30,8 +31,13 @@ void push(Stack* stack, int data) {
}

void pop(Stack* stack) {
if (stack->top == NULL) {
printf("Stack is empty, cannot pop.\n");
return;
}
Node* temp = stack->top;
stack->top = stack->top->next;
free(temp);
}

Node* searchByValue(Stack* stack, int value) {
Expand All @@ -40,6 +46,7 @@ Node* searchByValue(Stack* stack, int value) {
if (current->data == value) {
return current;
}
current = current->next;
}
return NULL;
}
Expand Down Expand Up @@ -72,7 +79,6 @@ void traverseStack(Stack* stack) {
}

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

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

using namespace std;

class StackTest : public testing::Test
{
// Метод, который выполняется перед каждым тестом
void SetUp() override
{
stack = new Stack(); // Создаем новый экземпляр стека
}

// Метод, который выполняется после каждого теста
void TearDown() override {
delete stack; // Удаляем стек, освобождая память
}

public:
Stack* stack; // Указатель на стек, который будет использоваться в тестах
};

// Тест на проверку, что стек пустой
TEST_F(StackTest, isEmptyTest)
{
ASSERT_EQ(isEmpty(stack), true); // Проверяем, что isEmpty возвращает true
}

// Тест на получение верхнего элемента стека
TEST_F(StackTest, getTopTest)
{
ASSERT_EQ(getTop(stack), nullptr); // Проверяем, что верхний элемент равен nullptr (стек пуст)
}

// Тест на добавление элементов в стек
TEST_F(StackTest, PushTest)
{
push(stack, 3); // Добавляем элемент 3
push(stack, 5); // Добавляем элемент 5
ASSERT_EQ(getTop(stack)->data, 5); // Проверяем, что верхний элемент равен 5
}

// Тест на удаление элемента из стека
TEST_F(StackTest, PopTest)
{
push(stack, 3); // Добавляем элемент 3
pop(stack); // Удаляем верхний элемент
ASSERT_EQ(getTop(stack), nullptr); // Проверяем, что стек пустой (nullptr)
}

// Тест на попытку удалить элемент из пустого стека
TEST_F(StackTest, EmptyPopTest)
{
pop(stack); // Пытаемся удалить элемент из пустого стека
ASSERT_EQ(getTop(stack), nullptr); // Проверяем, что стек все еще пустой
}

// Тест на уничтожение стека
TEST_F(StackTest, destroyStackTest)
{
push(stack, 3); // Добавляем элементы в стек
push(stack, 5);
push(stack, 15);

destroyStack(stack); // Уничтожаем стек

ASSERT_EQ(getTop(stack), nullptr); // Проверяем, что стек пустой (nullptr)
}

// Тест на поиск элемента по значению
TEST_F(StackTest, searchByValueTest)
{
push(stack, 3);
push(stack, 5);
push(stack, 15);

ASSERT_EQ(searchByValue(stack, 5)->data, 5); // Проверяем, что найденный элемент равен 5
}

// Тест на поиск элемента по значению (не найдено)
TEST_F(StackTest, searchByValueInvTest)
{
ASSERT_EQ(searchByValue(stack, 5), nullptr); // Проверяем, что поиск возвращает nullptr (не найдено)
}

// Тест на поиск элемента по индексу
TEST_F(StackTest, searchByIndexTest)
{
push(stack, 3);
push(stack, 5);
push(stack, 15);

ASSERT_EQ(searchByIndex(stack, 1)->data, 5); // Проверяем, что элемент с индексом 1 равен 5
}

// Тест на поиск элемента по индексу (не найдено)
TEST_F(StackTest, searchByIndexInvTest)
{
ASSERT_EQ(searchByIndex(stack, 1), nullptr); // Проверяем, что поиск возвращает nullptr (не найдено)
}

// Тест на обход стека и вывод его элементов
TEST_F(StackTest, traverseStackTest) {
testing::internal::CaptureStdout(); // Захватываем стандартный вывод

push(stack, 3);
push(stack, 5);
push(stack, 15);

traverseStack(stack); // Обходим стек и выводим элементы

std::string str = testing::internal::GetCapturedStdout(); // Получаем захваченный вывод
EXPECT_EQ("Stack elements: 15 5 3 \n", str); // Проверяем правильность вывода
}

// Тест на обход пустого стека
TEST_F(StackTest, traverseStackEmptyTest) {
testing::internal::CaptureStdout(); // Захватываем стандартный вывод

traverseStack(stack); // Обходим пустой стек

std::string str = testing::internal::GetCapturedStdout(); // Получаем захваченный вывод
EXPECT_EQ("Stack elements: \n", str); // Проверяем правильность вывода для пустого стека
}

int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv); // Инициализируем Google Test

return RUN_ALL_TESTS(); // Запускаем все тесты и возвращаем результат
}