mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 04:18:55 +00:00
signals + tests
This commit is contained in:
parent
4b6cbba04f
commit
fa9cc3b8cc
4 changed files with 212 additions and 20 deletions
7
Makefile
7
Makefile
|
@ -1,5 +1,5 @@
|
|||
CC = gcc
|
||||
CFLAGS = -Wall -Wpedantic
|
||||
CFLAGS = -std=c99 -Wall -D_POSIX_C_SOURCE=199506L
|
||||
LD = gcc
|
||||
LDFLAGS = -lpthread -lrt
|
||||
|
||||
|
@ -7,16 +7,17 @@ BIN_NAME = cfloor
|
|||
|
||||
all: $(BIN_NAME)
|
||||
|
||||
test: obj/test.o obj/networking.o obj/linked.o obj/logging.o
|
||||
test: obj/test.o obj/networking.o obj/linked.o obj/logging.o obj/signals.o
|
||||
$(LD) $(LDFLAGS) -o $@ $^
|
||||
valgrind: CFLAGS += -static -g
|
||||
valgrind: clean test
|
||||
valgrind --leak-check=yes ./test
|
||||
|
||||
obj/test.o: src/networking.h src/linked.h src/logging.h
|
||||
obj/test.o: src/networking.h src/linked.h src/logging.h src/signals.h
|
||||
obj/networking.o: src/networking.h src/headers.h src/linked.h
|
||||
obj/linked.o: src/linked.h
|
||||
obj/loggin.o: src/logging.h
|
||||
obj/signals.o: src/signals.h
|
||||
|
||||
obj/%.o: src/%.c obj
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
|
102
src/signals.c
Normal file
102
src/signals.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "signals.h"
|
||||
|
||||
int signal_setup(int signo, void (*handler)(int signo)) {
|
||||
struct sigaction action;
|
||||
|
||||
action.sa_flags = 0;
|
||||
action.sa_handler = handler;
|
||||
|
||||
return sigaction(signo, &action, NULL);
|
||||
}
|
||||
|
||||
int signal_block_all() {
|
||||
sigset_t mask;
|
||||
sigfillset(&mask);
|
||||
return pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||
}
|
||||
|
||||
int signal_allow_all() {
|
||||
sigset_t mask;
|
||||
sigfillset(&mask);
|
||||
return pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
|
||||
}
|
||||
int signal_block(int signo) {
|
||||
sigset_t mask;
|
||||
sigaddset(&mask, signo);
|
||||
return pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||
}
|
||||
int signal_allow(int signo) {
|
||||
sigset_t mask;
|
||||
sigaddset(&mask, signo);
|
||||
return pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
|
||||
}
|
||||
|
||||
static void timerHandler(union sigval target) {
|
||||
((void (*)(void))(target.sival_ptr))();
|
||||
}
|
||||
timer_t timer_createThreadTimer(void (*handler)()) {
|
||||
struct sigevent sevp;
|
||||
sevp.sigev_notify = SIGEV_THREAD;
|
||||
sevp.sigev_notify_function = timerHandler;
|
||||
sevp.sigev_notify_attributes = NULL;
|
||||
sevp.sigev_value.sival_ptr = (void*) handler;
|
||||
|
||||
timer_t timer;
|
||||
|
||||
if (timer_create(CLOCK_BOOTTIME, &sevp, &timer) < 0) {
|
||||
timer = NULL;
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
timer_t timer_createSignalTimer(int signo) {
|
||||
struct sigevent sevp;
|
||||
sevp.sigev_notify = SIGEV_SIGNAL;
|
||||
sevp.sigev_signo = signo;
|
||||
|
||||
timer_t timer;
|
||||
|
||||
if (timer_create(CLOCK_BOOTTIME, &sevp, &timer) < 0) {
|
||||
timer = NULL;
|
||||
}
|
||||
|
||||
return timer;
|
||||
}
|
||||
int timer_destroy(timer_t timer) {
|
||||
return timer_delete(timer);
|
||||
}
|
||||
|
||||
int timer_startTimer(timer_t timer, unsigned long ms) {
|
||||
struct itimerspec time, old;
|
||||
|
||||
time.it_value.tv_sec = ms / 1000;
|
||||
time.it_value.tv_nsec = ((ms % 1000) * 1000000);
|
||||
time.it_interval.tv_sec = 0;
|
||||
time.it_interval.tv_nsec = 0;
|
||||
|
||||
return timer_settime(timer, 0, &time, &old);
|
||||
}
|
||||
int timer_startInterval(timer_t timer, unsigned long ms) {
|
||||
struct itimerspec time, old;
|
||||
|
||||
time.it_value.tv_sec = ms / 1000;
|
||||
time.it_value.tv_nsec = ((ms % 1000) * 1000000);
|
||||
time.it_interval.tv_sec = ms / 1000;
|
||||
time.it_interval.tv_nsec = ((ms % 1000) * 1000000);
|
||||
|
||||
return timer_settime(timer, 0, &time, &old);
|
||||
}
|
||||
int timer_stop(timer_t timer) {
|
||||
struct itimerspec time, old;
|
||||
|
||||
time.it_value.tv_sec = 0;
|
||||
time.it_value.tv_nsec = 0;
|
||||
time.it_interval.tv_sec = 0;
|
||||
time.it_interval.tv_nsec = 0;
|
||||
|
||||
return timer_settime(timer, 0, &time, &old);
|
||||
}
|
20
src/signals.h
Normal file
20
src/signals.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef SIGNALS_H
|
||||
#define SIGNALS_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
int signal_setup(int signum, void (*handler)(int signo));
|
||||
int signal_block_all();
|
||||
int signal_allow_all();
|
||||
int signal_block(int signo);
|
||||
int signal_allow(int signo);
|
||||
|
||||
timer_t timer_createThreadTimer(void (*handler)());
|
||||
timer_t timer_createSignalTimer(int signo);
|
||||
int timer_destroy(timer_t timer);
|
||||
|
||||
int timer_startTimer(timer_t timer, unsigned long ms);
|
||||
int timer_startInterval(timer_t timer, unsigned long ms);
|
||||
int timer_stop(timer_t timer);
|
||||
|
||||
#endif
|
103
src/test.c
103
src/test.c
|
@ -2,12 +2,20 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "networking.h"
|
||||
#include "linked.h"
|
||||
#include "logging.h"
|
||||
#include "signals.h"
|
||||
|
||||
bool global = true;
|
||||
bool overall = true;
|
||||
|
||||
void checkBool(bool ok, const char* check) {
|
||||
const char* result;
|
||||
|
@ -33,6 +41,10 @@ void checkNull(void* value, const char* check) {
|
|||
checkBool(value != NULL, check);
|
||||
}
|
||||
|
||||
void showError() {
|
||||
fprintf(stderr, "Error: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
void testLinkedList() {
|
||||
linkedList_t list = linked_create();
|
||||
|
||||
|
@ -85,20 +97,80 @@ void testLinkedList() {
|
|||
linked_destroy(&list);
|
||||
}
|
||||
|
||||
bool hasData(int fd) {
|
||||
int tmp = poll(&(struct pollfd){ .fd = fd, .events = POLLIN }, 1, 10);
|
||||
|
||||
return tmp == 1;
|
||||
}
|
||||
|
||||
bool handlerHasTriggered = false;
|
||||
void criticalHandler() {
|
||||
printf("This is the critical handler.\n");
|
||||
printBacktrace();
|
||||
}
|
||||
void testLogging() {
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) < 0) {
|
||||
showError();
|
||||
return;
|
||||
}
|
||||
|
||||
FILE* pipeWrite = fdopen(pipefd[1], "w");
|
||||
if (pipeWrite == NULL) {
|
||||
showError();
|
||||
return;
|
||||
}
|
||||
setbuf(pipeWrite, NULL);
|
||||
FILE* pipeRead = fdopen(pipefd[0], "r");
|
||||
if (pipeRead == NULL) {
|
||||
showError();
|
||||
return;
|
||||
}
|
||||
setbuf(pipeRead, NULL);
|
||||
|
||||
setLogging(pipeWrite, DEFAULT_LOGLEVEL, false);
|
||||
setLogging(stderr, DEFAULT_LOGLEVEL, true);
|
||||
|
||||
info("This info should not be displayed.");
|
||||
checkBool(!hasData(pipefd[0]), "no data read (info)");
|
||||
|
||||
warn("This warning should be displayed.");
|
||||
checkBool(hasData(pipefd[0]), "data read (warn)");
|
||||
fflush(pipeRead);
|
||||
|
||||
error("This error should be displayed.");
|
||||
checkBool(hasData(pipefd[0]), "data read (error)");
|
||||
fflush(pipeRead);
|
||||
|
||||
setCriticalHandler(&criticalHandler);
|
||||
|
||||
critical("This critical should be displayed.");
|
||||
checkBool(hasData(pipefd[0]), "data read (crititcal)");
|
||||
fflush(pipeRead);
|
||||
|
||||
fclose(pipeWrite);
|
||||
fclose(pipeRead);
|
||||
}
|
||||
|
||||
volatile int counter = 0;
|
||||
void timerThread() {
|
||||
counter++;
|
||||
}
|
||||
void testTimers() {
|
||||
timer_t timer = timer_createThreadTimer(&timerThread);
|
||||
if (timer == NULL) {
|
||||
showError();
|
||||
return;
|
||||
}
|
||||
if (timer_startInterval(timer, 10) < 0) {
|
||||
showError();
|
||||
return;
|
||||
}
|
||||
sleep(1);
|
||||
timer_stop(timer);
|
||||
timer_destroy(timer);
|
||||
|
||||
checkInt(counter, 100, "interval count");
|
||||
}
|
||||
|
||||
handler_t handlerGetter(struct metaData metaData, const char* host) {
|
||||
|
@ -115,24 +187,21 @@ void testNetworking() {
|
|||
});
|
||||
}
|
||||
|
||||
void test(const char* name, void (*testFunction)()) {
|
||||
printf("%s\n", name);
|
||||
printf("%.*s\n", (int) strlen(name),
|
||||
"===================================");
|
||||
testFunction();
|
||||
if (!global)
|
||||
overall = false;
|
||||
printf("%s: %s\n\n", name, global ? "OK" : "FAILED");
|
||||
global = true;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
bool overall = true;
|
||||
|
||||
printf("linked lists\n");
|
||||
printf("============\n\n");
|
||||
testLinkedList();
|
||||
if (!global)
|
||||
overall = false;
|
||||
printf("linked lists: %s\n\n", global ? "OK" : "FAILED");
|
||||
global = true;
|
||||
|
||||
printf("logging\n");
|
||||
printf("============\n\n");
|
||||
testLogging();
|
||||
if (!global)
|
||||
overall = false;
|
||||
printf("logging: %s\n\n", global ? "OK" : "FAILED");
|
||||
global = true;
|
||||
test("linked lists", &testLinkedList);
|
||||
test("logging", &testLogging);
|
||||
test("signals", &testTimers);
|
||||
|
||||
|
||||
printf("\nOverall: %s\n", overall ? "OK" : "FAILED");
|
||||
|
|
Loading…
Reference in a new issue