Skip to content

Commit 7a29867

Browse files
committed
tests: add VISP_BACKEND_TEST macro
- simplify running tests for all backends - allow to skip gpu tests from command line
1 parent 904e05c commit 7a29867

File tree

12 files changed

+129
-105
lines changed

12 files changed

+129
-105
lines changed

include/visp/util.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,17 @@ struct flags {
146146
return (lhs.value & uint32_t(rhs)) != 0;
147147
}
148148

149+
friend constexpr bool operator&(flags<E> lhs, flags<E> rhs) {
150+
return (lhs.value & rhs.value) != 0;
151+
}
152+
149153
friend constexpr flags<E> operator|(flags<E> lhs, E rhs) {
150154
return flags<E>(lhs.value | uint32_t(rhs));
151155
}
156+
157+
friend constexpr flags<E> operator|(flags<E> lhs, flags<E> rhs) {
158+
return flags<E>(lhs.value | rhs.value);
159+
}
152160
};
153161

154162
} // namespace visp

src/cli/cli.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ char const* next_arg(int argc, char** argv, int& i) {
3535
if (++i < argc) {
3636
return argv[i];
3737
} else {
38-
throw error("Missing argument after {}", argv[i - 1]);
38+
throw except("Missing argument after {}", argv[i - 1]);
3939
}
4040
}
4141

@@ -45,7 +45,7 @@ std::vector<char const*> collect_args(int argc, char** argv, int& i, char delim
4545
r.push_back(next_arg(argc, argv, i));
4646
} while (i + 1 < argc && argv[i + 1][0] != delim);
4747
if (r.empty()) {
48-
throw error("Missing argument after {}", argv[i - 1]);
48+
throw except("Missing argument after {}", argv[i - 1]);
4949
}
5050
return r;
5151
}
@@ -54,21 +54,21 @@ int parse_int(std::string_view arg) {
5454
int value = 0;
5555
auto [ptr, ec] = std::from_chars(arg.data(), arg.data() + arg.size(), value);
5656
if (ec != std::errc()) {
57-
throw error("Invalid integer argument: {}", arg);
57+
throw except("Invalid integer argument: {}", arg);
5858
}
5959
return value;
6060
}
6161

6262
char const* validate_path(char const* arg) {
6363
if (!exists(path(arg))) {
64-
throw error("File not found: {}", arg);
64+
throw except("File not found: {}", arg);
6565
}
6666
return arg;
6767
}
6868

6969
void require_inputs(std::span<char const* const> inputs, int n_required, char const* names) {
7070
if (inputs.size() != size_t(n_required)) {
71-
throw error(
71+
throw except(
7272
"Expected -i to be followed by {} inputs: {} - but found {}.", n_required, names,
7373
inputs.size());
7474
}
@@ -77,7 +77,7 @@ void require_inputs(std::span<char const* const> inputs, int n_required, char co
7777
cli_args cli_parse(int argc, char** argv) {
7878
cli_args r;
7979
if (argc < 2) {
80-
throw error("Missing command.\nUsage: {} <command> [options]", argv[0]);
80+
throw except("Missing command.\nUsage: {} <command> [options]", argv[0]);
8181
}
8282

8383
std::string_view arg1 = argv[1];
@@ -90,7 +90,7 @@ cli_args cli_parse(int argc, char** argv) {
9090
} else if (arg1 == "esrgan") {
9191
r.command = cli_command::esrgan;
9292
} else {
93-
throw error("Unknown command: {}", arg1);
93+
throw except("Unknown command: {}", arg1);
9494
}
9595

9696
for (int i = 2; i < argc; ++i) {
@@ -111,14 +111,14 @@ cli_args cli_parse(int argc, char** argv) {
111111
} else if (backend_arg == "gpu") {
112112
r.bknd_type = backend_type::gpu;
113113
} else {
114-
throw error("Unknown backend type '{}', must be one of: cpu, gpu", backend_arg);
114+
throw except("Unknown backend type '{}', must be one of: cpu, gpu", backend_arg);
115115
}
116116
} else if (arg == "--composite") {
117117
r.composite = next_arg(argc, argv, i);
118118
} else if (arg == "--tile") {
119119
r.tile_size = parse_int(next_arg(argc, argv, i));
120120
} else if (arg.starts_with("-")) {
121-
throw error("Unknown argument: {}", arg);
121+
throw except("Unknown argument: {}", arg);
122122
}
123123
}
124124
return r;
@@ -255,12 +255,12 @@ struct sam_prompt {
255255

256256
sam_prompt sam_parse_prompt(std::span<char const* const> args, i32x2 extent) {
257257
if (args.empty()) {
258-
throw error(
258+
throw except(
259259
"SAM requires a prompt with coordinates for a point or box"
260260
"eg. '--prompt 100 200' to pick the point at pixel (x=100, y=200)");
261261
}
262262
if (args.size() < 2 || args.size() > 4) {
263-
throw error(
263+
throw except(
264264
"Invalid number of arguments for SAM prompt. Expected 2 (point) or 4 (box) numbers, "
265265
"got {}",
266266
args.size());
@@ -269,17 +269,17 @@ sam_prompt sam_parse_prompt(std::span<char const* const> args, i32x2 extent) {
269269
if (args.size() >= 2) {
270270
a = {parse_int(args[0]), parse_int(args[1])};
271271
if (a[0] < 0 || a[1] < 0 || a[0] >= extent[0] || a[1] >= extent[1]) {
272-
throw error("Invalid image coordinates: ({}, {})", a[0], a[1]);
272+
throw except("Invalid image coordinates: ({}, {})", a[0], a[1]);
273273
}
274274
}
275275
i32x2 b{-1, -1};
276276
if (args.size() == 4) {
277277
b = {parse_int(args[2]), parse_int(args[3])};
278278
if (b[0] < 0 || b[1] < 0 || b[0] >= extent[0] || b[1] >= extent[1]) {
279-
throw error("Invalid image coordinates: ({}, {})", b[0], b[1]);
279+
throw except("Invalid image coordinates: ({}, {})", b[0], b[1]);
280280
}
281281
if (a[0] >= b[0] || a[1] >= b[1]) {
282-
throw error("Invalid box coordinates: ({}, {}) to ({}, {})", a[0], a[1], b[0], b[1]);
282+
throw except("Invalid box coordinates: ({}, {}) to ({}, {})", a[0], a[1], b[0], b[1]);
283283
}
284284
}
285285
return sam_prompt{a, b};

src/util/string.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ template <size_t N, typename... Args>
6666
char const* format(fixed_string<N>& dst, char const* fmt, Args&&... args) {
6767
auto it = truncating_iterator(dst.data, N);
6868
auto out = fmt::vformat_to(it, fmt, fmt::make_format_args(args...));
69-
dst.data[N - 1] = 0;
7069
dst.length = std::min(size_t(out - it), N - 1);
70+
dst.data[dst.length] = 0;
7171
return dst.c_str();
7272
}
7373

@@ -79,7 +79,7 @@ String format(char const* fmt, Args&&... args) {
7979
}
8080

8181
template <typename... Args>
82-
exception error(char const* fmt, Args&&... args) {
82+
exception except(char const* fmt, Args&&... args) {
8383
return exception(format<fixed_string<128>>(fmt, std::forward<Args>(args)...));
8484
}
8585

src/visp/birefnet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,14 +588,14 @@ const swin_params swin_l_params = {
588588
swin_params swin_detect_params(model_ref m) {
589589
tensor t = m.find("bb.layers.0.blocks.0.attn.proj.bias");
590590
if (t == nullptr) {
591-
throw error("Failed to detect model parameters");
591+
throw except("Failed to detect model parameters");
592592
}
593593
if (t->ne[0] == 96) {
594594
return swin_t_params;
595595
} else if (t->ne[0] == 192) {
596596
return swin_l_params;
597597
} else {
598-
throw error("Unsupported Swin Transformer embed dim: {}", t->ne[0]);
598+
throw except("Unsupported Swin Transformer embed dim: {}", t->ne[0]);
599599
}
600600
}
601601

src/visp/esrgan.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ esrgan_params esrgan_detect_params(model_ref m) {
102102
// 3 layers per upscale block, each upscales x2, 5 blocks for the rest of the model
103103
p.scale = 1 << ((model_len - 5) / 3);
104104
if (p.scale < 2 || p.scale > 4) {
105-
throw error("Unsupported scale: {}", p.scale);
105+
throw except("Unsupported scale: {}", p.scale);
106106
}
107107
if (p.n_blocks < 1 || p.n_blocks > 23) {
108-
throw error("Invalid number of blocks: {}", p.n_blocks);
108+
throw except("Invalid number of blocks: {}", p.n_blocks);
109109
}
110110
return p;
111111
}

src/visp/image.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ image_data image_load(char const* filepath) {
184184
int channels = 0;
185185
uint8_t* pixels = stbi_load(filepath, &extent[0], &extent[1], &channels, 0);
186186
if (!pixels) {
187-
throw error("Failed to load image {}: {}", filepath, stbi_failure_reason());
187+
throw except("Failed to load image {}: {}", filepath, stbi_failure_reason());
188188
}
189189
image_format format = image_format_from_channels(channels);
190190
return image_data(extent, format, std::unique_ptr<uint8_t[]>(pixels));
@@ -195,12 +195,12 @@ void image_save(image_view const& img, char const* filepath) {
195195

196196
if (!(img.format == image_format::alpha_u8 || img.format == image_format::rgb_u8 ||
197197
img.format == image_format::rgba_u8)) {
198-
throw error("Unsupported image format [{}]", int(img.format));
198+
throw except("Unsupported image format [{}]", int(img.format));
199199
}
200200
int comp = n_channels(img.format);
201201
if (!stbi_write_png(
202202
filepath, img.extent[0], img.extent[1], comp, img.data, img.extent[0] * comp)) {
203-
throw error("Failed to save image {}", filepath);
203+
throw except("Failed to save image {}", filepath);
204204
}
205205
}
206206

@@ -338,7 +338,7 @@ void image_scale(image_view const& img, i32x2 target, image_span const& dst) {
338338
STBIR_COLORSPACE_SRGB, nullptr);
339339
}
340340
if (result == 0) {
341-
throw error(
341+
throw except(
342342
"Failed to resize image {}x{} to {}x{}", img.extent[0], img.extent[1], target[0],
343343
target[1]);
344344
}

src/visp/ml.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ backend_device backend_init(backend_type type) {
5252
backend_device b;
5353
b.handle.reset(ggml_backend_init_by_type(convert(type), nullptr));
5454
if (!b.handle) {
55-
throw error("Failed to initialize backend, no suitable device available");
55+
throw except("Failed to initialize backend, no suitable device available");
5656
}
5757
b.device = ggml_backend_get_device(b.handle.get());
5858

@@ -305,7 +305,7 @@ tensor model_ref::weights(char const* name) const {
305305
if (tensor result = find(name)) {
306306
return result;
307307
}
308-
throw error("tensor not found: {}.{}", prefix.view(), name);
308+
throw except("tensor not found: {}.{}", prefix.view(), name);
309309
}
310310

311311
model_ref model_ref::with_prefix(tensor_name new_prefix) const {
@@ -360,13 +360,13 @@ tensor_data tensor_alloc(tensor x) {
360360
tensor_data tensor_load(tensor x, char const* filepath) {
361361
FILE* file = fopen(filepath, "rb");
362362
if (!file) {
363-
throw error("Failed to open file: {}", filepath);
363+
throw except("Failed to open file: {}", filepath);
364364
}
365365
tensor_data result = tensor_alloc(x);
366366
size_t read = fread(result.data.get(), 1, ggml_nbytes(x), file);
367367
fclose(file);
368368
if (read != ggml_nbytes(x)) {
369-
throw error("Failed to read data from file: {}", filepath);
369+
throw except("Failed to read data from file: {}", filepath);
370370
}
371371
return result;
372372
}

tests/test-image.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace visp {
1010

11-
TEST_CASE(image_formats) {
11+
VISP_TEST(image_formats) {
1212
auto formats = std::array{image_format::rgba_u8, image_format::bgra_u8, image_format::argb_u8,
1313
image_format::rgb_u8, image_format::alpha_u8, image_format::rgba_f32,
1414
image_format::rgb_f32, image_format::alpha_f32};
@@ -36,14 +36,14 @@ TEST_CASE(image_formats) {
3636
}
3737
}
3838

39-
TEST_CASE(image_load) {
39+
VISP_TEST(image_load) {
4040
image_data img = image_load((test_dir().input / "cat-and-hat.jpg").string().c_str());
4141
CHECK(img.extent == i32x2{512, 512});
4242
CHECK(img.format == image_format::rgb_u8);
4343
CHECK(n_bytes(img) == 512 * 512 * 3);
4444
}
4545

46-
TEST_CASE(image_save) {
46+
VISP_TEST(image_save) {
4747
image_data img = image_alloc(i32x2{16, 16}, image_format::rgba_u8);
4848
for (int i = 0; i < 16 * 16; ++i) {
4949
img.data.get()[i * 4 + 0] = 255;
@@ -74,20 +74,20 @@ void test_image_u8_to_f32(
7474
CHECK_IMAGES_EQUAL(output, expected);
7575
}
7676

77-
TEST_CASE(image_alpha_u8_to_alpha_f32) {
77+
VISP_TEST(image_alpha_u8_to_alpha_f32) {
7878
test_image_u8_to_f32(
7979
image_format::alpha_u8, image_format::alpha_f32, //
8080
std::array<uint8_t, 4>{0, 128, 190, 255}, //
8181
std::array<float, 4>{0.05f, 0.3f, 0.4225f, 0.55f});
8282
}
83-
TEST_CASE(image_rgb_u8_to_rgb_f32) {
83+
VISP_TEST(image_rgb_u8_to_rgb_f32) {
8484
test_image_u8_to_f32(
8585
image_format::rgb_u8, image_format::rgb_f32, //
8686
std::array<uint8_t, 12>{0, 128, 192, 255, 0, 128, 128, 255, 0, 128, 64, 255}, //
8787
std::array<float, 12>{
8888
0.05f, 0.7f, -1.05f, 0.55f, 0.2f, -0.8f, 0.3f, 1.2f, -0.3f, 0.3f, 0.45f, -1.3f});
8989
}
90-
TEST_CASE(image_rgba_u8_to_rgb_f32) {
90+
VISP_TEST(image_rgba_u8_to_rgb_f32) {
9191
test_image_u8_to_f32(
9292
image_format::rgba_u8, image_format::rgb_f32, //
9393
std::array<uint8_t, 16>{
@@ -101,7 +101,7 @@ TEST_CASE(image_rgba_u8_to_rgb_f32) {
101101
0.3f, 1.2f, -0.3f, //
102102
0.3f, 0.45f, -1.3f});
103103
}
104-
TEST_CASE(image_rgba_u8_to_rgba_f32) {
104+
VISP_TEST(image_rgba_u8_to_rgba_f32) {
105105
test_image_u8_to_f32(
106106
image_format::rgba_u8, image_format::rgba_f32, //
107107
std::array<uint8_t, 16>{
@@ -115,7 +115,7 @@ TEST_CASE(image_rgba_u8_to_rgba_f32) {
115115
0.3f, 1.2f, -0.3f, 0.9f, 0.3f, //
116116
0.45f, -1.3f, 1.4f});
117117
}
118-
TEST_CASE(image_bgra_u8_to_rgb_f32) {
118+
VISP_TEST(image_bgra_u8_to_rgb_f32) {
119119
test_image_u8_to_f32(
120120
image_format::bgra_u8, image_format::rgb_f32, //
121121
std::array<uint8_t, 16>{
@@ -129,7 +129,7 @@ TEST_CASE(image_bgra_u8_to_rgb_f32) {
129129
0.3f, 1.2f, -0.3f, //
130130
0.3f, 0.45f, -1.3f});
131131
}
132-
TEST_CASE(image_argb_u8_to_rgb_f32) {
132+
VISP_TEST(image_argb_u8_to_rgb_f32) {
133133
test_image_u8_to_f32(
134134
image_format::argb_u8, image_format::rgb_f32, //
135135
std::array<uint8_t, 16>{
@@ -144,7 +144,7 @@ TEST_CASE(image_argb_u8_to_rgb_f32) {
144144
0.3f, 0.45f, -1.3f});
145145
}
146146

147-
TEST_CASE(image_u8_to_f32_tiled_pad) {
147+
VISP_TEST(image_u8_to_f32_tiled_pad) {
148148
std::array<uint8_t, 9> input_data = {0, 0, 102, 0, 0, 255, 0, 0, 102};
149149
std::array<float, 4> expected_data = {1.0f, 1.0f, 0.4f, 0.4f};
150150
image_view input(i32x2{3, 3}, image_format::alpha_u8, input_data);
@@ -159,7 +159,7 @@ TEST_CASE(image_u8_to_f32_tiled_pad) {
159159
CHECK_IMAGES_EQUAL(output, expected);
160160
}
161161

162-
TEST_CASE(image_alpha_f32_to_alpha_u8) {
162+
VISP_TEST(image_alpha_f32_to_alpha_u8) {
163163
std::array<float, 4> input_data{0.0f, 0.3f, 0.4225f, 1.1f};
164164
std::array<uint8_t, 4> expected_data = {0, 76, 107, 255};
165165
image_view input(i32x2{2, 2}, image_format::alpha_f32, input_data.data());
@@ -171,7 +171,7 @@ TEST_CASE(image_alpha_f32_to_alpha_u8) {
171171
CHECK_IMAGES_EQUAL(output, expected);
172172
}
173173

174-
TEST_CASE(image_rgb_f32_to_rgba_u8) {
174+
VISP_TEST(image_rgb_f32_to_rgba_u8) {
175175
std::array<float, 6> input_data{0.0f, 0.31f, -0.51f, 1.0f, 0.2f, 1.8f};
176176
std::array<uint8_t, 8> expected_data = {0, 79, 0, 255, 255, 51, 255, 255};
177177
image_view input(i32x2{2, 1}, image_format::rgb_f32, input_data.data());
@@ -183,7 +183,7 @@ TEST_CASE(image_rgb_f32_to_rgba_u8) {
183183
CHECK_IMAGES_EQUAL(output, expected);
184184
}
185185

186-
TEST_CASE(image_scale) {
186+
VISP_TEST(image_scale) {
187187
image_data img = image_alloc(i32x2{8, 8}, image_format::rgba_u8);
188188
for (int i = 0; i < 8 * 8; ++i) {
189189
img.data[i * 4 + 0] = uint8_t(255);
@@ -202,7 +202,7 @@ TEST_CASE(image_scale) {
202202
}
203203
}
204204

205-
TEST_CASE(image_alpha_composite) {
205+
VISP_TEST(image_alpha_composite) {
206206
std::array<uint8_t, 2 * 2 * 4> fg_data = {255, 0, 0, 255, 0, 255, 0, 255, //
207207
0, 0, 255, 255, 255, 255, 0, 255};
208208
image_view fg{i32x2{2, 2}, image_format::rgba_u8, fg_data};
@@ -222,7 +222,7 @@ TEST_CASE(image_alpha_composite) {
222222
CHECK_IMAGES_EQUAL(output, expected);
223223
}
224224

225-
TEST_CASE(image_blur) {
225+
VISP_TEST(image_blur) {
226226
constexpr i32x2 extent{6, 6};
227227
// clang-format off
228228
std::array<float, extent[0] * extent[1]> input_data = {
@@ -252,7 +252,7 @@ TEST_CASE(image_blur) {
252252
CHECK_IMAGES_EQUAL(output, expected);
253253
}
254254

255-
TEST_CASE(tile_merge) {
255+
VISP_TEST(tile_merge) {
256256
std::array<std::array<f32x3, 5 * 5>, 4> tiles;
257257
for (int t = 0; t < 4; ++t) {
258258
float v = float(t);
@@ -290,7 +290,7 @@ TEST_CASE(tile_merge) {
290290
CHECK_IMAGES_EQUAL(dst_span, expected);
291291
}
292292

293-
TEST_CASE(tile_merge_blending) {
293+
VISP_TEST(tile_merge_blending) {
294294
std::array<f32x3, 22 * 19> dst{};
295295
auto dst_span = image_span({22, 19}, dst);
296296

0 commit comments

Comments
 (0)