]> git.sur5r.net Git - i3/i3/blob - testcases/t/187-commands-parser.t
39da19d8aeefd578903f25f86bf4c0046783a175
[i3/i3] / testcases / t / 187-commands-parser.t
1 #!perl
2 # vim:ts=4:sw=4:expandtab
3 #
4 # Please read the following documents before working on tests:
5 # • https://build.i3wm.org/docs/testsuite.html
6 #   (or docs/testsuite)
7 #
8 # • https://build.i3wm.org/docs/lib-i3test.html
9 #   (alternatively: perldoc ./testcases/lib/i3test.pm)
10 #
11 # • https://build.i3wm.org/docs/ipc.html
12 #   (or docs/ipc)
13 #
14 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
15 #   (unless you are already familiar with Perl)
16 #
17 # Tests the standalone parser binary to see if it calls the right code when
18 # confronted with various commands, if it prints proper error messages for
19 # wrong commands and if it terminates in every case.
20 #
21 use i3test i3_autostart => 0;
22
23 sub parser_calls {
24     my ($command) = @_;
25
26     # TODO: use a timeout, so that we can error out if it doesn’t terminate
27     # TODO: better way of passing arguments
28     my $stdout = qx(test.commands_parser '$command' 2>&1 >&-);
29
30     # Filter out all debugging output.
31     my @lines = split("\n", $stdout);
32     @lines = grep { not /^# / } @lines;
33
34     # The criteria management calls are irrelevant and not what we want to test
35     # in the first place.
36     @lines = grep { !(/cmd_criteria_init()/ || /cmd_criteria_match_windows/) } @lines;
37     return join("\n", @lines);
38 }
39
40 ################################################################################
41 # 1: First that the parser properly recognizes commands which are ok.
42 ################################################################################
43
44 # The first call has only a single command, the following ones are consolidated
45 # for performance.
46 is(parser_calls('move workspace 3'),
47    'cmd_move_con_to_workspace_name(3, (null))',
48    'single number (move workspace 3) ok');
49
50 is(parser_calls(
51    'move to workspace 3; ' .
52    'move window to workspace 3; ' .
53    'move container to workspace 3; ' .
54    'move workspace foobar; ' .
55    'move workspace torrent; ' .
56    'move workspace to output LVDS1; ' .
57    'move workspace 3: foobar; ' .
58    'move workspace "3: foobar"; ' .
59    'move workspace "3: foobar, baz"; '),
60    "cmd_move_con_to_workspace_name(3, (null))\n" .
61    "cmd_move_con_to_workspace_name(3, (null))\n" .
62    "cmd_move_con_to_workspace_name(3, (null))\n" .
63    "cmd_move_con_to_workspace_name(foobar, (null))\n" .
64    "cmd_move_con_to_workspace_name(torrent, (null))\n" .
65    "cmd_move_workspace_to_output(LVDS1)\n" .
66    "cmd_move_con_to_workspace_name(3: foobar, (null))\n" .
67    "cmd_move_con_to_workspace_name(3: foobar, (null))\n" .
68    "cmd_move_con_to_workspace_name(3: foobar, baz, (null))",
69    'move ok');
70
71 is(parser_calls('move workspace 3: foobar, nop foo'),
72    "cmd_move_con_to_workspace_name(3: foobar, (null))\n" .
73    "cmd_nop(foo)",
74    'multiple ops (move workspace 3: foobar, nop foo) ok');
75
76 is(parser_calls(
77    'exec i3-sensible-terminal; ' .
78    'exec --no-startup-id i3-sensible-terminal'),
79    "cmd_exec((null), i3-sensible-terminal)\n" .
80    "cmd_exec(--no-startup-id, i3-sensible-terminal)",
81    'exec ok');
82
83 is(parser_calls(
84    'resize shrink left; ' .
85    'resize shrink left 25 px; ' .
86    'resize shrink left 25 px or 33 ppt; ' .
87    'resize shrink left 25'),
88    "cmd_resize(shrink, left, 10, 10)\n" .
89    "cmd_resize(shrink, left, 25, 10)\n" .
90    "cmd_resize(shrink, left, 25, 33)\n" .
91    "cmd_resize(shrink, left, 25, 10)",
92    'simple resize ok');
93
94 is(parser_calls('resize shrink left 25 px or 33 ppt,'),
95    'cmd_resize(shrink, left, 25, 33)',
96    'trailing comma resize ok');
97
98 is(parser_calls('resize shrink left 25 px or 33 ppt;'),
99    'cmd_resize(shrink, left, 25, 33)',
100    'trailing semicolon resize ok');
101
102 is(parser_calls('[con_mark=yay] focus'),
103    "cmd_criteria_add(con_mark, yay)\n" .
104    "cmd_focus()",
105    'criteria focus ok');
106
107 is(parser_calls("[con_mark=yay con_mark=bar] focus"),
108    "cmd_criteria_add(con_mark, yay)\n" .
109    "cmd_criteria_add(con_mark, bar)\n" .
110    "cmd_focus()",
111    'criteria focus ok');
112
113 is(parser_calls("[con_mark=yay\tcon_mark=bar] focus"),
114    "cmd_criteria_add(con_mark, yay)\n" .
115    "cmd_criteria_add(con_mark, bar)\n" .
116    "cmd_focus()",
117    'criteria focus ok');
118
119 is(parser_calls("[con_mark=yay\tcon_mark=bar]\tfocus"),
120    "cmd_criteria_add(con_mark, yay)\n" .
121    "cmd_criteria_add(con_mark, bar)\n" .
122    "cmd_focus()",
123    'criteria focus ok');
124
125 is(parser_calls('[con_mark="yay"] focus'),
126    "cmd_criteria_add(con_mark, yay)\n" .
127    "cmd_focus()",
128    'quoted criteria focus ok');
129
130 # Make sure trailing whitespace is stripped off: While this is not an issue for
131 # commands being parsed due to the configuration, people might send IPC
132 # commands with leading or trailing newlines.
133 is(parser_calls("workspace test\n"),
134    'cmd_workspace_name(test, (null))',
135    'trailing whitespace stripped off ok');
136
137 is(parser_calls("\nworkspace test"),
138    'cmd_workspace_name(test, (null))',
139    'trailing whitespace stripped off ok');
140
141 ################################################################################
142 # 2: Verify that the parser spits out the right error message on commands which
143 # are not ok.
144 ################################################################################
145
146 is(parser_calls('unknown_literal'),
147    "ERROR: Expected one of these tokens: <end>, '[', '" . join("', '", qw(
148        move
149        exec
150        exit
151        restart
152        reload
153        shmlog
154        debuglog
155        border
156        layout
157        append_layout
158        workspace
159        focus
160        kill
161        open
162        fullscreen
163        sticky
164        split
165        floating
166        mark
167        unmark
168        resize
169        rename
170        nop
171        scratchpad
172        swap
173        title_format
174        mode
175        bar
176     )) . "'\n" .
177    "ERROR: Your command: unknown_literal\n" .
178    "ERROR:               ^^^^^^^^^^^^^^^",
179    'error for unknown literal ok');
180
181 is(parser_calls('move something to somewhere'),
182    "ERROR: Expected one of these tokens: 'window', 'container', 'to', '--no-auto-back-and-forth', 'workspace', 'output', 'mark', 'scratchpad', 'left', 'right', 'up', 'down', 'position', 'absolute'\n" .
183    "ERROR: Your command: move something to somewhere\n" .
184    "ERROR:                    ^^^^^^^^^^^^^^^^^^^^^^",
185    'error for unknown literal ok');
186
187 ################################################################################
188 # 3: Verify that escaping works correctly
189 ################################################################################
190
191 is(parser_calls('workspace "foo"'),
192    'cmd_workspace_name(foo, (null))',
193    'Command with simple double quotes ok');
194
195 is(parser_calls('workspace "foo'),
196    'cmd_workspace_name(foo, (null))',
197    'Command without ending double quotes ok');
198
199 is(parser_calls('workspace "foo \"bar"'),
200    'cmd_workspace_name(foo "bar, (null))',
201    'Command with escaped double quotes ok');
202
203 is(parser_calls('workspace "foo \\'),
204    'cmd_workspace_name(foo \\, (null))',
205    'Command with single backslash in the end ok');
206
207 is(parser_calls('workspace "foo\\\\bar"'),
208    'cmd_workspace_name(foo\\bar, (null))',
209    'Command with escaped backslashes ok');
210
211 is(parser_calls('workspace "foo\\\\\\"bar"'),
212    'cmd_workspace_name(foo\\"bar, (null))',
213    'Command with escaped double quotes after escaped backslashes ok');
214
215 ################################################################################
216 # 4: Verify that resize commands with a "px or ppt"-construction are parsed
217 # correctly
218 ################################################################################
219
220 is(parser_calls("resize shrink width 10 px or"),
221    "ERROR: Expected one of these tokens: <number>\n" .
222    "ERROR: Your command: resize shrink width 10 px or\n" .
223    "ERROR:                                           ",
224    "error for resize command with incomplete 'or'-construction ok");
225
226 is(parser_calls("resize grow left 10 px or 20 ppt"),
227    "cmd_resize(grow, left, 10, 20)",
228    "resize command with 'or'-construction ok");
229
230 done_testing;