2 * Copyright © 2020 Valve Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
33 #include <llvm-c/Target.h>
35 #include "framework.h"
37 static const char *help_message
=
38 "Usage: %s [-h] [-l --list] [--no-check] [TEST [TEST ...]]\n"
40 "Run ACO unit test(s). If TEST is not provided, all tests are run.\n"
42 "positional arguments:\n"
43 " TEST Run TEST. If TEST ends with a '.', run tests with names\n"
44 " starting with TEST. The test variant (after the '/') can\n"
45 " be omitted to run all variants\n"
47 "optional arguments:\n"
48 " -h, --help Show this help message and exit.\n"
49 " -l --list List unit tests.\n"
50 " --no-check Print test output instead of checking it.\n";
52 std::map
<std::string
, TestDef
> tests
;
55 static TestDef current_test
;
56 static unsigned tests_written
= 0;
57 static FILE *checker_stdin
= NULL
;
58 static char *checker_stdin_data
= NULL
;
59 static size_t checker_stdin_size
= 0;
61 static char *output_data
= NULL
;
62 static size_t output_size
= 0;
63 static size_t output_offset
= 0;
65 static char current_variant
[64] = {0};
66 static std::set
<std::string
> *variant_filter
= NULL
;
68 bool test_failed
= false;
69 bool test_skipped
= false;
70 static char fail_message
[256] = {0};
75 /* not entirely correct, but shouldn't matter */
81 if (output_offset
== output_size
&& !test_skipped
&& !test_failed
)
84 char *data
= output_data
+ output_offset
;
85 uint32_t size
= output_size
- output_offset
;
87 fwrite("test", 1, 4, checker_stdin
);
88 fwrite(current_test
.name
, 1, strlen(current_test
.name
)+1, checker_stdin
);
89 fwrite(current_variant
, 1, strlen(current_variant
)+1, checker_stdin
);
90 fwrite(current_test
.source_file
, 1, strlen(current_test
.source_file
)+1, checker_stdin
);
91 if (test_failed
|| test_skipped
) {
92 const char *res
= test_failed
? "failed" : "skipped";
93 fwrite("\x01", 1, 1, checker_stdin
);
94 fwrite(res
, 1, strlen(res
)+1, checker_stdin
);
95 fwrite(fail_message
, 1, strlen(fail_message
)+1, checker_stdin
);
97 fwrite("\x00", 1, 1, checker_stdin
);
99 fwrite(&size
, 4, 1, checker_stdin
);
100 fwrite(data
, 1, size
, checker_stdin
);
103 output_offset
+= size
;
106 bool set_variant(const char *name
)
108 if (variant_filter
&& !variant_filter
->count(name
))
113 test_skipped
= false;
114 strncpy(current_variant
, name
, sizeof(current_variant
) - 1);
116 printf("Running '%s/%s'\n", current_test
.name
, name
);
121 void fail_test(const char *fmt
, ...)
127 vsnprintf(fail_message
, sizeof(fail_message
), fmt
, args
);
132 void skip_test(const char *fmt
, ...)
138 vsnprintf(fail_message
, sizeof(fail_message
), fmt
, args
);
143 void run_test(TestDef def
)
150 test_skipped
= false;
151 memset(current_variant
, 0, sizeof(current_variant
));
154 output
= open_memstream(&output_data
, &output_size
);
166 int check_output(char **argv
)
171 fclose(checker_stdin
);
176 write(stdin_pipe
[1], checker_stdin_data
, checker_stdin_size
);
177 close(stdin_pipe
[1]);
178 dup2(stdin_pipe
[0], STDIN_FILENO
);
180 execlp(ACO_TEST_PYTHON_BIN
, ACO_TEST_PYTHON_BIN
, ACO_TEST_SOURCE_DIR
"/check_output.py", NULL
);
182 fprintf(stderr
, "%s: execl() failed: %s\n", argv
[0], strerror(errno
));
186 bool match_test(std::string name
, std::string pattern
)
188 if (name
.length() < pattern
.length())
190 if (pattern
.back() == '.')
191 name
.resize(pattern
.length());
192 return name
== pattern
;
195 int main(int argc
, char **argv
)
200 const struct option opts
[] = {
201 { "help", no_argument
, &print_help
, 1 },
202 { "list", no_argument
, &do_list
, 1 },
203 { "no-check", no_argument
, &do_check
, 0 },
208 while ((c
= getopt_long(argc
, argv
, "hl", opts
, NULL
)) != -1) {
220 fprintf(stderr
, "%s: Invalid argument\n", argv
[0]);
226 fprintf(stderr
, help_message
, argv
[0]);
231 for (auto test
: tests
)
232 printf("%s\n", test
.first
.c_str());
236 std::vector
<std::pair
<std::string
, std::string
>> names
;
237 for (int i
= optind
; i
< argc
; i
++) {
238 std::string name
= argv
[i
];
240 size_t pos
= name
.find('/');
241 if (pos
!= std::string::npos
) {
242 variant
= name
.substr(pos
+ 1);
243 name
= name
.substr(0, pos
);
245 names
.emplace_back(std::pair
<std::string
, std::string
>(name
, variant
));
249 checker_stdin
= open_memstream(&checker_stdin_data
, &checker_stdin_size
);
251 LLVMInitializeAMDGPUTargetInfo();
252 LLVMInitializeAMDGPUTarget();
253 LLVMInitializeAMDGPUTargetMC();
254 LLVMInitializeAMDGPUDisassembler();
258 for (auto pair
: tests
) {
259 bool found
= names
.empty();
260 bool all_variants
= names
.empty();
261 std::set
<std::string
> variants
;
262 for (const std::pair
<std::string
, std::string
>& name
: names
) {
263 if (match_test(pair
.first
, name
.first
)) {
265 if (name
.second
.empty())
268 variants
.insert(name
.second
);
273 variant_filter
= all_variants
? NULL
: &variants
;
274 printf("Running '%s'\n", pair
.first
.c_str());
275 run_test(pair
.second
);
278 if (!tests_written
) {
279 fprintf(stderr
, "%s: No matching tests\n", argv
[0]);
285 return check_output(argv
);
287 printf("Tests ran\n");