Skip to content

Commit 3856f13

Browse files
committed
alg_update_reference_frame: test harness: directly compare functions
Directly run two functions on the same input and check whether they give the same output; don't just rely on printing a few numbers to the screen and eyeballing the results.
1 parent 57ca38b commit 3856f13

File tree

1 file changed

+73
-30
lines changed

1 file changed

+73
-30
lines changed

alg/tests/test_alg_update_reference_frame.c

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,59 @@ clean (struct context *ctx)
5555
ctx->imgs.motionsize = WIDTH * HEIGHT;
5656
}
5757

58+
static int
59+
equal_output (struct context *ctx, int action, void (*func_a)(struct context *, int), void (*func_b)(struct context *, int))
60+
{
61+
int i, ret = 1;
62+
struct context cxs[2];
63+
64+
for (i = 0; i < 2; i++)
65+
{
66+
/* Copy original context: */
67+
memcpy(&cxs[i], ctx, sizeof(*ctx));
68+
memcpy(&cxs[i].imgs, &ctx->imgs, sizeof(ctx->imgs));
69+
70+
/* Copy the original image structures: */
71+
#define CPY(x) cxs[i].imgs.x = malloc(ctx->imgs.size * sizeof(*ctx->imgs.x)); memcpy(cxs[i].imgs.x, ctx->imgs.x, ctx->imgs.size * sizeof(*ctx->imgs.x));
72+
CPY(ref)
73+
CPY(out)
74+
CPY(image_virgin)
75+
CPY(smartmask_final)
76+
CPY(ref_dyn)
77+
#undef CPY
78+
}
79+
/* Run both functions on their own copy: */
80+
func_a(&cxs[0], action);
81+
func_b(&cxs[1], action);
82+
83+
/* Compare image outputs: */
84+
#define CMP(x) if (memcmp(cxs[0].imgs.x, cxs[1].imgs.x, sizeof(*cxs[0].imgs.x)) != 0) { ret = 0; goto out; }
85+
CMP(ref)
86+
CMP(ref_dyn)
87+
#undef CMP
88+
89+
out: /* Free memory, return: */
90+
for (i = 0; i < 2; i++) {
91+
free(cxs[i].imgs.ref);
92+
free(cxs[i].imgs.out);
93+
free(cxs[i].imgs.image_virgin);
94+
free(cxs[i].imgs.smartmask_final);
95+
free(cxs[i].imgs.ref_dyn);
96+
}
97+
return ret;
98+
}
99+
58100
static void
59-
permutate (int action, void (*func)(struct context *, int))
101+
permutate (int action, void (*func_a)(struct context *, int), void (*func_b)(struct context *, int))
60102
{
61-
unsigned char ref[16];
62-
unsigned char out[16];
63-
unsigned char image_virgin[16];
64-
unsigned char smartmask_final[16];
65-
uint16_t ref_dyn[16];
103+
#define STRIPSZ 41
104+
105+
unsigned char ref[STRIPSZ];
106+
unsigned char out[STRIPSZ];
107+
unsigned char image_virgin[STRIPSZ];
108+
unsigned char smartmask_final[STRIPSZ];
109+
uint16_t ref_dyn[STRIPSZ];
66110
struct context ctx;
67-
unsigned int ref_cksum;
68-
unsigned int ref_dyn_cksum;
69111

70112
int i, iter_ref_dyn, iter_smartmask, iter_image_virgin, iter_out, iter_ref;
71113

@@ -76,8 +118,8 @@ permutate (int action, void (*func)(struct context *, int))
76118
ctx.imgs.image_virgin = image_virgin;
77119
ctx.imgs.smartmask_final = smartmask_final;
78120
ctx.imgs.ref_dyn = ref_dyn;
79-
ctx.imgs.size = 16;
80-
ctx.imgs.motionsize = 16;
121+
ctx.imgs.size = STRIPSZ;
122+
ctx.imgs.motionsize = STRIPSZ;
81123

82124
/* For the purposes of the routine, smartmask is zero or nonzero: */
83125
for (iter_smartmask = 0; iter_smartmask < 2; iter_smartmask++) {
@@ -87,35 +129,35 @@ permutate (int action, void (*func)(struct context *, int))
87129
for (iter_out = 0; iter_out < 2; iter_out++) {
88130
memset(out, iter_out, ctx.imgs.size);
89131

90-
ref_cksum = 0;
91-
ref_dyn_cksum = 0;
92-
93132
for (iter_image_virgin = 0; iter_image_virgin < 256; iter_image_virgin++) {
94-
memset(image_virgin, iter_image_virgin, ctx.imgs.size);
95-
133+
for (i = 0; i < ctx.imgs.size; i++) {
134+
image_virgin[i] = iter_image_virgin + i;
135+
}
96136
/* ref_dyn has a limited range: */
97137
for (iter_ref_dyn = 0; iter_ref_dyn < 10; iter_ref_dyn++) {
98-
for (i = 0; i < 16; i++) {
99-
ref_dyn[i] = iter_ref_dyn + 1;
138+
for (i = 0; i < ctx.imgs.size; i++) {
139+
ref_dyn[i] = iter_ref_dyn + i;
100140
}
101141
for (iter_ref = 0; iter_ref < 256; iter_ref++) {
102-
memset(ref, iter_ref, ctx.imgs.size);
103-
func(&ctx, action);
104-
ref_cksum += ref[0];
105-
106-
for (i = 0; i < 16; i++) {
107-
ref_dyn_cksum += ref_dyn[i];
142+
for (i = 0; i < ctx.imgs.size; i++) {
143+
ref[i] = iter_ref + i;
144+
}
145+
/* For this permutation, check that both functions
146+
* return the same output data: */
147+
if (equal_output(&ctx, action, func_a, func_b) == 0) {
148+
printf("Functions do NOT match!\n");
149+
return;
108150
}
109151
}
110152
}
111153
}
112-
printf("%d %d\n", ref_cksum, ref_dyn_cksum);
113154
}
114155
}
156+
printf("Functions MATCH\n");
115157
}
116158

117159
static void
118-
testsuite (char *name, struct context *ctx, int action, void (*func)(struct context *, int))
160+
timing (char *name, struct context *ctx, int action, void (*func)(struct context *, int))
119161
{
120162
int i;
121163
float total_time = 0.0f;
@@ -132,8 +174,6 @@ testsuite (char *name, struct context *ctx, int action, void (*func)(struct cont
132174

133175
/* Print bogus value to prevent the loop from being optimized out: */
134176
printf("Value: %d\nTime: %.4f sec\n", ctx->imgs.ref[0], total_time);
135-
136-
permutate(action, func);
137177
}
138178

139179
#define UPDATE_REF_FRAME 1
@@ -151,9 +191,12 @@ main ()
151191

152192
init(&ctx);
153193

154-
testsuite("plain", &ctx, UPDATE_REF_FRAME, alg_update_reference_frame_plain);
155-
testsuite("plain, SSE2 algorithm demo", &ctx, UPDATE_REF_FRAME, alg_update_reference_frame_sse2_algo);
156-
testsuite("SSE2", &ctx, UPDATE_REF_FRAME, alg_update_reference_frame_sse2);
194+
timing("plain", &ctx, UPDATE_REF_FRAME, alg_update_reference_frame_plain);
195+
timing("plain, SSE2 algorithm demo", &ctx, UPDATE_REF_FRAME, alg_update_reference_frame_sse2_algo);
196+
timing("SSE2", &ctx, UPDATE_REF_FRAME, alg_update_reference_frame_sse2);
197+
198+
permutate(UPDATE_REF_FRAME, alg_update_reference_frame_plain, alg_update_reference_frame_sse2_algo);
199+
permutate(UPDATE_REF_FRAME, alg_update_reference_frame_plain, alg_update_reference_frame_sse2);
157200

158201
free(ctx.imgs.ref);
159202
free(ctx.imgs.out);

0 commit comments

Comments
 (0)