1 /*
2  * Copyright © 2017 Collabora Ltd.
3  *
4  * This file is part of vkmark.
5  *
6  * vkmark is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation, either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * vkmark is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with vkmark. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Authors:
20  *   Alexandros Frantzis <alexandros.frantzis@collabora.com>
21  */
22 
23 #include "src/options.h"
24 #include "src/util.h"
25 
26 #include "catch.hpp"
27 #include <memory>
28 
29 using namespace Catch::Matchers;
30 
31 SCENARIO("options prints window system help", "")
32 {
33     Options options;
34 
35     GIVEN("Options with window system help")
36     {
37         std::string const ws1_help{"WINDOW SYSTEM HELP 1\n"};
38         std::string const ws2_help{"WINDOW SYSTEM HELP 2\n"};
39 
40         options.add_window_system_help(ws1_help);
41         options.add_window_system_help(ws2_help);
42 
43         WHEN("getting the help string")
44         {
45             auto const help = options.help_string();
46 
47             THEN("the window system help is contained")
48             {
49                 REQUIRE_THAT(help, Contains(ws1_help));
50                 REQUIRE_THAT(help, Contains(ws2_help));
51             }
52         }
53     }
54 }
55 
56 namespace
57 {
58 
argv_from_vector(std::vector<std::string> & vec)59 std::unique_ptr<char*[]> argv_from_vector(std::vector<std::string>& vec)
60 {
61     auto argv = std::make_unique<char*[]>(vec.size() + 1);
62 
63     for (size_t i = 0; i < vec.size(); ++i)
64         argv[i] = &vec[i][0];
65 
66     argv[vec.size()] = nullptr;
67 
68     return argv;
69 }
70 
71 }
72 
73 SCENARIO("options parses command line arguments", "")
74 {
75     Options options;
76 
77     GIVEN("A command line with invalid options fails")
78     {
79         std::vector<std::string> args{"vkmark", "--invalid"};
80         auto argv = argv_from_vector(args);
81 
82         WHEN("parsing the args")
83         {
84             auto const result = options.parse_args(args.size(), argv.get());
85 
86             THEN("the parsing fails")
87             {
88                 REQUIRE_FALSE(result);
89             }
90         }
91     }
92     GIVEN("A command line with -b and --benchmark")
93     {
94         std::string const bench1{"scene1:opt1=val1"};
95         std::string const bench2{"scene2"};
96         std::vector<std::string> args{"vkmark", "-b", bench1, "--benchmark", bench2};
97         auto argv = argv_from_vector(args);
98 
99         WHEN("parsing the args")
100         {
101             REQUIRE(options.parse_args(args.size(), argv.get()));
102 
103             THEN("the benchmarks are parsed")
104             {
105                 REQUIRE_THAT(options.benchmarks,
106                              Equals(std::vector<std::string>{bench1, bench2}));
107             }
108         }
109     }
110 
111     GIVEN("A command line with -s")
112     {
113         int const width = 123;
114         int const height = 456;
115         std::vector<std::string> args{
116             "vkmark", "-s", std::to_string(width) + "x" + std::to_string(height)};
117         auto argv = argv_from_vector(args);
118 
119         WHEN("parsing the args")
120         {
121             REQUIRE(options.parse_args(args.size(), argv.get()));
122 
123             THEN("the size is parsed")
124             {
125                 REQUIRE(options.size.first == width);
126                 REQUIRE(options.size.second == height);
127             }
128         }
129     }
130 
131     GIVEN("A command line with --size")
132     {
133         int const width = 123;
134         int const height = 456;
135         std::vector<std::string> args{
136             "vkmark", "--size", std::to_string(width) + "x" + std::to_string(height)};
137         auto argv = argv_from_vector(args);
138 
139         WHEN("parsing the args")
140         {
141             REQUIRE(options.parse_args(args.size(), argv.get()));
142 
143             THEN("the size is parsed")
144             {
145                 REQUIRE(options.size.first == width);
146                 REQUIRE(options.size.second == height);
147             }
148         }
149     }
150 
151     GIVEN("A command line with --fullscreen")
152     {
153         std::vector<std::string> args{"vkmark", "--fullscreen"};
154         auto argv = argv_from_vector(args);
155 
156         WHEN("parsing the args")
157         {
158             REQUIRE(options.parse_args(args.size(), argv.get()));
159 
160             THEN("the fullscreen option is parsed")
161             {
162                 REQUIRE(options.size.first == -1);
163                 REQUIRE(options.size.second == -1);
164             }
165         }
166     }
167 
168     GIVEN("A command line with --present-mode")
169     {
170         std::vector<std::string> args{"vkmark", "--present-mode", "fifo"};
171         auto argv = argv_from_vector(args);
172 
173         WHEN("parsing the args")
174         {
175             REQUIRE(options.parse_args(args.size(), argv.get()));
176 
177             THEN("the present mode is parsed")
178             {
179                 REQUIRE(options.present_mode == vk::PresentModeKHR::eFifo);
180             }
181         }
182     }
183 
184     GIVEN("A command line with --list-scenes")
185     {
186         std::vector<std::string> args{"vkmark", "--list-scenes"};
187         auto argv = argv_from_vector(args);
188 
189         WHEN("parsing the args")
190         {
191             REQUIRE_FALSE(options.list_scenes);
192             REQUIRE(options.parse_args(args.size(), argv.get()));
193 
194             THEN("the list-scenes option is parsed")
195             {
196                 REQUIRE(options.list_scenes);
197             }
198         }
199     }
200 
201     GIVEN("A command line with --show-all-options")
202     {
203         std::vector<std::string> args{"vkmark", "--show-all-options"};
204         auto argv = argv_from_vector(args);
205 
206         WHEN("parsing the args")
207         {
208             REQUIRE_FALSE(options.show_all_options);
209             REQUIRE(options.parse_args(args.size(), argv.get()));
210 
211             THEN("the show-all-options option is parsed")
212             {
213                 REQUIRE(options.show_all_options);
214             }
215         }
216     }
217 
218     GIVEN("A command line with --winsys-dir")
219     {
220         std::string const winsys_dir{"bla/winsys"};
221         std::vector<std::string> args{"vkmark", "--winsys-dir", winsys_dir};
222         auto argv = argv_from_vector(args);
223 
224         WHEN("parsing the args")
225         {
226             REQUIRE(options.parse_args(args.size(), argv.get()));
227 
228             THEN("the window system dir is parsed")
229             {
230                 REQUIRE(options.window_system_dir == winsys_dir);
231             }
232         }
233     }
234 
235     GIVEN("A command line with --data-dir")
236     {
237         std::string const data_dir{"bla/data"};
238         std::vector<std::string> args{"vkmark", "--data-dir", data_dir};
239         auto argv = argv_from_vector(args);
240 
241         WHEN("parsing the args")
242         {
243             REQUIRE(options.parse_args(args.size(), argv.get()));
244 
245             THEN("the data dir is parsed")
246             {
247                 REQUIRE(options.data_dir == data_dir);
248             }
249         }
250     }
251 
252     GIVEN("A command line with --winsys")
253     {
254         std::string const winsys{"mywinsys"};
255         std::vector<std::string> args{"vkmark", "--winsys", winsys};
256         auto argv = argv_from_vector(args);
257 
258         WHEN("parsing the args")
259         {
260             REQUIRE(options.window_system.empty());
261             REQUIRE(options.parse_args(args.size(), argv.get()));
262 
263             THEN("the winsys is parsed")
264             {
265                 REQUIRE(options.window_system == winsys);
266             }
267         }
268     }
269 
270     GIVEN("A command line with --winsys-options")
271     {
272         std::string const winsys_options{"opt1=v1:opt2=v2"};
273         std::vector<std::string> args{"vkmark", "--winsys-options", winsys_options};
274         auto argv = argv_from_vector(args);
275 
276         WHEN("parsing the args")
277         {
278             REQUIRE(options.parse_args(args.size(), argv.get()));
279 
280             THEN("the data dir is parsed")
281             {
282                 REQUIRE(options.window_system_options.size() == 2);
283                 REQUIRE(options.window_system_options[0].name == "opt1");
284                 REQUIRE(options.window_system_options[0].value == "v1");
285                 REQUIRE(options.window_system_options[1].name == "opt2");
286                 REQUIRE(options.window_system_options[1].value == "v2");
287             }
288         }
289     }
290 
291     GIVEN("A command line with -d")
292     {
293         std::vector<std::string> args{"vkmark", "-d"};
294         auto argv = argv_from_vector(args);
295 
296         WHEN("parsing the args")
297         {
298             REQUIRE_FALSE(options.show_debug);
299             REQUIRE(options.parse_args(args.size(), argv.get()));
300 
301             THEN("the debug option is parsed")
302             {
303                 REQUIRE(options.show_debug);
304             }
305         }
306     }
307 
308     GIVEN("A command line with --debug")
309     {
310         std::vector<std::string> args{"vkmark", "--debug"};
311         auto argv = argv_from_vector(args);
312 
313         WHEN("parsing the args")
314         {
315             REQUIRE_FALSE(options.show_debug);
316             REQUIRE(options.parse_args(args.size(), argv.get()));
317 
318             THEN("the debug option is parsed")
319             {
320                 REQUIRE(options.show_debug);
321             }
322         }
323     }
324 
325     GIVEN("A command line with -h")
326     {
327         std::vector<std::string> args{"vkmark", "-h"};
328         auto argv = argv_from_vector(args);
329 
330         WHEN("parsing the args")
331         {
332             REQUIRE_FALSE(options.show_help);
333             REQUIRE(options.parse_args(args.size(), argv.get()));
334 
335             THEN("the help option is parsed")
336             {
337                 REQUIRE(options.show_help);
338             }
339         }
340     }
341 
342     GIVEN("A command line with --help")
343     {
344         std::vector<std::string> args{"vkmark", "--help"};
345         auto argv = argv_from_vector(args);
346 
347         WHEN("parsing the args")
348         {
349             REQUIRE_FALSE(options.show_help);
350             REQUIRE(options.parse_args(args.size(), argv.get()));
351 
352             THEN("the help option is parsed")
353             {
354                 REQUIRE(options.show_help);
355             }
356         }
357     }
358 
359     GIVEN("A command line with --run-forever")
360     {
361         std::vector<std::string> args{"vkmark", "--run-forever"};
362         auto argv = argv_from_vector(args);
363 
364         WHEN("parsing the args")
365         {
366             REQUIRE_FALSE(options.run_forever);
367             REQUIRE(options.parse_args(args.size(), argv.get()));
368 
369             THEN("the run-forever option is parsed")
370             {
371                 REQUIRE(options.run_forever);
372             }
373         }
374     }
375 
376     GIVEN("A complex command line")
377     {
378         std::vector<std::string> args{
379             "vkmark",
380             "--benchmark=scene1:opt=val",
381             "-s", "111x222",
382             "--data-dir=data",
383             "--winsys-dir=build/src",
384             "-p", "fiforelaxed"};
385         auto argv = argv_from_vector(args);
386 
387         WHEN("parsing the args")
388         {
389             REQUIRE_FALSE(options.show_help);
390             REQUIRE(options.parse_args(args.size(), argv.get()));
391 
392             THEN("all options are parsed")
393             {
394                 REQUIRE(options.benchmarks.size() == 1);
395                 REQUIRE(options.benchmarks[0] == "scene1:opt=val");
396                 REQUIRE(options.size.first == 111);
397                 REQUIRE(options.size.second == 222);
398                 REQUIRE(options.data_dir == "data");
399                 REQUIRE(options.window_system_dir == "build/src");
400                 REQUIRE(options.present_mode == vk::PresentModeKHR::eFifoRelaxed);
401             }
402         }
403     }
404 }
405