all repos — tint2 @ a7ca1b739b798ebc82771f759d50b805074156eb

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

src/util/test.c (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <glib.h>

#include "colors.h"
#include "signals.h"
#include "test.h"

typedef struct TestListItem {
    Test *test;
    const char *name;
} TestListItem;

static GList *all_tests = NULL;

void register_test_(Test *test, const char *name)
{
    TestListItem *item = (TestListItem *)calloc(sizeof(TestListItem), 1);
    item->test = test;
    item->name = name;
    all_tests = g_list_append(all_tests, item);
}

static char *test_log_name_from_test_name(const char *test_name)
{
    char *output_name = g_strdup_printf("test_%s.log", test_name);
    char *result = strdup(output_name);
    g_free(output_name);
    return result;
}

static void redirect_test_output(const char *test_name)
{
    char *output_name = test_log_name_from_test_name(test_name);
    int fd = open(output_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    if (fd == -1)
        goto err;
    if (dup2(fd, STDOUT_FILENO) == -1)
        goto err;
    if (dup2(fd, STDERR_FILENO) == -1)
        goto err;

    close(fd);
    free(output_name);
    return;
err:
    fprintf(stderr, "tint2: Could not redirect test output to file name: %s\n", output_name);
    if (fd != -1)
        close(fd);
    free(output_name);
}

__attribute__((noreturn))
static void run_test_child(TestListItem *item)
{
    reset_signals();
    redirect_test_output(item->name);
    bool result = true;
    item->test(&result);
    exit(result ? EXIT_SUCCESS : EXIT_FAILURE);
}

static FILE *open_test_log(const char *test_name)
{
    char *output_name = test_log_name_from_test_name(test_name);
    FILE *log = fopen(output_name, "a");
    free(output_name);
    return log;
}

static Status run_test_parent(TestListItem *item, pid_t child)
{
    FILE *log = open_test_log(item->name);
    if (child == -1) {
        fprintf(log, "\n" "Test failed, fork failed\n");
        fclose(log);
        return FAILURE;
    }

    int child_status;
    pid_t ret_pid = waitpid(child, &child_status, 0);
    if (ret_pid != child) {
        fprintf(log, "\n" "Test failed, waitpid failed\n");
        fclose(log);
        return FAILURE;
    }
    if (WIFEXITED(child_status)) {
        int exit_status = WEXITSTATUS(child_status);
        if (exit_status == EXIT_SUCCESS) {
            fprintf(log, "\n" "Test succeeded.\n");
            fclose(log);
            return SUCCESS;
        } else {
            fprintf(log, "\n" "Test failed, exit status: %d.\n", exit_status);
            fclose(log);
            return FAILURE;
        }
    } else if (WIFSIGNALED(child_status)) {
        int signal = WTERMSIG(child_status);
        fprintf(log, "\n" "Test failed, child killed by signal: %d.\n", signal);
        fclose(log);
        return FAILURE;
    } else {
        fprintf(log, "\n" "Test failed, waitpid failed.\n");
        fclose(log);
        return FAILURE;
    }
}

static Status run_test(TestListItem *item)
{
    pid_t pid = fork();
    if (pid == 0)
        run_test_child(item);
    return run_test_parent(item, pid);
}

void run_all_tests()
{
    fprintf(stdout, BLUE "tint2: Running %d tests..." RESET "\n", g_list_length(all_tests));
    size_t count = 0, succeeded = 0, failed = 0;
    for (GList *l = all_tests; l; l = l->next) {
        TestListItem *item = (TestListItem *)l->data;
        Status status = run_test(item);
        count++;
        fprintf(stdout, BLUE "tint2: Test " YELLOW "%s" BLUE ": ", item->name);
        if (status == SUCCESS) {
            fprintf(stdout, GREEN "succeeded" RESET "\n");
            succeeded++;
        } else {
            fprintf(stdout, RED "failed" RESET "\n");
            failed++;
        }
    }
    if (failed == 0)
        fprintf(stdout, BLUE "tint2: " GREEN "all %lu tests succeeded." RESET "\n", count);
    else
        fprintf(stdout, BLUE "tint2: " RED "%lu" BLUE " out of %lu tests " RED "failed." RESET "\n", failed, count);
}

TEST(dummy) {
    int x = 2;
    int y = 2;
    ASSERT_EQUAL(x, y);
}

TEST(dummyBad) {
    int x = 2;
    int y = 3;
    ASSERT_EQUAL(x, y);
}