diff --git a/05_hw/CMakeLists.txt b/05_hw/CMakeLists.txt index 6f5e398..b549dba 100644 --- a/05_hw/CMakeLists.txt +++ b/05_hw/CMakeLists.txt @@ -1,7 +1,16 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.17) project(stack) +find_package(GTest REQUIRED) +find_package(benchmark REQUIRED) -add_library(stack stack.c) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -O3") -add_executable(main main.c) +add_library(stack stack.cpp) +add_executable(main main.cpp) target_link_libraries(main stack) + +add_executable(test_suite_stack test_suite_stack.cpp) +target_link_libraries(test_suite_stack stack GTest::GTest) + +add_executable(benchmark benchmark.cpp) +target_link_libraries(benchmark stack benchmark::benchmark) diff --git a/05_hw/benchmarks.cpp b/05_hw/benchmarks.cpp new file mode 100644 index 0000000..bacbd96 --- /dev/null +++ b/05_hw/benchmarks.cpp @@ -0,0 +1,41 @@ +#include +#include "stack.h" + +//Stress functions pop and push of class Stack by using Google Bench lib +// See more functions in user guide for lib at github https://github.com/google/benchmark/blob/main/docs/user_guide.md + +class StackBench : public benchmark::Fixture { +public: + void SetUp(::benchmark::State& state) { + stack = new Stack(); + } + + void TearDown(::benchmark::State& state) { + delete stack; + } + Stack* stack; +}; + + +BENCHMARK_DEFINE_F(StackBench, PushTest)(benchmark::State& st) { + for (auto _ : st) { + for(int i=0; i < st.range(0); i++){ + stack->push(i); + } + } +} + +BENCHMARK_DEFINE_F(StackBench, PopTest)(benchmark::State& st) { + for(int i=0; i < st.range(0); i++){ + stack->push(i); + } + for (auto _ : st) { + for(int i=0; i < st.range(0); i++){ + stack->pop(); + } + } +} +BENCHMARK_REGISTER_F(StackBench, PushTest)->Arg(100000)->Arg(200000)->Arg(400000)->Arg(80000)->Arg(1600000)->Arg(3200000)->MeasureProcessCPUTime(); +BENCHMARK_REGISTER_F(StackBench, PopTest)->Arg(100000)->Arg(200000)->Arg(400000)->Arg(80000)->Arg(1600000)->Arg(3200000)->MeasureProcessCPUTime(); + +BENCHMARK_MAIN(); \ No newline at end of file diff --git a/05_hw/main.c b/05_hw/main.c deleted file mode 100644 index fded814..0000000 --- a/05_hw/main.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "stack.h" - -#include - -int main() { - Stack stack; - initStack(&stack); - - push(&stack, 10); - push(&stack, 20); - push(&stack, 30); - - printf("After pushing elements:\n"); - traverseStack(&stack); - - pop(&stack); - - printf("After popping an element:\n"); - traverseStack(&stack); - - Node* searchResult = searchByValue(&stack, 20); - if (searchResult != NULL) { - printf("Element with value 20 found.\n"); - } else { - printf("Element with value 20 not found.\n"); - } - - Node* topElement = getTop(&stack); - if (topElement != NULL) { - printf("Top element: %d\n", topElement->data); - } - - return 0; -} - - diff --git a/05_hw/main.cpp b/05_hw/main.cpp new file mode 100644 index 0000000..6d09d3c --- /dev/null +++ b/05_hw/main.cpp @@ -0,0 +1,50 @@ +#include + +#include "stack.h" + +int main() { + Stack *stack = new Stack(); + int index = 0; + + stack->push(10); + stack->push(20); + stack->push(30); + std::cout << "After pushing elements:" << std::endl; + stack->traverseStack(); + + stack->pop(); + std::cout << "After popping element:" << std::endl; + stack->traverseStack(); + + Node* searchResult = stack->searchByValue(20); + if (searchResult != nullptr) { + std::cout << "Element with value 20 found." << std::endl; + } else { + std::cout << "Element with value 20 not found." << std::endl; + } + + Node* searchResult2 = stack->searchByValue(50); + if (searchResult2 != nullptr) { + std::cout << "Element with value 50 found." << std::endl; + } else { + std::cout << "Element with value 50 not found." << std::endl; + } + + std::cin >> "Enter the index to search for ..." >> index >> std::endl; + Node* searchIndex = stack->searchByIndex(index); + if (searchIndex != nullptr) { + std::cout << "Element with index " << index << " found. The value is: " << searchIndex->data << std::endl; + } else { + std::cout << "Element with index " << index << " not found." << std::endl; + } + + Node* topElement = stack->getTop(); + if (topElement != nullptr) { + std::cout << "Top element: " << topElement->data << std::endl; + } + + + + delete stack; + return 0; +} \ No newline at end of file diff --git a/05_hw/stack.c b/05_hw/stack.c deleted file mode 100644 index 0964440..0000000 --- a/05_hw/stack.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -#include "stack.h" - -Node* createNode(int data) { - Node* newNode = (Node*)malloc(sizeof(Node)); - newNode->data = data; - newNode->next = NULL; - return newNode; -} - -void initStack(Stack* stack) { - stack->top = NULL; -} - -void destroyStack(Stack* stack) { - Node* current = stack->top; - while (current != NULL) { - Node *tmp = current; - current = current->next; - free(tmp); - } -} - -void push(Stack* stack, int data) { - Node* newNode = createNode(data); - newNode->next = stack->top; - stack->top = newNode; -} - -void pop(Stack* stack) { - Node* temp = stack->top; - stack->top = stack->top->next; -} - -Node* searchByValue(Stack* stack, int value) { - Node* current = stack->top; - while (current != NULL) { - if (current->data == value) { - return current; - } - } - return NULL; -} - -Node* searchByIndex(Stack* stack, int index) { - Node* current = stack->top; - int count = 0; - while (current != NULL) { - if (count == index) { - return current; - } - count++; - current = current->next; - } - return NULL; -} - -Node* getTop(Stack* stack) { - return stack->top; -} - -void traverseStack(Stack* stack) { - Node* current = stack->top; - printf("Stack elements: "); - while (current != NULL) { - printf("%d ", current->data); - current = current->next; - } - printf("\n"); -} - -bool isEmpty(Stack* stack) { - free(stack->top); - return stack->top == NULL; -} - diff --git a/05_hw/stack.cpp b/05_hw/stack.cpp new file mode 100644 index 0000000..a6ca3c6 --- /dev/null +++ b/05_hw/stack.cpp @@ -0,0 +1,102 @@ +#include +#include "stack.h" + +void Stack::initStack() +{ + this->top = nullptr; +} +void Stack::destroyStack() +{ + Node *current = this->top; + while (current != nullptr) + { + Node *tmp = current; + current = current->next; + delete tmp; + } +} + +Stack::Stack(){ + initStack(); +} +Stack::~Stack(){ + destroyStack(); +} + +Node *Stack::createNode(int data) +{ + Node *newNode = new Node(); + newNode->data = data; + newNode->next = nullptr; + return newNode; +} + +bool Stack::isEmpty() +{ + return this->top == nullptr; +} + +void Stack::push(int data) +{ + Node *newNode = createNode(data); + newNode->next = this->top; + this->top = newNode; +} + +void Stack::pop() +{ + if (isEmpty()) return; + Node *temp = this->top; + this->top = this->top->next; + delete temp; +} + +Node *Stack::searchByValue(int value) +{ + Node *current = this->top; + while (current != nullptr) + { + if (current->data == value) + { + return current; + } + current = current->next; + } + return nullptr; +} + +Node *Stack::searchByIndex(int index) +{ + if (index < 0){return nullptr;} + Node *current = this->top; + for (int i = 0; current != nullptr; i++) + { + if (i == index) + { + return current; + } + current = current->next; + } + return nullptr; +} + +Node *Stack::getTop() +{ + return this->top; +} + +void Stack::traverseStack() +{ + if (isEmpty()) + { + std::cout << "Stack is empty! Please, add value to stack :( " << std::endl; + return; + } + Node *current = this->top; + std::cout << "Elements: "; + while (current != nullptr) + { + std::cout << " [" << current->data << "] "; + current = current->next; + } +} diff --git a/05_hw/stack.h b/05_hw/stack.h index ef0734e..940215f 100644 --- a/05_hw/stack.h +++ b/05_hw/stack.h @@ -1,40 +1,29 @@ #pragma once -#include +#ifndef STACK_H +#define STACK_H typedef struct Node { int data; - struct Node* next; + struct Node *next; } Node; -typedef struct Stack { - Node* top; -} Stack; - -#ifdef __cplusplus -extern "C" { -#endif - -Node* createNode(int data); - -void initStack(Stack* stack); - -void destroyStack(Stack *stack); - -void push(Stack* stack, int data); - -void pop(Stack* stack); - -Node* searchByValue(Stack* stack, int value); - -Node* searchByIndex(Stack* stack, int index); - -Node* getTop(Stack* stack); - -void traverseStack(Stack* stack); - -bool isEmpty(Stack* stack); - -#ifdef __cplusplus -} +//The Stack class stores data about the stack, as well as methods for working with the stack. +class Stack{ + private: + Node* top; + Node* createNode(int data); + void initStack(); + void destroyStack(); + public: + void push(int data); + void pop(); + Node *searchByValue(int value); + Node *searchByIndex(int index); + Node *getTop(); + void traverseStack(); + bool isEmpty(); + Stack(); + ~Stack(); +}; #endif diff --git a/05_hw/test_suite_stack.cpp b/05_hw/test_suite_stack.cpp new file mode 100644 index 0000000..33a64de --- /dev/null +++ b/05_hw/test_suite_stack.cpp @@ -0,0 +1,124 @@ +#include +#include "stack.h" + +class StackTest : public ::testing::Test { +protected: + void SetUp() override { + stack = new Stack(); + } + + void TearDown() override { + delete stack; + } + + Stack* stack; +}; + +TEST_F(StackTest, IsEmptySuccess) { + EXPECT_EQ(stack->isEmpty(),true); +} + +TEST_F(StackTest, IsEmptyFail) { + stack->push(100); + EXPECT_EQ(stack->isEmpty(),false); +} + +TEST_F(StackTest, GetTopEmpty) { + Node *result = stack->getTop(); + EXPECT_EQ(result, nullptr); +} + +TEST_F(StackTest, Push) { + stack->push(1); + Node *result = stack->getTop(); + EXPECT_EQ(result->data,1); +} + +TEST_F(StackTest, Pop) { + stack->push(2); + stack->pop(); + EXPECT_EQ(stack->isEmpty(),true); +} + +TEST_F(StackTest, PopFromEmptyStack) { + stack->pop(); + EXPECT_EQ(stack->isEmpty(),true); +} + +TEST_F(StackTest, GetTop) { + stack->push(100); + stack->push(75); + stack->push(50); + stack->push(25); + stack->pop(); + Node *result = stack->getTop(); + EXPECT_EQ(result->data,100); +} + +TEST_F(StackTest, SearchByValueSuccess) { + stack->push(100); + stack->push(75); + stack->push(50); + stack->push(25); + Node *result = stack->searchByValue(25); + EXPECT_EQ(result->data,25); +} + +TEST_F(StackTest, SearchByValueFail) { + stack->push(100); + stack->push(75); + stack->push(50); + stack->push(25); + Node *result = stack->searchByValue(10); + EXPECT_EQ(result,nullptr); +} + +TEST_F(StackTest, SearchByIndexSuccess) { + stack->push(100); + stack->push(75); + stack->push(50); + stack->push(25); + Node * result = stack->searchByIndex(0); + EXPECT_EQ(result->data,100); +} + +TEST_F(StackTest, SearchByIndexFail1) { + stack->push(100); + stack->push(75); + stack->push(50); + stack->push(25); + Node *result = stack->searchByIndex(5); + EXPECT_EQ(result,nullptr); +} + +TEST_F(StackTest, SearchByIndexFail2) { + stack->push(100); + stack->push(75); + stack->push(50); + stack->push(25); + Node *result = stack->searchByIndex(-1); + EXPECT_EQ(result,nullptr); +} + +TEST_F(StackTest, TraverseStack) { + testing::internal::CaptureStdout(); + stack->push(100); + stack->push(75); + stack->push(50); + stack->push(25); + stack->traverseStack(); + std::string captured_stdout = testing::internal::GetCapturedStdout(); + EXPECT_EQ("Elements: [100] [75] [50] [25] \n", captured_stdout); +} + +TEST_F(StackTest, TraverseStackEmpty) { + testing::internal::CaptureStdout(); + stack->traverseStack(); + std::string captured_stdout = testing::internal::GetCapturedStdout(); + EXPECT_EQ("Stack is empty! Please, add value to stack :( \n", captured_stdout); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file