Commit d70a25c6 authored by Swann Perarnau's avatar Swann Perarnau
Browse files

[refactor/test] speed up and improve bitmap tests

The bitmap tests were slowing down the entire pipeline, while at the
same time missing important checks on the inputs. This version is a bit
more exhaustive, while also speeding up the test by only checking the
corner-cases (first bits, last bits, partial ranges, overlapping
ranges).
parent 3eb5ca16
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
/** The type used to store bits **/ /** The type used to store bits **/
#define AML_BITMAP_TYPE unsigned long #define AML_BITMAP_TYPE unsigned long
/** The number of basic type elements used to store bits **/ /** The number of basic type elements used to store bits **/
#define AML_BITMAP_SIZE (AML_BITMAP_BYTES/sizeof(AML_BITMAP_TYPE)) #define AML_BITMAP_SIZE ((int)(AML_BITMAP_BYTES/sizeof(AML_BITMAP_TYPE)))
/** The number of bits held in each basic type element **/ /** The number of bits held in each basic type element **/
#define AML_BITMAP_NBITS (8 * sizeof(AML_BITMAP_TYPE)) #define AML_BITMAP_NBITS ((int)(8 * sizeof(AML_BITMAP_TYPE)))
/** /**
* aml_bitmap is a static array of elements wrapped in a structure. * aml_bitmap is a static array of elements wrapped in a structure.
...@@ -50,13 +50,13 @@ void aml_bitmap_copy(struct aml_bitmap *dst, const struct aml_bitmap *src); ...@@ -50,13 +50,13 @@ void aml_bitmap_copy(struct aml_bitmap *dst, const struct aml_bitmap *src);
* Empty a bitmap with all bits cleared. * Empty a bitmap with all bits cleared.
* @param bitmap: The bitmap to set. * @param bitmap: The bitmap to set.
**/ **/
void aml_bitmap_zero(struct aml_bitmap *bitmap); int aml_bitmap_zero(struct aml_bitmap *bitmap);
/** /**
* Fill a bitmap with all bits set. * Fill a bitmap with all bits set.
* @param bitmap: The bitmap to set. * @param bitmap: The bitmap to set.
**/ **/
void aml_bitmap_fill(struct aml_bitmap *bitmap); int aml_bitmap_fill(struct aml_bitmap *bitmap);
/** /**
* Check whether a bit in bitmap is set. * Check whether a bit in bitmap is set.
...@@ -135,7 +135,7 @@ int aml_bitmap_clear_range(struct aml_bitmap *bitmap, ...@@ -135,7 +135,7 @@ int aml_bitmap_clear_range(struct aml_bitmap *bitmap,
* @param bitmap: The bitmap to inspect. * @param bitmap: The bitmap to inspect.
* @return The number of bits set in bitmap. * @return The number of bits set in bitmap.
**/ **/
unsigned long aml_bitmap_nset(const struct aml_bitmap *bitmap); int aml_bitmap_nset(const struct aml_bitmap *bitmap);
/** /**
* Copy a unsigned long array used as a bitmap into an actual bitmap. * Copy a unsigned long array used as a bitmap into an actual bitmap.
......
...@@ -50,13 +50,18 @@ void aml_bitmap_copy_to_ulong(const struct aml_bitmap *dst, ...@@ -50,13 +50,18 @@ void aml_bitmap_copy_to_ulong(const struct aml_bitmap *dst,
src[AML_BITMAP_NTH(i)] |= (1UL << AML_BITMAP_ITH(i)); src[AML_BITMAP_NTH(i)] |= (1UL << AML_BITMAP_ITH(i));
} }
void aml_bitmap_zero(struct aml_bitmap *bitmap) int aml_bitmap_zero(struct aml_bitmap *bitmap)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
memset(bitmap, 0, sizeof(struct aml_bitmap)); memset(bitmap, 0, sizeof(struct aml_bitmap));
return 0;
} }
int aml_bitmap_iszero(const struct aml_bitmap *bitmap) int aml_bitmap_iszero(const struct aml_bitmap *bitmap)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
for (unsigned int i = 0; i < AML_BITMAP_SIZE; i++) for (unsigned int i = 0; i < AML_BITMAP_SIZE; i++)
if (bitmap->mask[i] != AML_BITMAP_EMPTY) if (bitmap->mask[i] != AML_BITMAP_EMPTY)
return 0; return 0;
...@@ -65,35 +70,46 @@ int aml_bitmap_iszero(const struct aml_bitmap *bitmap) ...@@ -65,35 +70,46 @@ int aml_bitmap_iszero(const struct aml_bitmap *bitmap)
int aml_bitmap_isfull(const struct aml_bitmap *bitmap) int aml_bitmap_isfull(const struct aml_bitmap *bitmap)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
for (unsigned int i = 0; i < AML_BITMAP_SIZE; i++) for (unsigned int i = 0; i < AML_BITMAP_SIZE; i++)
if (bitmap->mask[i] != AML_BITMAP_FULL) if (bitmap->mask[i] != AML_BITMAP_FULL)
return 0; return 0;
return 1; return 1;
} }
void aml_bitmap_fill(struct aml_bitmap *bitmap) int aml_bitmap_fill(struct aml_bitmap *bitmap)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
memset(bitmap, ~0, sizeof(struct aml_bitmap)); memset(bitmap, ~0, sizeof(struct aml_bitmap));
return 0;
} }
int aml_bitmap_isset(const struct aml_bitmap *bitmap, const unsigned int i) int aml_bitmap_isset(const struct aml_bitmap *bitmap, const unsigned int i)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
if (i >= AML_BITMAP_MAX) if (i >= AML_BITMAP_MAX)
return -1; return -AML_EINVAL;
return (bitmap->mask[AML_BITMAP_NTH(i)] & return (bitmap->mask[AML_BITMAP_NTH(i)] &
(1UL << AML_BITMAP_ITH(i))) > 0UL; (1UL << AML_BITMAP_ITH(i))) > 0UL;
} }
int aml_bitmap_set(struct aml_bitmap *bitmap, const unsigned int i) int aml_bitmap_set(struct aml_bitmap *bitmap, const unsigned int i)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
if (i >= AML_BITMAP_MAX) if (i >= AML_BITMAP_MAX)
return -1; return -AML_EINVAL;
bitmap->mask[AML_BITMAP_NTH(i)] |= (1UL << AML_BITMAP_ITH(i)); bitmap->mask[AML_BITMAP_NTH(i)] |= (1UL << AML_BITMAP_ITH(i));
return 0; return 0;
} }
int aml_bitmap_isequal(const struct aml_bitmap *a, const struct aml_bitmap *b) int aml_bitmap_isequal(const struct aml_bitmap *a, const struct aml_bitmap *b)
{ {
if (a == NULL || b == NULL)
return -AML_EINVAL;
for (unsigned int i = 0; i < AML_BITMAP_SIZE; i++) for (unsigned int i = 0; i < AML_BITMAP_SIZE; i++)
if (a->mask[i] != b->mask[i]) if (a->mask[i] != b->mask[i])
return 0; return 0;
...@@ -102,8 +118,10 @@ int aml_bitmap_isequal(const struct aml_bitmap *a, const struct aml_bitmap *b) ...@@ -102,8 +118,10 @@ int aml_bitmap_isequal(const struct aml_bitmap *a, const struct aml_bitmap *b)
int aml_bitmap_clear(struct aml_bitmap *bitmap, const unsigned int i) int aml_bitmap_clear(struct aml_bitmap *bitmap, const unsigned int i)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
if (i >= AML_BITMAP_MAX) if (i >= AML_BITMAP_MAX)
return -1; return -AML_EINVAL;
bitmap->mask[AML_BITMAP_NTH(i)] &= ~(1UL << AML_BITMAP_ITH(i)); bitmap->mask[AML_BITMAP_NTH(i)] &= ~(1UL << AML_BITMAP_ITH(i));
return 0; return 0;
} }
...@@ -111,8 +129,10 @@ int aml_bitmap_clear(struct aml_bitmap *bitmap, const unsigned int i) ...@@ -111,8 +129,10 @@ int aml_bitmap_clear(struct aml_bitmap *bitmap, const unsigned int i)
int aml_bitmap_set_range(struct aml_bitmap *bitmap, int aml_bitmap_set_range(struct aml_bitmap *bitmap,
const unsigned int i, const unsigned int ii) const unsigned int i, const unsigned int ii)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
if (i >= AML_BITMAP_MAX || ii >= AML_BITMAP_MAX || i > ii) if (i >= AML_BITMAP_MAX || ii >= AML_BITMAP_MAX || i > ii)
return -1; return -AML_EINVAL;
if (i == ii) if (i == ii)
return aml_bitmap_set(bitmap, i); return aml_bitmap_set(bitmap, i);
...@@ -136,8 +156,10 @@ int aml_bitmap_set_range(struct aml_bitmap *bitmap, ...@@ -136,8 +156,10 @@ int aml_bitmap_set_range(struct aml_bitmap *bitmap,
int aml_bitmap_clear_range(struct aml_bitmap *bitmap, int aml_bitmap_clear_range(struct aml_bitmap *bitmap,
const unsigned int i, const unsigned int ii) const unsigned int i, const unsigned int ii)
{ {
if (bitmap == NULL)
return -AML_EINVAL;
if (i >= AML_BITMAP_MAX || ii >= AML_BITMAP_MAX || i > ii) if (i >= AML_BITMAP_MAX || ii >= AML_BITMAP_MAX || i > ii)
return -1; return -AML_EINVAL;
if (i == ii) if (i == ii)
return aml_bitmap_clear(bitmap, i); return aml_bitmap_clear(bitmap, i);
...@@ -158,15 +180,18 @@ int aml_bitmap_clear_range(struct aml_bitmap *bitmap, ...@@ -158,15 +180,18 @@ int aml_bitmap_clear_range(struct aml_bitmap *bitmap,
return 0; return 0;
} }
unsigned long aml_bitmap_nset(const struct aml_bitmap *bitmap) int aml_bitmap_nset(const struct aml_bitmap *bitmap)
{ {
unsigned long i, b, n;
unsigned long test = 1UL; unsigned long test = 1UL;
unsigned long nset = 0; int nset = 0;
for (n = 0; n < AML_BITMAP_SIZE; n++) { if (bitmap == NULL)
b = bitmap->mask[n]; return -AML_EINVAL;
for (i = 0; i < AML_BITMAP_NBITS; i++) {
for (int n = 0; n < AML_BITMAP_SIZE; n++) {
unsigned long b = bitmap->mask[n];
for (int i = 0; i < AML_BITMAP_NBITS; i++) {
nset += b & test ? 1 : 0; nset += b & test ? 1 : 0;
b = b >> 1; b = b >> 1;
} }
...@@ -176,11 +201,12 @@ unsigned long aml_bitmap_nset(const struct aml_bitmap *bitmap) ...@@ -176,11 +201,12 @@ unsigned long aml_bitmap_nset(const struct aml_bitmap *bitmap)
int aml_bitmap_last(const struct aml_bitmap *bitmap) int aml_bitmap_last(const struct aml_bitmap *bitmap)
{ {
if (bitmap == NULL)
return -1;
int n; int n;
unsigned int i = 0; unsigned int i = 0;
if (bitmap == NULL)
return -AML_EINVAL;
for (n = AML_BITMAP_SIZE - 1; n >= 0 && bitmap->mask[n] == 0; n--) for (n = AML_BITMAP_SIZE - 1; n >= 0 && bitmap->mask[n] == 0; n--)
; ;
...@@ -301,6 +327,9 @@ int aml_bitmap_from_string(struct aml_bitmap *bitmap, const char *bitmap_str) ...@@ -301,6 +327,9 @@ int aml_bitmap_from_string(struct aml_bitmap *bitmap, const char *bitmap_str)
int aml_bitmap_create(struct aml_bitmap **map) int aml_bitmap_create(struct aml_bitmap **map)
{ {
if (map == NULL)
return -AML_EINVAL;
struct aml_bitmap *b = calloc(1, sizeof(struct aml_bitmap)); struct aml_bitmap *b = calloc(1, sizeof(struct aml_bitmap));
if (b == NULL) { if (b == NULL) {
...@@ -319,6 +348,9 @@ int aml_bitmap_create(struct aml_bitmap **map) ...@@ -319,6 +348,9 @@ int aml_bitmap_create(struct aml_bitmap **map)
**/ **/
void aml_bitmap_destroy(struct aml_bitmap **map) void aml_bitmap_destroy(struct aml_bitmap **map)
{ {
if (map == NULL)
return;
free(*map); free(*map);
*map = NULL; *map = NULL;
} }
......
...@@ -11,108 +11,163 @@ ...@@ -11,108 +11,163 @@
#include "aml.h" #include "aml.h"
#include <assert.h> #include <assert.h>
void test_bitmap_fill(){ /* set of bits that are interesting to test. In increasing order by design, for
unsigned long i; * the range tests.
struct aml_bitmap b; * - first one
aml_bitmap_fill(&b); * - middle of a backing element
for(i = 0; i < AML_BITMAP_MAX; i++) * - last one in the middle of the backing array
assert(aml_bitmap_isset(&b, i)); * - middle of a backing element
assert(aml_bitmap_nset(&b) == AML_BITMAP_MAX); * - first one in the middle of the backing array
} * - middle of a backing element
* - last one
*/
#define NTESTS 7
#define TESTS_IDX {0, AML_BITMAP_NBITS + 16, \
(2*AML_BITMAP_NBITS) - 1, (2*AML_BITMAP_NBITS) + 16, \
3*AML_BITMAP_NBITS, (3*AML_BITMAP_NBITS) + 16, AML_BITMAP_MAX - 1}
#define TESTS_OFF {0, 1, 1, 2, 3, 3, AML_BITMAP_SIZE - 1}
void test_bitmap_zero(){ int main(void)
unsigned long i; {
struct aml_bitmap b; struct aml_bitmap *bitmap;
aml_bitmap_zero(&b); int idx[NTESTS] = TESTS_IDX;
for(i = 0; i < AML_BITMAP_MAX; i++) int off[NTESTS] = TESTS_OFF;
assert(!aml_bitmap_isset(&b, i));
assert(aml_bitmap_nset(&b) == 0);
}
void test_bitmap_set(){ /* create/destroy should fail on NULL */
unsigned long i,j; assert(aml_bitmap_create(NULL) == -AML_EINVAL);
struct aml_bitmap b; aml_bitmap_destroy(NULL);
aml_bitmap_zero(&b); /* create should succeed with a pointer */
for(i = 0; i < AML_BITMAP_MAX; i++){ assert(aml_bitmap_create(&bitmap) == AML_SUCCESS);
aml_bitmap_set(&b, i); assert(bitmap != NULL);
assert(aml_bitmap_isset(&b, i));
for(j = 0; j < i; j++) /* access the mask just to be sure */
assert(!aml_bitmap_isset(&b, j)); assert(bitmap->mask[0] == 0);
for(j = i+1; j < AML_BITMAP_MAX; j++) aml_bitmap_destroy(&bitmap);
assert(!aml_bitmap_isset(&b, j)); assert(bitmap == NULL);
assert(aml_bitmap_nset(&b) == 1); /* keep a bitmap on for the rest of the tests */
aml_bitmap_clear(&b, i); assert(aml_bitmap_create(&bitmap) == AML_SUCCESS);
assert(!aml_bitmap_isset(&b, i));
} /* zero should work */
} assert(aml_bitmap_zero(NULL) == -AML_EINVAL);
memset(bitmap->mask, 255, AML_BITMAP_BYTES);
assert(aml_bitmap_zero(bitmap) == AML_SUCCESS);
for (size_t i = 0; i < AML_BITMAP_SIZE; i++)
assert(bitmap->mask[i] == 0);
/* iszero/isfull (1) */
assert(aml_bitmap_iszero(NULL) == -AML_EINVAL);
assert(aml_bitmap_isfull(NULL) == -AML_EINVAL);
assert(aml_bitmap_iszero(bitmap));
assert(!aml_bitmap_isfull(bitmap));
/* nset (1) */
assert(aml_bitmap_nset(bitmap) == 0);
/* fill should work */
assert(aml_bitmap_fill(NULL) == -AML_EINVAL);
assert(aml_bitmap_fill(bitmap) == AML_SUCCESS);
for (size_t i = 0; i < AML_BITMAP_SIZE; i++)
assert(bitmap->mask[i] != 0);
assert(!aml_bitmap_iszero(bitmap));
assert(aml_bitmap_isfull(bitmap));
/* nset (2) */
assert(aml_bitmap_nset(bitmap) == AML_BITMAP_MAX);
void test_bitmap_clear(){ /* set / clear */
unsigned long i,j; aml_bitmap_zero(bitmap);
struct aml_bitmap b; assert(aml_bitmap_set(NULL, 0) == -AML_EINVAL);
aml_bitmap_fill(&b); assert(aml_bitmap_set(NULL, AML_BITMAP_MAX) == -AML_EINVAL);
for(i = 0; i < AML_BITMAP_MAX; i++){ for (int i = 0; i < NTESTS; i++) {
aml_bitmap_clear(&b, i); aml_bitmap_zero(bitmap);
assert(!aml_bitmap_isset(&b, i)); assert(aml_bitmap_set(bitmap, idx[i]) == AML_SUCCESS);
assert(bitmap->mask[off[i]] != 0);
for(j = 0; j < i; j++) /* nset (3) */
assert(aml_bitmap_isset(&b, j)); assert(aml_bitmap_nset(bitmap) == 1);
for(j = i+1; j < AML_BITMAP_MAX; j++) /* clear that offset and check for zero */
assert(aml_bitmap_isset(&b, j)); bitmap->mask[off[i]] = 0;
assert(aml_bitmap_iszero(bitmap));
assert(aml_bitmap_nset(&b) == (AML_BITMAP_MAX-1));
aml_bitmap_set(&b, i);
assert(aml_bitmap_isset(&b, i));
} }
}
void test_bitmap_set_range(){ /* same logic for clear */
unsigned long i, ii, j; assert(aml_bitmap_clear(NULL, 0) == -AML_EINVAL);
struct aml_bitmap b; assert(aml_bitmap_clear(NULL, AML_BITMAP_MAX) == -AML_EINVAL);
aml_bitmap_zero(&b); for (int i = 0; i < NTESTS; i++) {
for(i = 0; i < AML_BITMAP_MAX; i++){ aml_bitmap_fill(bitmap);
for(ii = i+1; ii < AML_BITMAP_MAX; ii++){ assert(aml_bitmap_clear(bitmap, idx[i]) == AML_SUCCESS);
assert(aml_bitmap_set_range(&b, i, ii) == 0); assert(bitmap->mask[off[i]] != ~0UL);
assert(aml_bitmap_nset(&b) == (1 + ii - i)); /* nset (4) */
for(j = 0; j < i; j++) assert(aml_bitmap_nset(bitmap) == AML_BITMAP_MAX - 1);
assert(!aml_bitmap_isset(&b, j)); /* set that offset and check for full */
for(j = i; j <= ii; j++) bitmap->mask[off[i]] = ~0UL;
assert(aml_bitmap_isset(&b, j)); assert(aml_bitmap_isfull(bitmap));
for(j = ii+1; j < AML_BITMAP_MAX; j++)
assert(!aml_bitmap_isset(&b, j));
aml_bitmap_zero(&b);
} }
/* idem for isset */
assert(aml_bitmap_isset(NULL, 0) == -AML_EINVAL);
assert(aml_bitmap_isset(bitmap, AML_BITMAP_MAX) == -AML_EINVAL);
aml_bitmap_zero(bitmap);
for (int i = 1; i < NTESTS; i++) {
aml_bitmap_set(bitmap, idx[i]);
assert(aml_bitmap_isset(bitmap, idx[i]));
assert(!aml_bitmap_isset(bitmap, idx[i-1]));
aml_bitmap_clear(bitmap, idx[i]);
assert(!aml_bitmap_isset(bitmap, idx[i]));
assert(!aml_bitmap_isset(bitmap, idx[i-1]));
} }
}
void test_bitmap_clear_range(){ /* bad input for ranges (out-of-bounds, reverse indexes) */
unsigned long i, ii, j; assert(aml_bitmap_set_range(NULL, 0, 1) == -AML_EINVAL);
struct aml_bitmap b; assert(aml_bitmap_set_range(bitmap, 0, AML_BITMAP_MAX) == -AML_EINVAL);
aml_bitmap_fill(&b); assert(aml_bitmap_set_range(bitmap, AML_BITMAP_MAX,
for(i = 0; i < AML_BITMAP_MAX; i++){ AML_BITMAP_MAX+1) == -AML_EINVAL);
for(ii = i+1; ii < AML_BITMAP_MAX; ii++){ assert(aml_bitmap_set_range(bitmap, AML_BITMAP_MAX, 0) == -AML_EINVAL);
assert(aml_bitmap_clear_range(&b, i, ii) == 0); assert(aml_bitmap_set_range(bitmap, 1, 0) == -AML_EINVAL);
assert(aml_bitmap_nset(&b) == (AML_BITMAP_MAX-ii+i-1));
for(j = 0; j < i; j++) for (int i = 0; i < NTESTS; i++) {
assert(aml_bitmap_isset(&b, j)); for (int j = i; j < NTESTS; j++) {
for(j = i; j <= ii; j++) aml_bitmap_zero(bitmap);
assert(!aml_bitmap_isset(&b, j)); assert(aml_bitmap_set_range(bitmap, idx[i], idx[j]) ==
for(j = ii+1; j < AML_BITMAP_MAX; j++) AML_SUCCESS);
assert(aml_bitmap_isset(&b, j)); for (int k = 0; k < idx[i]; k++)
aml_bitmap_fill(&b); assert(!aml_bitmap_isset(bitmap, k));
for (int k = idx[i]; k <= idx[j]; k++)
assert(aml_bitmap_isset(bitmap, k));
for (int k = idx[j]+1; k < AML_BITMAP_MAX; k++)
assert(!aml_bitmap_isset(bitmap, k));
/* nset (5) */
assert(aml_bitmap_nset(bitmap) == 1 + idx[j] - idx[i]);
} }
} }
}
int main(){ /* same logic for clear */
test_bitmap_fill(); assert(aml_bitmap_clear_range(NULL, 0, 1) == -AML_EINVAL);
test_bitmap_zero(); assert(aml_bitmap_clear_range(bitmap, 0, AML_BITMAP_MAX) ==
test_bitmap_set(); -AML_EINVAL);
test_bitmap_clear(); assert(aml_bitmap_clear_range(bitmap, AML_BITMAP_MAX,
test_bitmap_set_range(); AML_BITMAP_MAX+1) == -AML_EINVAL);
test_bitmap_clear_range(); assert(aml_bitmap_clear_range(bitmap, AML_BITMAP_MAX, 0) ==
-AML_EINVAL);
assert(aml_bitmap_clear_range(bitmap, 1, 0) == -AML_EINVAL);
for (int i = 0; i < NTESTS; i++) {
for (int j = i; j < NTESTS; j++) {
aml_bitmap_fill(bitmap);
assert(aml_bitmap_clear_range(bitmap, idx[i], idx[j]) ==
AML_SUCCESS);
for (int k = 0; k < idx[i]; k++)
assert(aml_bitmap_isset(bitmap, k));
for (int k = idx[i]; k <= idx[j]; k++)
assert(!aml_bitmap_isset(bitmap, k));
for (int k = idx[j]+1; k < AML_BITMAP_MAX; k++)
assert(aml_bitmap_isset(bitmap, k));
assert(aml_bitmap_nset(bitmap) ==
AML_BITMAP_MAX - idx[j] + idx[i] - 1);
}
}
aml_bitmap_destroy(&bitmap);
return 0; return 0;
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment