TestAllFiles.h revision 74835918
1/*
2 * Copyright (c) 2023, Oracle and/or its affiliates.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include <glib.h>
25
26#include <errno.h>
27#include <limits.h>
28#include <setjmp.h>
29#include <signal.h>
30#include <stdlib.h>
31#include <unistd.h>
32
33#include "config.h"
34
35#define DEFAULT_TIMEOUT 10 /* maximum seconds for each file */
36
37static sigjmp_buf jump_env;
38
39static void sigalrm (int sig)
40{
41    siglongjmp(jump_env, 1);
42}
43
44typedef int (*testfilefunc)(const gchar *filepath);
45
46/*
47 * Test all files in a given subdir of either the build or source directory
48 */
49static void
50TestAllFilesByType(GTestFileType file_type, gboolean compressed,
51                   const char *subdir, int expected, testfilefunc testfunc)
52{
53    const gchar *datadir_path, *filename;
54    GDir *datadir;
55    GError *err = NULL;
56    int timeout = DEFAULT_TIMEOUT;
57    char *timeout_env;
58
59    GPatternSpec *xpm_pattern = g_pattern_spec_new("*.xpm");
60#ifndef NO_ZPIPE
61    GPatternSpec *z_pattern = compressed ? g_pattern_spec_new("*.xpm.Z") : NULL;
62    GPatternSpec *gz_pattern = compressed ? g_pattern_spec_new("*.xpm.gz") : NULL;
63#endif
64
65    /* Allow override when debugging tests */
66    timeout_env = getenv("XPM_TEST_TIMEOUT");
67    if (timeout_env != NULL) {
68        int from_env = atoi(timeout_env);
69
70        if (from_env >= 0)
71            timeout = from_env;
72    }
73
74    datadir_path = g_test_get_filename(file_type, "pixmaps", subdir,
75                       (file_type == G_TEST_BUILT) ? "generated" : NULL, NULL);
76    g_assert_nonnull(datadir_path);
77    g_test_message("Reading files from %s", datadir_path);
78
79    datadir = g_dir_open(datadir_path, 0, &err);
80    g_assert_no_error(err);
81
82    errno = 0;
83    while ((filename = g_dir_read_name(datadir)) != NULL) {
84
85        if (!g_pattern_match_string(xpm_pattern, filename)) {
86#ifndef NO_ZPIPE
87                if (!compressed ||
88                    (!g_pattern_match_string(z_pattern, filename) &&
89                     !g_pattern_match_string(gz_pattern, filename)))
90#endif
91                {
92                    g_test_message("skipping \"%s\"", filename);
93                    continue;
94                }
95        }
96
97        /*
98         * Assumes the test function should complete in less than "timeout"
99         * seconds and fails if they don't, in order to catch runaway loops.
100         */
101        if (timeout > 0) {
102            struct sigaction sa = {
103                .sa_handler = sigalrm,
104                .sa_flags = SA_RESTART
105            };
106            sigemptyset (&sa.sa_mask);
107            sigaction(SIGALRM, &sa, NULL);
108        }
109
110        if (sigsetjmp(jump_env, 1) == 0) {
111            int status;
112            gchar *filepath;
113
114            filepath = g_build_filename(datadir_path, filename, NULL);
115
116            g_test_message("testing \"%s\", should return %d",
117                           filename, expected);
118            if (timeout > 0)
119                alarm(timeout);
120            status = testfunc(filepath);
121            g_assert_cmpint(status, ==, expected);
122
123            if (timeout > 0) {
124                status = alarm(0); /* cancel alarm */
125                g_test_message("%d seconds left on %d second timer",
126                               status, timeout);
127            }
128
129            g_free(filepath);
130        }
131        else {
132            g_test_message("timed out reading %s", filename);
133            g_assertion_message(G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC,
134                                "test timed out");
135        }
136
137        errno = 0;
138    }
139    // g_assert_cmpint(errno, ==, 0); - not sure why this sometimes fails
140
141    g_dir_close(datadir);
142}
143
144/*
145 * Test all non-compressed files in a given subdir
146 */
147static void
148TestAllNormalFiles(const char *subdir, int expected, testfilefunc testfunc)
149{
150    TestAllFilesByType(G_TEST_DIST, FALSE, subdir, expected, testfunc);
151}
152
153/*
154 * Test all compressed files in a given subdir
155 */
156static void
157TestAllCompressedFiles(const char *subdir, int expected, testfilefunc testfunc)
158{
159#ifdef NO_ZPIPE
160    g_test_message("compression disabled, skipping compressed file tests");
161#else
162    TestAllFilesByType(G_TEST_BUILT, TRUE, subdir, expected, testfunc);
163#endif
164}
165