dte test coverage


Directory: ./
File: test/filetype.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 102 102 100.0%
Functions: 5 5 100.0%
Branches: 4 4 100.0%

Line Branch Exec Source
1 #include "test.h"
2 #include "filetype.h"
3
4 1 static void test_is_valid_filetype_name(TestContext *ctx)
5 {
6 1 EXPECT_TRUE(is_valid_filetype_name("c"));
7 1 EXPECT_TRUE(is_valid_filetype_name("asm"));
8 1 EXPECT_TRUE(is_valid_filetype_name("abc-XYZ_128.90"));
9 1 EXPECT_FALSE(is_valid_filetype_name(""));
10 1 EXPECT_FALSE(is_valid_filetype_name("x/y"));
11 1 EXPECT_FALSE(is_valid_filetype_name(" "));
12 1 EXPECT_FALSE(is_valid_filetype_name("/"));
13 1 EXPECT_FALSE(is_valid_filetype_name("-c"));
14 1 EXPECT_FALSE(is_valid_filetype_name("abc xyz"));
15 1 EXPECT_FALSE(is_valid_filetype_name("abc\txyz"));
16 1 EXPECT_FALSE(is_valid_filetype_name("xyz "));
17 1 EXPECT_FALSE(is_valid_filetype_name("foo\n"));
18
19 1 char str[65];
20 1 size_t n = sizeof(str) - 1;
21 1 memset(str, 'a', n);
22 1 str[n] = '\0';
23 1 ASSERT_EQ(strlen(str), 64);
24 1 EXPECT_FALSE(is_valid_filetype_name(str));
25 1 str[n - 1] = '\0';
26 1 ASSERT_EQ(strlen(str), 63);
27 1 EXPECT_TRUE(is_valid_filetype_name(str));
28
29 1 StringView filetype = STRING_VIEW("zero\0\0");
30 1 EXPECT_EQ(filetype.length, 6);
31 1 EXPECT_FALSE(is_valid_filetype_name_sv(&filetype));
32 1 filetype.length--;
33 1 EXPECT_FALSE(is_valid_filetype_name_sv(&filetype));
34 1 filetype.length--;
35 1 EXPECT_TRUE(is_valid_filetype_name_sv(&filetype));
36 1 }
37
38 1 static void test_find_ft_filename(TestContext *ctx)
39 {
40 1 static const struct {
41 const char *filename;
42 const char *expected_filetype;
43 } tests[] = {
44 {"/usr/local/include/lib.h", "c"},
45 {"test.C", "c"},
46 {"test.H", "c"},
47 {"test.S", "asm"},
48 {"test.1", "roff"},
49 {"test.5", "roff"},
50 {"test.c++", "c"},
51 {"test.cc~", "c"},
52 {"test.csv", "csv"},
53 {"test.d", "d"},
54 {"test.d2", "d2"},
55 {"test.gcode", "gcode"},
56 {"test.json", "json"},
57 {"test.kt", "kotlin"},
58 {"test.kts", "kotlin"},
59 {"test.l", "lex"},
60 {"test.lua", "lua"},
61 {"test.m", "objc"},
62 {"test.opml", "xml"},
63 {"test.py", "python"},
64 {"test.re", "c"},
65 {"test.rs", "rust"},
66 {"test.rss", "xml"},
67 {"test.s", "asm"},
68 {"test.tsv", "tsv"},
69 {"test.v", "verilog"},
70 {"test.y", "yacc"},
71 {"test.bats", "sh"},
72 {"test.tlv", "tl-verilog"},
73 {"test.typ", "typst"},
74 {"test.weechatlog", "weechatlog"},
75 {"test.xml", "xml"},
76 {"makefile", "make"},
77 {"GNUmakefile", "make"},
78 {".file.yml", "yaml"},
79 {"/etc/nginx.conf", "nginx"},
80 {"file..rb", "ruby"},
81 {"file.rb", "ruby"},
82 {"/etc/hosts", "config"},
83 {"/etc/fstab", "config"},
84 {"/boot/grub/menu.lst", "config"},
85 {"/etc/krb5.conf", "ini"},
86 {"/etc/ld.so.conf", "config"},
87 {"/etc/default/grub", "sh"},
88 {"/etc/systemd/user.conf", "ini"},
89 {"/etc/nginx/mime.types", "nginx"},
90 {"/etc/pam.d/login", "config"},
91 {"/etc/iptables/iptables.rules", "config"},
92 {"/etc/iptables/ip6tables.rules", "config"},
93 {"/root/.bash_profile", "sh"},
94 {".bash_profile", "sh"},
95 {".clang-format", "yaml"},
96 {".drirc", "xml"},
97 {".dterc", "dte"},
98 {".editorconfig", "ini"},
99 {".gitattributes", "config"},
100 {".gitconfig", "ini"},
101 {".gitmodules", "ini"},
102 {".jshintrc", "json"},
103 {".zshrc", "sh"},
104 {".XCompose", "config"},
105 {".tmux.conf", "tmux"},
106 {"zshrc", "sh"},
107 {"dot_zshrc", "sh"},
108 {"gnus", "lisp"},
109 {".gnus", "lisp"},
110 {"dot_gnus", "lisp"},
111 {"bash_functions", "sh"},
112 {".bash_functions", "sh"},
113 {"dot_bash_functions", "sh"},
114 {"dot_watchmanconfig", "json"},
115 {"file.flatpakref", "ini"},
116 {"file.automount", "ini"},
117 {"file.nginxconf", "nginx"},
118 {"meson_options.txt", "meson"},
119 {".git-blame-ignore-revs", "config"},
120 {"tags", "ctags"},
121 {"Pipfile", "toml"},
122 {"Pipfile.lock", "json"},
123 {"user-dirs.dirs", "config"},
124 {"Makefile.am", "make"},
125 {"Makefile.in", "make"},
126 {"Makefile.i_", NULL},
127 {"Makefile.a_", NULL},
128 {"Makefile._m", NULL},
129 {"M_______.am", NULL},
130 {".Makefile", NULL},
131 {"file.glslf", "glsl"},
132 {"file.glslv", "glsl"},
133 {"file.gl_lv", NULL},
134 {"file.gls_v", NULL},
135 {"file.gl__v", NULL},
136 {"._", NULL},
137 {".1234", NULL},
138 {".12345", NULL},
139 {".123456", NULL},
140 {".doa_", NULL},
141 {"dot_", NULL},
142 {"dot_z", NULL},
143 {"/etc../etc.c.old/c.old", NULL},
144 {".c~", NULL},
145 {".ini~", NULL},
146 {".yml.bak", NULL},
147 {"test.c.bak", "c"},
148 {"test.c.new", "c"},
149 {"test.c.old~", "c"},
150 {"test.c.orig", "c"},
151 {"test.c.pacnew", "c"},
152 {"test.c.pacorig", "c"},
153 {"test.c.pacsave", "c"},
154 {"test.c.dpkg-dist", "c"},
155 {"test.c.dpkg-old", "c"},
156 {"test.c.dpkg-backup", "c"},
157 {"test.c.dpkg-remove", "c"},
158 {"test.c.rpmnew", "c"},
159 {"test.c.rpmsave", "c"},
160 {"test.@", NULL},
161 {"test.~", NULL},
162 {"test.", NULL},
163 {"test..", NULL},
164 {"1", NULL},
165 {"/", NULL},
166 {".c", NULL},
167 {".", NULL},
168 {"", NULL},
169 {NULL, NULL},
170 };
171 1 const PointerArray arr = PTR_ARRAY_INIT;
172 1 const StringView empty_line = STRING_VIEW_INIT;
173
2/2
✓ Branch 0 (6→3) taken 126 times.
✓ Branch 1 (6→7) taken 1 times.
127 FOR_EACH_I(i, tests) {
174 126 const char *ft = find_ft(&arr, tests[i].filename, empty_line);
175 126 IEXPECT_STREQ(ft, tests[i].expected_filetype);
176 }
177 1 }
178
179 1 static void test_find_ft_firstline(TestContext *ctx)
180 {
181 1 static const struct {
182 const char *line;
183 const char *expected_filetype;
184 } tests[] = {
185 {"<!DOCTYPE html>", "html"},
186 {"<!doctype HTML", "html"},
187 {"<!doctype htm", NULL},
188 {"<!DOCTYPE fontconfig", "xml"},
189 {"<!DOCTYPE colormap", "xml"},
190 {"<!DOCTYPE busconfig", "xml"},
191 {"<!doctype busconfig", NULL},
192 {"<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "xml"},
193 {"ISO-10303-21;", "step"},
194 {"%YAML 1.1", "yaml"},
195 {"%YamL", NULL},
196 {"[wrap-file]", "ini"},
197 {"[wrap-file", NULL},
198 {"[section] \t", "ini"},
199 {" [section]", NULL},
200 {"[section \t", NULL},
201 {"[ section]", NULL},
202 {"[1]", NULL},
203 {"diff --git a/example.txt b/example.txt", "diff"},
204 {".TH DTE 1", NULL},
205 {"", NULL},
206 {" ", NULL},
207 {" <?xml", NULL},
208 {"\0<?xml", NULL},
209 {"#autoload", "sh"},
210 {"#compdef dte", "sh"},
211 {"#compdef", NULL},
212 {"stash@{0}: WIP on master: ...", "gitstash"},
213 {"stash@", NULL},
214 {"commit 8c6db8e8f8fbf055633ffb7a8bb449bb177adf01 (...)", "gitlog"},
215 {"commit 8c6db8e8f8fbf055633ffb7a8bb449bb177adf01", "gitlog"},
216 {"commit 8c6db8e8f8fbf055633ffb7a8bb449bb177adf01 ", NULL},
217 {"commit 8c6db8e8f8fbf055633ffb7a8bb449bb177adf0 (...)", NULL},
218
219 // Emacs style file-local variables
220 {"<!--*-xml-*-->", "xml"},
221 {"% -*-latex-*-", "tex"},
222 {"# -*-shell-script-*-", "sh"},
223 {"// -*- c -*-", "c"},
224 {".. -*-rst-*-", "rst"},
225 {";; -*-scheme-*-", "scheme"},
226 {"-- -*-lua-*-", "lua"},
227 {"\\input texinfo @c -*-texinfo-*-", "texinfo"},
228
229 // Not yet handled
230 {".. -*- mode: rst -*-", NULL},
231 {".. -*- Mode: rst -*-", NULL},
232 {".. -*- mode: rst; -*-", NULL},
233 {".. -*- coding: utf-8; mode: rst; fill-column: 75; -*- ", NULL},
234 {";; -*- mode: Lisp; fill-column: 75; comment-column: 50; -*-", NULL},
235 {";; -*- mode: fallback ; mode: lisp -*- ", NULL},
236
237 // These could be handled, but currently aren't (mostly due to heuristics
238 // intended to avoid doing extra work, if unlikely to detect anything)
239 {" <!--*-xml-*-->", NULL},
240 {"~ -*- c -*-", NULL},
241 {"xyz -*- c -*-", NULL},
242 {"d -*- c -*-", NULL},
243
244 // Hashbangs
245 {"#!/usr/bin/ash", "sh"},
246 {"#!/usr/bin/awk", "awk"},
247 {"#!/usr/bin/bash", "sh"},
248 {"#!/usr/bin/bats", "sh"},
249 {"#!/usr/bin/bigloo", "scheme"},
250 {"#!/usr/bin/ccl", "lisp"},
251 {"#!/usr/bin/chicken", "scheme"},
252 {"#!/usr/bin/clisp", "lisp"},
253 {"#!/usr/bin/coffee", "coffee"},
254 {"#!/usr/bin/crystal", "ruby"},
255 {"#!/usr/bin/dash", "sh"},
256 {"#!/usr/bin/deno", "typescript"},
257 {"#!/usr/bin/ecl", "lisp"},
258 {"#!/usr/bin/gawk", "awk"},
259 {"#!/usr/bin/gmake", "make"},
260 {"#!/usr/bin/gnuplot", "gnuplot"},
261 {"#!/usr/bin/groovy", "groovy"},
262 {"#!/usr/bin/gsed", "sed"},
263 {"#!/usr/bin/guile", "scheme"},
264 {"#!/usr/bin/jruby", "ruby"},
265 {"#!/usr/bin/ksh", "sh"},
266 {"#!/usr/bin/lisp", "lisp"},
267 {"#!/usr/bin/luajit", "lua"},
268 {"#!/usr/bin/lua", "lua"},
269 {"#!/usr/bin/macruby", "ruby"},
270 {"#!/usr/bin/make", "make"},
271 {"#!/usr/bin/mawk", "awk"},
272 {"#!/usr/bin/mksh", "sh"},
273 {"#!/usr/bin/moon", "moonscript"},
274 {"#!/usr/bin/nawk", "awk"},
275 {"#!/usr/bin/node", "javascript"},
276 {"#!/usr/bin/nodejs", "javascript"},
277 {"#!/usr/bin/openrc-run", "sh"},
278 {"#!/usr/bin/pdksh", "sh"},
279 {"#!/usr/bin/perl", "perl"},
280 {"#!/usr/bin/php", "php"},
281 {"#!/usr/bin/pypy3", "python"},
282 {"#!/usr/bin/python", "python"},
283 {"#!/usr/bin/r6rs", "scheme"},
284 {"#!/usr/bin/racket", "scheme"},
285 {"#!/usr/bin/rake", "ruby"},
286 {"#!/usr/bin/ruby", "ruby"},
287 {"#!/usr/bin/runhaskell", "haskell"},
288 {"#!/usr/bin/rust-script", "rust"},
289 {"#!/usr/bin/sbcl", "lisp"},
290 {"#!/usr/bin/sed", "sed"},
291 {"#!/bin/sh", "sh"},
292 {"#!/usr/bin/tcc", "c"},
293 {"#!/usr/bin/tclsh", "tcl"},
294 {"#!/usr/bin/ts-node", "typescript"},
295 {"#!/usr/bin/wish", "tcl"},
296 {"#!/usr/bin/zsh", "sh"},
297 {"#!/usr/bin/lua5.3", "lua"},
298 {"#!/usr/bin/env lua", "lua"},
299 {"#!/usr/bin/env lua5.3", "lua"},
300 {"#! /usr/bin/env lua5.3", "lua"},
301 {"#! /usr/bin/env lua5.3", "lua"},
302 {"#!/usr/bin/env /usr/bin/lua", "lua"},
303 {"#!/lua", "lua"},
304 {"#!/usr/bin/_unhaskell", NULL},
305 {"#!/usr/bin/runhaskel_", NULL},
306 {"#!/usr/bin/unknown", NULL},
307 {"#!lua", NULL},
308 {"#!/usr/bin/ lua", NULL},
309 {"#!/usr/bin/", NULL},
310 {"#!/usr/bin/env", NULL},
311 {"#!/usr/bin/env ", NULL},
312 {"#!/usr/bin/env ", NULL},
313 {"#!/usr/bin/env/ lua", NULL},
314 {"#!/lua/", NULL},
315 };
316 1 const PointerArray arr = PTR_ARRAY_INIT;
317
2/2
✓ Branch 0 (6→3) taken 121 times.
✓ Branch 1 (6→7) taken 1 times.
122 FOR_EACH_I(i, tests) {
318 121 const char *ft = find_ft(&arr, NULL, strview_from_cstring(tests[i].line));
319 121 IEXPECT_STREQ(ft, tests[i].expected_filetype);
320 }
321 1 }
322
323 1 static void test_find_ft_dynamic(TestContext *ctx)
324 {
325 1 PointerArray a = PTR_ARRAY_INIT;
326 1 const char *ft = "test1";
327 1 StringView line = STRING_VIEW_INIT;
328 1 EXPECT_FALSE(is_ft(&a, ft));
329 1 EXPECT_TRUE(add_filetype(&a, ft, "ext-test", FT_EXTENSION, NULL));
330 1 EXPECT_TRUE(is_ft(&a, ft));
331 1 EXPECT_STREQ(find_ft(&a, "/tmp/file.ext-test", line), ft);
332
333 1 ft = "test2";
334 1 EXPECT_TRUE(add_filetype(&a, ft, "/zdir/__[A-Z]+$", FT_FILENAME, NULL));
335 1 EXPECT_STREQ(find_ft(&a, "/tmp/zdir/__TESTFILE", line), ft);
336 1 EXPECT_STREQ(find_ft(&a, "/tmp/zdir/__testfile", line), NULL);
337
338 1 ft = "test3";
339 1 EXPECT_TRUE(add_filetype(&a, ft, "._fiLeName", FT_BASENAME, NULL));
340 1 EXPECT_STREQ(find_ft(&a, "/tmp/._fiLeName", line), ft);
341 1 EXPECT_STREQ(find_ft(&a, "/tmp/._filename", line), NULL);
342
343 1 ft = "test4";
344 1 line = strview_from_cstring("!!42");
345 1 EXPECT_TRUE(add_filetype(&a, ft, "^!+42$", FT_CONTENT, NULL));
346 1 EXPECT_STREQ(find_ft(&a, NULL, line), ft);
347
348 1 ft = "test5";
349 1 line = strview_from_cstring("#!/usr/bin/xyzlang4.2");
350 1 EXPECT_TRUE(add_filetype(&a, ft, "xyzlang", FT_INTERPRETER, NULL));
351 1 EXPECT_STREQ(find_ft(&a, NULL, line), ft);
352
353 1 EXPECT_TRUE(is_ft(&a, "test1"));
354 1 EXPECT_TRUE(is_ft(&a, "test2"));
355 1 EXPECT_TRUE(is_ft(&a, "test3"));
356 1 EXPECT_TRUE(is_ft(&a, "test4"));
357 1 EXPECT_TRUE(is_ft(&a, "test5"));
358 1 EXPECT_FALSE(is_ft(&a, "test0"));
359 1 EXPECT_FALSE(is_ft(&a, "test"));
360
361 1 free_filetypes(&a);
362 1 }
363
364 1 static void test_is_ft(TestContext *ctx)
365 {
366 1 const PointerArray a = PTR_ARRAY_INIT;
367 1 EXPECT_TRUE(is_ft(&a, "ada"));
368 1 EXPECT_TRUE(is_ft(&a, "asm"));
369 1 EXPECT_TRUE(is_ft(&a, "awk"));
370 1 EXPECT_TRUE(is_ft(&a, "c"));
371 1 EXPECT_TRUE(is_ft(&a, "d"));
372 1 EXPECT_TRUE(is_ft(&a, "dte"));
373 1 EXPECT_TRUE(is_ft(&a, "java"));
374 1 EXPECT_TRUE(is_ft(&a, "javascript"));
375 1 EXPECT_TRUE(is_ft(&a, "lua"));
376 1 EXPECT_TRUE(is_ft(&a, "mail"));
377 1 EXPECT_TRUE(is_ft(&a, "make"));
378 1 EXPECT_TRUE(is_ft(&a, "pkg-config"));
379 1 EXPECT_TRUE(is_ft(&a, "rst"));
380 1 EXPECT_TRUE(is_ft(&a, "sh"));
381 1 EXPECT_TRUE(is_ft(&a, "yaml"));
382 1 EXPECT_TRUE(is_ft(&a, "zig"));
383
384 1 EXPECT_FALSE(is_ft(&a, ""));
385 1 EXPECT_FALSE(is_ft(&a, "-"));
386 1 EXPECT_FALSE(is_ft(&a, "a"));
387 1 EXPECT_FALSE(is_ft(&a, "C"));
388 1 EXPECT_FALSE(is_ft(&a, "MAKE"));
389 1 }
390
391 static const TestEntry tests[] = {
392 TEST(test_is_valid_filetype_name),
393 TEST(test_find_ft_filename),
394 TEST(test_find_ft_firstline),
395 TEST(test_find_ft_dynamic),
396 TEST(test_is_ft),
397 };
398
399 const TestGroup filetype_tests = TEST_GROUP(tests);
400