diff --git a/.github/workflows/c-ci.yml b/.github/workflows/c-ci.yml new file mode 100644 index 0000000..2ff9066 --- /dev/null +++ b/.github/workflows/c-ci.yml @@ -0,0 +1,28 @@ +name: C/C++ CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install GCC and tooling + run: | + sudo apt-get update + sudo apt-get install -y gcc build-essential + + - name: Build tests with address sanitizer + run: | + gcc -fsanitize=address -g 05_hw/stack.c 05_hw/tests.c -o tests.exe + + - name: Run tests + run: | + ./tests.exe \ No newline at end of file diff --git a/05_hw/benchmark.c b/05_hw/benchmark.c new file mode 100644 index 0000000..4ef62c8 --- /dev/null +++ b/05_hw/benchmark.c @@ -0,0 +1,62 @@ +#include +#include +#include "stack.h" + +#define N 1000000 + +void benchmark_push() { + Stack s; + initStack(&s); + + clock_t start = clock(); + + for (int i = 0; i < N; i++) { + push(&s, i); + } + + clock_t end = clock(); + + double elapsed_ms = ((double)(end - start) / CLOCKS_PER_SEC) * 1000.0; + + printf("Push benchmark:\n"); + printf(" Total pushes: %d\n", N); + printf(" Total time: %.3f ms\n", elapsed_ms); + printf(" Avg per push: %.6f microseconds\n\n", (elapsed_ms * 1000.0) / N); + + destroyStack(&s); +} + +// Функция для измерения pop() +void benchmark_pop() { + Stack s; + initStack(&s); + + // Заполняем стек заранее + for (int i = 0; i < N; i++) { + push(&s, i); + } + + clock_t start = clock(); + + for (int i = 0; i < N; i++) { + pop(&s); + } + + clock_t end = clock(); + + double elapsed_ms = ((double)(end - start) / CLOCKS_PER_SEC) * 1000.0; + + printf("Pop benchmark:\n"); + printf(" Total pops: %d\n", N); + printf(" Total time: %.3f ms\n", elapsed_ms); + printf(" Avg per pop: %.6f microseconds\n\n", (elapsed_ms * 1000.0) / N); +} + +int main() { + printf("=== Stack benchmark ===\n\n"); + + benchmark_push(); + benchmark_pop(); + + return 0; +} \ No newline at end of file diff --git a/05_hw/report.txt b/05_hw/report.txt new file mode 100644 index 0000000..b0bc597 --- /dev/null +++ b/05_hw/report.txt @@ -0,0 +1,17 @@ +Running: cppcheck --enable=all --template={"file":"{file}","line":{line},"column":{column},"severity":"{severity}","message":"{message}","id":"{id}"} c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\ + +Checking c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\stack.h ... +{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.h","line":1,"column":0,"severity":"information","message":"Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"}, + +Checking c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\stack.c ... +{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":1,"column":0,"severity":"information","message":"Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"}, +{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":2,"column":0,"severity":"information","message":"Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"}, + +{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":31,"column":5,"severity":"warning","message":"Returning 0 from pop() may be misleading: 0 is also valid data value.","id":"inconclusiveReturnValue"}, + +{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":16,"column":5,"severity":"style","message":"Parameter stack can be null pointer.","id":"nullPointerRedundantCheck"}, + +{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\stack.c","line":67,"column":5,"severity":"style","message":"Found printf without newline. This may cause performance issues.","id":"performancePrintfWithoutNewline"}, + +Checking c:\Users\User\Desktop\works\lecture-testing-task-main\05_hw\main.c ... +{"file":"c:\\Users\\User\\Desktop\\works\\lecture-testing-task-main\\05_hw\\main.c","line":3,"column":0,"severity":"information","message":"Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.","id":"missingIncludeSystem"}, \ No newline at end of file diff --git a/05_hw/stack.c b/05_hw/stack.c index 0964440..bea5d4e 100644 --- a/05_hw/stack.c +++ b/05_hw/stack.c @@ -1,10 +1,11 @@ #include #include - #include "stack.h" Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); + if (!newNode) return NULL; + newNode->data = data; newNode->next = NULL; return newNode; @@ -17,21 +18,33 @@ void initStack(Stack* stack) { void destroyStack(Stack* stack) { Node* current = stack->top; while (current != NULL) { - Node *tmp = current; + Node* tmp = current; current = current->next; - free(tmp); + free(tmp); } + stack->top = NULL; } void push(Stack* stack, int data) { Node* newNode = createNode(data); + if (!newNode) return; + newNode->next = stack->top; stack->top = newNode; } -void pop(Stack* stack) { +int pop(Stack* stack) { + if (stack->top == NULL) { + return 0; + } + Node* temp = stack->top; - stack->top = stack->top->next; + int value = temp->data; + + stack->top = temp->next; + free(temp); + + return value; } Node* searchByValue(Stack* stack, int value) { @@ -40,6 +53,7 @@ Node* searchByValue(Stack* stack, int value) { if (current->data == value) { return current; } + current = current->next; } return NULL; } @@ -47,6 +61,7 @@ Node* searchByValue(Stack* stack, int value) { Node* searchByIndex(Stack* stack, int index) { Node* current = stack->top; int count = 0; + while (current != NULL) { if (count == index) { return current; @@ -64,15 +79,15 @@ Node* getTop(Stack* stack) { 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; -} - +} \ No newline at end of file diff --git a/05_hw/stack.h b/05_hw/stack.h index ef0734e..86f3efa 100644 --- a/05_hw/stack.h +++ b/05_hw/stack.h @@ -23,7 +23,7 @@ void destroyStack(Stack *stack); void push(Stack* stack, int data); -void pop(Stack* stack); +int pop(Stack* stack); Node* searchByValue(Stack* stack, int value); @@ -37,4 +37,4 @@ bool isEmpty(Stack* stack); #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/05_hw/test.c b/05_hw/test.c new file mode 100644 index 0000000..2c5686e --- /dev/null +++ b/05_hw/test.c @@ -0,0 +1,117 @@ +#include +#include + +#include "stack.h" + +void test_initStack(void) { + Stack s; + initStack(&s); + CU_ASSERT_PTR_NULL(s.top); + destroyStack(&s); +} + +void test_push_and_getTop(void) { + Stack s; + initStack(&s); + + push(&s, 10); + CU_ASSERT_PTR_NOT_NULL(s.top); + CU_ASSERT_EQUAL(getTop(&s)->data, 10); + + push(&s, 20); + CU_ASSERT_EQUAL(getTop(&s)->data, 20); + + destroyStack(&s); +} + +void test_pop(void) { + Stack s; + initStack(&s); + + push(&s, 10); + push(&s, 20); + + pop(&s); + CU_ASSERT_EQUAL(getTop(&s)->data, 10); + + pop(&s); + CU_ASSERT_PTR_NULL(getTop(&s)); + + destroyStack(&s); +} + +void test_searchByValue(void) { + Stack s; + initStack(&s); + + push(&s, 5); + push(&s, 10); + push(&s, 15); + + CU_ASSERT_PTR_NOT_NULL(searchByValue(&s, 10)); + CU_ASSERT_PTR_NULL(searchByValue(&s, 999)); + + destroyStack(&s); +} + +void test_searchByIndex(void) { + Stack s; + initStack(&s); + + push(&s, 1); + push(&s, 2); + push(&s, 3); + + CU_ASSERT_EQUAL(searchByIndex(&s, 0)->data, 3); + CU_ASSERT_EQUAL(searchByIndex(&s, 1)->data, 2); + CU_ASSERT_EQUAL(searchByIndex(&s, 2)->data, 1); + CU_ASSERT_PTR_NULL(searchByIndex(&s, 10)); + + destroyStack(&s); +} + +void test_isEmpty(void) { + Stack s; + initStack(&s); + CU_ASSERT_TRUE(isEmpty(&s)); + + push(&s, 123); + CU_ASSERT_FALSE(isEmpty(&s)); + + destroyStack(&s); +} + +void test_destroyStack(void) { + Stack s; + initStack(&s); + + push(&s, 1); + push(&s, 2); + push(&s, 3); + + destroyStack(&s); + + CU_ASSERT_PTR_NULL(s.top); + + destroyStack(&s); +} + +int main() { + CU_initialize_registry(); + + CU_pSuite suite = CU_add_suite("Stack tests", 0, 0); + + CU_add_test(suite, "initStack", test_initStack); + CU_add_test(suite, "push & getTop", test_push_and_getTop); + CU_add_test(suite, "pop", test_pop); + CU_add_test(suite, "searchByValue", test_searchByValue); + CU_add_test(suite, "searchByIndex", test_searchByIndex); + CU_add_test(suite, "isEmpty", test_isEmpty); + CU_add_test(suite, "destroyStack", test_destroyStack); + + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + CU_cleanup_registry(); + + return 0; +} \ No newline at end of file