dte test coverage


Directory: ./
File: src/command/run.c
Date: 2024-12-21 16:03:22
Exec Total Coverage
Lines: 65 66 98.5%
Functions: 3 3 100.0%
Branches: 30 32 93.8%

Line Branch Exec Source
1 #include "run.h"
2 #include "args.h"
3 #include "parse.h"
4 #include "change.h"
5 #include "config.h"
6 #include "error.h"
7 #include "util/debug.h"
8 #include "util/ptr-array.h"
9 #include "util/xmalloc.h"
10
11 // NOLINTNEXTLINE(*-avoid-non-const-global-variables)
12 const Command *current_command;
13
14 static bool run_commands(CommandRunner *runner, const PointerArray *array);
15
16 // NOLINTNEXTLINE(misc-no-recursion)
17 6283 static bool run_command(CommandRunner *runner, char **av)
18 {
19 6283 const CommandSet *cmds = runner->cmds;
20 6283 const Command *cmd = cmds->lookup(av[0]);
21
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6271 times.
6283 if (!cmd) {
22 12 const char *name = av[0];
23
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 if (!runner->lookup_alias) {
24 1 return error_msg("No such command: %s", name);
25 }
26
27 11 const char *alias_value = runner->lookup_alias(runner->e, name);
28
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (unlikely(!alias_value)) {
29 1 return error_msg("No such command or alias: %s", name);
30 }
31
32 10 PointerArray array = PTR_ARRAY_INIT;
33 10 CommandParseError err = parse_commands(runner, &array, alias_value);
34
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 if (unlikely(err != CMDERR_NONE)) {
35 1 const char *err_msg = command_parse_error_to_string(err);
36 1 ptr_array_free(&array);
37 1 return error_msg("Parsing alias %s: %s", name, err_msg);
38 }
39
40 // Remove NULL
41 9 array.count--;
42
43
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 9 times.
37 for (size_t i = 1; av[i]; i++) {
44 28 ptr_array_append(&array, xstrdup(av[i]));
45 }
46 9 ptr_array_append(&array, NULL);
47
48 9 bool r = run_commands(runner, &array);
49 9 ptr_array_free(&array);
50 9 return r;
51 }
52
53
4/4
✓ Branch 0 taken 5854 times.
✓ Branch 1 taken 417 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5853 times.
6271 if (unlikely(current_config.file && !(cmd->cmdopts & CMDOPT_ALLOW_IN_RC))) {
54 1 return error_msg("Command %s not allowed in config file", cmd->name);
55 }
56
57 // Record command in macro buffer, if recording (this needs to be done
58 // before parse_args() mutates the array)
59
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6265 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
6270 if (runner->allow_recording && runner->cmds->macro_record) {
60 5 runner->cmds->macro_record(runner->e, cmd, av + 1);
61 }
62
63 // By default change can't be merged with previous one.
64 // Any command can override this by calling begin_change() again.
65 6270 begin_change(CHANGE_MERGE_NONE);
66
67 6270 CommandArgs a = cmdargs_new(av + 1);
68 6270 current_command = cmd;
69
4/4
✓ Branch 0 taken 6263 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 6170 times.
6270 bool r = likely(parse_args(cmd, &a)) && cmd->cmd(runner->e, &a);
70 6270 current_command = NULL;
71
72 6270 end_change();
73 6270 return r;
74 }
75
76 // NOLINTNEXTLINE(misc-no-recursion)
77 7589 static bool run_commands(CommandRunner *runner, const PointerArray *array)
78 {
79
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7589 times.
7589 if (unlikely(runner->recursion_count > 16)) {
80 return error_msg("alias recursion limit reached");
81 }
82
83 7589 void **ptrs = array->ptrs;
84 7589 size_t len = array->count;
85 7589 size_t nfailed = 0;
86 7589 BUG_ON(len == 0);
87 7589 BUG_ON(ptrs[len - 1] != NULL);
88 7589 runner->recursion_count++;
89
90
2/2
✓ Branch 0 taken 7620 times.
✓ Branch 1 taken 7589 times.
15209 for (size_t s = 0, e = 0; s < len; ) {
91 // Iterate over strings, until a terminating NULL is encountered
92 30087 while (ptrs[e]) {
93 22467 e++;
94 30087 BUG_ON(e >= len);
95 }
96
97 // If the value of `e` (end) changed, there's a run of at least
98 // 1 string, which is a command followed by 0 or more arguments
99
2/2
✓ Branch 0 taken 6283 times.
✓ Branch 1 taken 1337 times.
7620 if (e != s) {
100
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 6179 times.
6283 if (!run_command(runner, (char**)ptrs + s)) {
101 104 nfailed++;
102 }
103 }
104
105 // Skip past the NULL, onto the next command (if any)
106 7620 s = ++e;
107 }
108
109 7589 runner->recursion_count--;
110 7589 return (nfailed == 0);
111 }
112
113 7582 bool handle_command(CommandRunner *runner, const char *cmd)
114 {
115 7582 BUG_ON(runner->recursion_count != 0);
116 7582 PointerArray array = PTR_ARRAY_INIT;
117 7582 CommandParseError err = parse_commands(runner, &array, cmd);
118 7582 bool r;
119
2/2
✓ Branch 0 taken 7580 times.
✓ Branch 1 taken 2 times.
7582 if (likely(err == CMDERR_NONE)) {
120 7580 r = run_commands(runner, &array);
121 7580 BUG_ON(runner->recursion_count != 0);
122 } else {
123 2 const char *str = command_parse_error_to_string(err);
124 2 error_msg("Command syntax error: %s", str);
125 2 r = false;
126 }
127 7582 ptr_array_free(&array);
128 7582 return r;
129 }
130