dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 96.4% 160 / 0 / 166
Functions: 100.0% 6 / 0 / 6
Branches: 50.0% 2 / 8 / 12

test/init.c
Line Branch Exec Source
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <limits.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include "test.h"
9 #include "editor.h"
10 #include "exec.h"
11 #include "terminal/color.h"
12 #include "terminal/terminal.h"
13 #include "trace.h"
14 #include "util/debug.h"
15 #include "util/fd.h"
16 #include "util/intern.h"
17 #include "util/log.h"
18 #include "util/path.h"
19 #include "util/xreadwrite.h"
20 #include "version.h"
21
22 1 static void test_process_sanity(TestContext *ctx)
23 {
24 // Note that if this fails, there'll only be (at best) an "aborted"
25 // message, since there's no stderr for test_fail() to use
26 1 ASSERT_TRUE(fd_is_valid(STDERR_FILENO));
27
28 1 ASSERT_NONNULL(freopen("/dev/null", "r", stdin));
29 1 ASSERT_NONNULL(freopen("/dev/null", "w", stdout));
30 1 }
31
32 1 static void test_posix_sanity(TestContext *ctx)
33 {
34 // This is not guaranteed by ISO C99, but it is required by POSIX
35 // and is relied upon by this codebase.
36 // See: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/limits.h.html#tag_14_26_03_06
37 1 ASSERT_EQ(CHAR_BIT, 8);
38 1 ASSERT_TRUE(sizeof(int) >= 4);
39 1 ASSERT_TRUE(BITSIZE(int) >= 32);
40 1 ASSERT_EQ(SCHAR_MIN, -128);
41 1 ASSERT_EQ(SCHAR_MAX, 127);
42 1 ASSERT_EQ(UCHAR_MAX, 255);
43 1 ASSERT_TRUE(UINT_MAX >= 0xFFFFFFFFu);
44 1 ASSERT_TRUE(INT_MAX >= 0x7FFFFFFF);
45 1 ASSERT_TRUE(INT_MIN <= -0x80000000);
46
47 IGNORE_WARNING("-Wformat-truncation")
48
49 // Some snprintf(3) implementations historically returned -1 in case of
50 // truncation. C99 and POSIX 2001 both require that it return the full
51 // size of the formatted string, as if there had been enough space.
52 1 char buf[8] = "........";
53 1 ASSERT_EQ(snprintf(buf, 8, "0123456789"), 10);
54 1 ASSERT_EQ(buf[7], '\0');
55 1 EXPECT_STREQ(buf, "0123456");
56
57 // C99 and POSIX 2001 also require the same behavior as above when the
58 // size argument is 0 (and allow the buffer argument to be NULL).
59 1 ASSERT_EQ(snprintf(NULL, 0, "987654321"), 9);
60
61 UNIGNORE_WARNINGS
62 1 }
63
64 // Note: this must be ordered before a successful call to log_open()
65 // (i.e. the one in test_init()), so as not to trigger the BUG_ON()
66 // assertions at the top of log_open()
67 1 static void test_log_open_errors(TestContext *ctx)
68 {
69 1 const LogLevel none = LOG_LEVEL_NONE;
70 1 const LogLevel info = LOG_LEVEL_INFO;
71 1 errno = 0;
72 1 ASSERT_EQ(log_open("/dev/null", none, 0), none);
73 1 EXPECT_EQ(errno, 0);
74 1 ASSERT_EQ(log_open("build/test/non-existent-dir/x", info, 0), none);
75 1 EXPECT_EQ(errno, ENOENT);
76
77
1/2
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 13 not taken.
1 if (access("/dev/full", W_OK) == 0) {
78 1 errno = 0;
79 1 ASSERT_EQ(log_open("/dev/full", info, 0), none);
80 1 EXPECT_EQ(errno, ENOSPC);
81 }
82
83 1 int tty = xopen("/dev/tty", O_WRONLY | O_CLOEXEC | O_NOCTTY, 0);
84
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 23 taken 1 time.
1 if (tty >= 0) {
85 ASSERT_TRUE(tty > STDERR_FILENO);
86 ASSERT_TRUE(is_controlling_tty(tty));
87 EXPECT_EQ(xclose(tty), 0);
88 errno = 0;
89 ASSERT_EQ(log_open("/dev/tty", info, 0), none);
90 EXPECT_EQ(errno, EINVAL);
91 }
92 1 }
93
94 1 static void test_trace_flags_from_str(TestContext *ctx)
95 {
96 1 if (!TRACE_LOGGING_ENABLED) {
97 return;
98 }
99
100 1 EXPECT_EQ(trace_flags_from_str("output"), TRACEFLAG_OUTPUT);
101 1 EXPECT_EQ(trace_flags_from_str(",x,, ,output,,"), TRACEFLAG_OUTPUT);
102 1 EXPECT_EQ(trace_flags_from_str("command,input"), TRACEFLAG_COMMAND | TRACEFLAG_INPUT);
103 1 EXPECT_EQ(trace_flags_from_str("command,inpu"), TRACEFLAG_COMMAND);
104 1 EXPECT_EQ(trace_flags_from_str(""), 0);
105 1 EXPECT_EQ(trace_flags_from_str(","), 0);
106 1 EXPECT_EQ(trace_flags_from_str("a"), 0);
107 }
108
109 1 static void test_init(TestContext *ctx)
110 {
111 1 char *home = path_absolute("build/test/HOME");
112 1 char *dte_home = path_absolute("build/test/DTE_HOME");
113 1 ASSERT_NONNULL(home);
114 1 ASSERT_NONNULL(dte_home);
115
116 1 ASSERT_TRUE(mkdir(home, 0755) == 0 || errno == EEXIST);
117 1 ASSERT_TRUE(mkdir(dte_home, 0755) == 0 || errno == EEXIST);
118
119 1 ASSERT_EQ(setenv("HOME", home, 1), 0);
120 1 ASSERT_EQ(setenv("DTE_HOME", dte_home, 1), 0);
121 1 ASSERT_EQ(setenv("XDG_RUNTIME_DIR", dte_home, 1), 0);
122 1 ASSERT_EQ(setenv("TZ", "UTC", 1), 0);
123 1 ASSERT_EQ(unsetenv("TERM"), 0);
124 1 ASSERT_EQ(unsetenv("COLORTERM"), 0);
125
126 1 EXPECT_FALSE(log_level_enabled(LOG_LEVEL_CRITICAL));
127 1 EXPECT_FALSE(log_level_enabled(LOG_LEVEL_ERROR));
128 1 EXPECT_FALSE(log_level_enabled(LOG_LEVEL_WARNING));
129 1 EXPECT_FALSE(log_level_enabled(LOG_LEVEL_NOTICE));
130 1 EXPECT_FALSE(log_level_enabled(LOG_LEVEL_INFO));
131 1 EXPECT_FALSE(log_level_enabled(LOG_LEVEL_DEBUG));
132 1 EXPECT_FALSE(log_level_enabled(LOG_LEVEL_TRACE));
133 1 EXPECT_FALSE(log_level_debug_enabled());
134
135 1 const LogLevel max_lvl = log_level_max();
136 1 const LogLevel req_lvl = LOG_LEVEL_TRACE;
137 1 ASSERT_EQ(log_open("build/test/log.txt", req_lvl, 0), max_lvl);
138 1 EXPECT_TRUE(log_level_enabled(LOG_LEVEL_CRITICAL));
139 1 EXPECT_TRUE(log_level_enabled(LOG_LEVEL_ERROR));
140 1 EXPECT_TRUE(log_level_enabled(LOG_LEVEL_WARNING));
141 1 EXPECT_TRUE(log_level_enabled(LOG_LEVEL_NOTICE));
142 1 EXPECT_TRUE(log_level_enabled(LOG_LEVEL_INFO));
143 1 EXPECT_EQ(log_level_enabled(LOG_LEVEL_DEBUG), DEBUG_LOGGING_ENABLED);
144 1 EXPECT_EQ(log_level_enabled(LOG_LEVEL_TRACE), TRACE_LOGGING_ENABLED);
145 1 EXPECT_EQ(log_level_debug_enabled(), DEBUG_LOGGING_ENABLED);
146 1 EXPECT_FALSE(log_trace_enabled(TRACEFLAGS_ALL));
147
148 1 const char *fn = __func__;
149 1 LOG_CRITICAL("%s: testing LOG_CRITICAL()", fn);
150 1 LOG_ERROR("%s: testing LOG_ERROR()", fn);
151 1 LOG_WARNING("%s: testing LOG_WARNING()", fn);
152 1 LOG_NOTICE("%s: testing LOG_NOTICE()", fn);
153 1 LOG_INFO("%s: testing LOG_INFO()", fn);
154 1 LOG_DEBUG("%s: testing LOG_DEBUG()", fn);
155 1 LOG_TRACE(TRACEFLAGS_ALL, "should always fail; trace flags not yet set");
156 1 log_write(LOG_LEVEL_TRACE, STRN("as above"));
157 1 log_write(LOG_LEVEL_INFO, STRN("testing log_write()"));
158 1 errno = EINVAL;
159 1 EXPECT_EQ(LOG_ERRNO("testing LOG_ERRNO()"), EINVAL);
160
161 1 const TraceLoggingFlags all = TRACEFLAGS_ALL;
162 1 set_trace_logging_flags(all);
163 1 EXPECT_EQ(log_trace_enabled(all), TRACE_LOGGING_ENABLED);
164 1 LOG_TRACE(all, "%s: testing LOG_TRACE()", fn);
165 1 TRACE_CMD("%s: testing TRACE_CMD()", fn);
166 1 TRACE_INPUT("%s: testing TRACE_INPUT()", fn);
167 1 TRACE_OUTPUT("%s: testing TRACE_OUTPUT()", fn);
168
169 1 EditorState *e = init_editor_state(home, dte_home);
170 1 ASSERT_NONNULL(e);
171 1 ASSERT_NONNULL(e->user_config_dir);
172 1 ASSERT_NONNULL(e->home_dir.data);
173 1 EXPECT_STREQ(e->user_config_dir, dte_home);
174 1 EXPECT_STRVIEW_EQ_CSTRING(e->home_dir, home);
175 1 EXPECT_PTREQ(e->user_config_dir, str_intern(dte_home));
176 1 EXPECT_PTREQ(e->home_dir.data, str_intern(home));
177 1 free(home);
178 1 free(dte_home);
179 1 e->options.lock_files = false;
180 1 ctx->userdata = e;
181
182 1 Terminal *term = &e->terminal;
183 1 EXPECT_EQ(term->features, 0);
184 1 EXPECT_EQ(term->width, 0);
185 1 EXPECT_EQ(term->height, 0);
186 1 term_init(term, "decansi", NULL);
187 1 EXPECT_EQ(term->features, TFLAG_8_COLOR);
188 1 EXPECT_EQ(term->width, 80);
189 1 EXPECT_EQ(term->height, 24);
190
191 1 const char *ver = getenv("DTE_VERSION");
192 1 EXPECT_NONNULL(ver);
193 1 EXPECT_STREQ(ver, VERSION);
194
195 1 EXPECT_EQ(need_term_reset_on_fatal_error, 0);
196 1 }
197
198 1 static void test_deinit(TestContext *ctx)
199 {
200 // Make sure default Terminal state wasn't changed
201 1 EditorState *e = ctx->userdata;
202 1 const Terminal *term = &e->terminal;
203 1 EXPECT_EQ(term->width, 80);
204 1 EXPECT_EQ(term->height, 24);
205 1 EXPECT_EQ(term->ncv_attributes, 0);
206 1 EXPECT_EQ(term->features, TFLAG_8_COLOR);
207 1 EXPECT_EQ(term->ibuf.len, 0);
208 1 EXPECT_NONNULL(term->ibuf.buf);
209
210 // Make sure no terminal output was buffered
211 1 const TermOutputBuffer *obuf = &term->obuf;
212 1 EXPECT_NONNULL(obuf->buf);
213 1 EXPECT_EQ(obuf->count, 0);
214 1 EXPECT_EQ(obuf->scroll_x, 0);
215 1 EXPECT_EQ(obuf->x, 0);
216 1 EXPECT_EQ(obuf->width, 0);
217 1 EXPECT_EQ(obuf->style.fg, COLOR_DEFAULT);
218 1 EXPECT_EQ(obuf->style.bg, COLOR_DEFAULT);
219 1 EXPECT_EQ(obuf->style.attr, 0);
220 1 EXPECT_EQ(obuf->cursor_style.type, CURSOR_DEFAULT);
221 1 EXPECT_EQ(obuf->cursor_style.color, COLOR_DEFAULT);
222
223 1 ASSERT_NONNULL(e->view);
224 1 ASSERT_NONNULL(e->buffer);
225 1 EXPECT_EQ(e->buffers.count, 1);
226 1 EXPECT_NULL(e->buffer->abs_filename);
227 1 EXPECT_PTREQ(e->buffer, e->buffers.ptrs[0]);
228 1 EXPECT_FALSE(e->err.print_to_stderr);
229 1 EXPECT_FALSE(e->err.stderr_errors_printed);
230 1 EXPECT_EQ(e->flags, EFLAG_HEADLESS);
231 1 EXPECT_EQ(e->include_recursion_count, 0);
232 1 EXPECT_FALSE(e->options.lock_files);
233
234 1 frame_remove(e, e->root_frame);
235 1 EXPECT_NULL(e->view);
236 1 EXPECT_NULL(e->buffer);
237 1 EXPECT_EQ(e->buffers.count, 0);
238
239 1 free_editor_state(e);
240 1 EXPECT_EQ(need_term_reset_on_fatal_error, 0);
241 1 EXPECT_TRUE(log_close());
242 1 }
243
244 static const TestEntry itests[] = {
245 TEST(test_process_sanity),
246 TEST(test_posix_sanity),
247 TEST(test_log_open_errors),
248 TEST(test_trace_flags_from_str),
249 TEST(test_init),
250 };
251
252 static const TestEntry dtests[] = {
253 TEST(test_deinit),
254 };
255
256 const TestGroup init_tests = TEST_GROUP(itests);
257 const TestGroup deinit_tests = TEST_GROUP(dtests);
258