Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to assert on const data #554

Open
wants to merge 8 commits into
base: bleeding
Choose a base branch
from
2 changes: 1 addition & 1 deletion include/criterion/internal/assert/op.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@
#define CRI_ASSERT_OP_TYPE_TAGGED(Type, Var, Name, MkNode, Val) Type
#define CRI_ASSERT_OP_TYPE_SINGLE(Type, Var, Name, MkNode, Val) Type

#define CRI_ASSERT_OP_ARRTYPE_TAGGED(Type, Var, Name, MkNode, Val) Type *
#define CRI_ASSERT_OP_ARRTYPE_TAGGED(Type, Var, Name, MkNode, Val) Type const *
#define CRI_ASSERT_OP_ARRTYPE_SINGLE(Type, Var, Name, MkNode, Val) Type

#define CRI_ASSERT_OPKIND(Kind, Type, Var, Name, MkNode, Val) Kind
Expand Down
48 changes: 27 additions & 21 deletions include/criterion/internal/assert/tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@

#define CRI_ASSERT_TYPE_TAG(Tag) CR_EXPAND(CRI_ASSERT_TYPE_TAG_(Tag))
#define CRI_ASSERT_TYPE_TAG_(Tag) CRI_IF_DEFINED_NODEFER(CRI_ASSERT_TEST_TAG_ ## Tag, CR_VA_HEAD(CRI_ASSERT_TYPE_TAG_ ## Tag), , CRI_ASSERT_TYPE_TAG_UNKNOWN, (Tag))
#define CRI_ASSERT_MUT_TYPE_TAG(Tag) CR_EXPAND(CRI_ASSERT_MUT_TYPE_TAG_(Tag))
#define CRI_ASSERT_MUT_TYPE_TAG_(Tag) CRI_IF_DEFINED_NODEFER(CRI_ASSERT_TEST_TAG_ ## Tag, CR_VA_HEAD(CRI_ASSERT_MUT_TYPE_TAG_ ## Tag), , CRI_ASSERT_TYPE_TAG_UNKNOWN, (Tag))

#define CRI_USER_TAG_ID(Id, Tag) CR_CONCAT(CR_CONCAT(cr_user_, CRI_ASSERT_TYPE_TAG_ID(Tag)), _ ## Id)

Expand Down Expand Up @@ -127,15 +129,16 @@

#define CRI_ASSERT_TEST_TAG_ptr ,
#define CRI_ASSERT_TEST_TAGC_ptr() ,
#define CRI_ASSERT_TYPE_TAG_ptr void *,
#define CRI_ASSERT_TYPE_TAG_ptr const void *,
#define CRI_ASSERT_TYPE_TAG_ID_ptr ptr,

#define CRI_ASSERT_TEST_TAG_str ,
#define CRI_ASSERT_TEST_TAGC_str() ,
#ifdef __cplusplus
# define CRI_ASSERT_TYPE_TAG_str std::string,
#else
# define CRI_ASSERT_TYPE_TAG_str char *,
# define CRI_ASSERT_TYPE_TAG_str const char *,
# define CRI_ASSERT_MUT_TYPE_TAG_str char *,
#endif
#define CRI_ASSERT_TYPE_TAG_ID_str str,

Expand All @@ -144,7 +147,8 @@
#ifdef __cplusplus
# define CRI_ASSERT_TYPE_TAG_wcs std::wstring,
#else
# define CRI_ASSERT_TYPE_TAG_wcs wchar_t *,
# define CRI_ASSERT_TYPE_TAG_wcs const wchar_t *,
# define CRI_ASSERT_MUT_TYPE_TAG_wcs wchar_t *,
#endif
#define CRI_ASSERT_TYPE_TAG_ID_wcs wcs,

Expand Down Expand Up @@ -195,42 +199,44 @@

#define CRI_ASSERT_DECLARE_NATIVE_CMP_FN(Tag) \
static inline int CRI_USER_TAG_ID(lt, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *actual, \
CRI_ASSERT_TYPE_TAG(Tag) *expected) \
CRI_ASSERT_TYPE_TAG(Tag) const *actual, \
CRI_ASSERT_TYPE_TAG(Tag) const *expected) \
{ \
return *actual < *expected; \
} \
static inline int CRI_USER_TAG_ID(eq, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *actual, \
CRI_ASSERT_TYPE_TAG(Tag) *expected) \
CRI_ASSERT_TYPE_TAG(Tag) const *actual, \
CRI_ASSERT_TYPE_TAG(Tag) const *expected) \
{ \
return *actual == *expected; \
} \
static inline int CRI_USER_TAG_ID(zero, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *val) \
CRI_ASSERT_TYPE_TAG(Tag) const *val) \
{ \
return !*val; \
}

#define CRI_ASSERT_DECLARE_NATIVE_FN(Tag, Fmt) \
CRI_ASSERT_DECLARE_NATIVE_CMP_FN(Tag) \
static inline char *CRI_USER_TAG_ID(tostr, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *e) \
CRI_ASSERT_TYPE_TAG(Tag) const *e) \
{ \
char *str = NULL; \
cr_asprintf(&str, "%" Fmt, *e); \
return str; \
}

#define CRI_ASSERT_DECLARE_STR_FN(Tag, Prefix, Fmt) \
CR_API int CRI_USER_TAG_ID(lt, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *actual, \
CRI_ASSERT_TYPE_TAG(Tag) *expected); \
CR_API int CRI_USER_TAG_ID(eq, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *actual, \
CRI_ASSERT_TYPE_TAG(Tag) *expected); \
CR_API int CRI_USER_TAG_ID(zero, Tag)(CRI_ASSERT_TYPE_TAG(Tag) *val); \
CR_API char *CRI_USER_TAG_ID(tostr, Tag)(CRI_ASSERT_TYPE_TAG(Tag) *e);
#define CRI_ASSERT_DECLARE_STR_FN(Tag, Prefix, Fmt) \
CR_API int CRI_USER_TAG_ID(lt, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) const *actual, \
CRI_ASSERT_TYPE_TAG(Tag) const *expected); \
CR_API int CRI_USER_TAG_ID(eq, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) const *actual, \
CRI_ASSERT_TYPE_TAG(Tag) const *expected); \
CR_API int CRI_USER_TAG_ID(zero, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) const *val); \
CR_API char *CRI_USER_TAG_ID(tostr, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) const *e);

#ifndef __cplusplus
# include <string.h>
Expand Down Expand Up @@ -287,7 +293,7 @@ CRI_ASSERT_DECLARE_NATIVE_CMP_FN(iptr)
CRI_ASSERT_DECLARE_NATIVE_CMP_FN(uptr)
CRI_ASSERT_DECLARE_NATIVE_CMP_FN(ptr)

static inline char *CRI_USER_TAG_ID(tostr, iptr)(intptr_t *e)
static inline char *CRI_USER_TAG_ID(tostr, iptr)(const intptr_t *e)
{
uintptr_t absptr = (uintptr_t) *e;
if (absptr > (uintptr_t)INTPTR_MAX)
Expand All @@ -298,14 +304,14 @@ static inline char *CRI_USER_TAG_ID(tostr, iptr)(intptr_t *e)
return str;
}

static inline char *CRI_USER_TAG_ID(tostr, uptr)(uintptr_t *e)
static inline char *CRI_USER_TAG_ID(tostr, uptr)(const uintptr_t *e)
{
char *str = NULL;
cr_asprintf(&str, "0x%" CRI_PRIxPTR, *e);
return str;
}

static inline char *CRI_USER_TAG_ID(tostr, ptr)(void **e)
static inline char *CRI_USER_TAG_ID(tostr, ptr)(const void **e)
{
char *str = NULL;
cr_asprintf(&str, "0x%" CRI_PRIxPTR, (uintptr_t) *e);
Expand Down
4 changes: 2 additions & 2 deletions include/criterion/new/stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ CR_BEGIN_C_API
CR_API void cr_stream_init(struct cr_stream *s);
CR_API void cr_stream_close(struct cr_stream *s);

CR_API int cr_user_stream_eq(struct cr_stream *s1, struct cr_stream *s2);
CR_API int cr_user_stream_lt(struct cr_stream *s1, struct cr_stream *s2);
CR_API int cr_user_stream_eq(const struct cr_stream *s1, const struct cr_stream *s2);
CR_API int cr_user_stream_lt(const struct cr_stream *s1, const struct cr_stream *s2);
CR_API char *cr_user_stream_tostr(const struct cr_stream *s);

CR_END_C_API
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ add_project_arguments(
cc.get_supported_arguments([
'-Wno-unused-parameter',
'-Wno-unused-value',
'-Werror',
'-fvisibility=hidden',
'-fexceptions',

Expand Down
8 changes: 4 additions & 4 deletions samples/asserts.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ struct dummy_struct {
};

/* We need to provide basic functions for our dummy struct */
int cr_user_dummy_struct_eq(struct dummy_struct *a, struct dummy_struct *b)
int cr_user_dummy_struct_eq(const struct dummy_struct *a, const struct dummy_struct *b)
{
return a->a == b->a && a->b == b->b;
}

char *cr_user_dummy_struct_tostr(struct dummy_struct *d)
char *cr_user_dummy_struct_tostr(const struct dummy_struct *d)
{
char *out;

Expand All @@ -97,8 +97,8 @@ char *cr_user_dummy_struct_tostr(struct dummy_struct *d)
}

Test(asserts, array) {
int arr1[] = { 1, 2, 3, 4 };
int arr2[] = { 4, 3, 2, 1 };
static const int arr1[] = { 1, 2, 3, 4 };
static const int arr2[] = { 4, 3, 2, 1 };

/* For primitive types we can compare their byte-to-byte representation */
struct cr_mem mem_arr1 = { .data = arr1, .size = 4 * sizeof (int) };
Expand Down
17 changes: 9 additions & 8 deletions src/capi/specifiers.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,26 @@
/* *INDENT-OFF* */
#define CRI_ASSERT_DEFINE_STR_FN(Tag, Prefix, Fmt) \
int CRI_USER_TAG_ID(lt, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *actual, \
CRI_ASSERT_TYPE_TAG(Tag) *expected) \
CRI_ASSERT_TYPE_TAG(Tag) const *actual, \
CRI_ASSERT_TYPE_TAG(Tag) const *expected) \
{ \
return Tag ## cmp(*actual, *expected) < 0; \
} \
int CRI_USER_TAG_ID(eq, Tag)( \
CRI_ASSERT_TYPE_TAG(Tag) *actual, \
CRI_ASSERT_TYPE_TAG(Tag) *expected) \
CRI_ASSERT_TYPE_TAG(Tag) const *actual, \
CRI_ASSERT_TYPE_TAG(Tag) const *expected) \
{ \
return !Tag ## cmp(*actual, *expected); \
} \
int CRI_USER_TAG_ID(zero, Tag)(CRI_ASSERT_TYPE_TAG(Tag) *val) \
int CRI_USER_TAG_ID(zero, Tag)(CRI_ASSERT_TYPE_TAG(Tag) const *val) \
{ \
return !Tag ## len(*val); \
} \
char *CRI_USER_TAG_ID(tostr, Tag)(CRI_ASSERT_TYPE_TAG(Tag) *e) \
char *CRI_USER_TAG_ID(tostr, Tag)(CRI_ASSERT_TYPE_TAG(Tag) const *e) \
{ \
CRI_ASSERT_TYPE_TAG(Tag) cri_dup = Tag ## dup(*e); \
CRI_ASSERT_TYPE_TAG(Tag) cri_line = cri_ ## Tag ## tokc(cri_dup, '\n'); \
CRI_ASSERT_MUT_TYPE_TAG(Tag) cri_dup = Tag ## dup(*e); \
CRI_ASSERT_MUT_TYPE_TAG(Tag) cri_line; \
cri_line = cri_ ## Tag ## tokc(cri_dup, '\n'); \
\
char *cri_str = NULL; \
size_t cri_off = 0; \
Expand Down
9 changes: 5 additions & 4 deletions src/capi/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
#include "criterion/new/stream.h"
#include "string/xxd.h"

static int streams_eval_cmp(struct cr_stream *m1, struct cr_stream *m2)
static int streams_eval_cmp(const struct cr_stream *m1,
const struct cr_stream *m2)
{
/* It doesn't make sense to compare consumed streams, but it still
happens in some case within an assertion. It's best to provide
Expand Down Expand Up @@ -80,12 +81,12 @@ static int streams_eval_cmp(struct cr_stream *m1, struct cr_stream *m2)
return cmp;
}

int cr_user_stream_eq(struct cr_stream *m1, struct cr_stream *m2)
int cr_user_stream_eq(const struct cr_stream *m1, const struct cr_stream *m2)
{
return !streams_eval_cmp(m1, m2);
}

int cr_user_stream_lt(struct cr_stream *m1, struct cr_stream *m2)
int cr_user_stream_lt(const struct cr_stream *m1, const struct cr_stream *m2)
{
return streams_eval_cmp(m1, m2) < 0;
}
Expand All @@ -97,7 +98,7 @@ char *cr_user_stream_tostr(const struct cr_stream *m)

void cr_stream_init(struct cr_stream *s)
{
s->cri_data = calloc(sizeof (*s->cri_data), 1);
s->cri_data = calloc(1, sizeof (*s->cri_data));
s->cri_data->ref = 1;
}

Expand Down
19 changes: 19 additions & 0 deletions test/full/bug521.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <criterion/criterion.h>
#include <criterion/new/assert.h>

Test(bug521, str) {
static const char *const foo = "foo";
cr_assert(eq(str, foo, "foo"));
cr_assert(ne(str, foo, "oof"));
}

Test(bug521, wcs) {
static const wchar_t *const foo = L"foo";
cr_assert(eq(wcs, foo, L"foo"));
cr_assert(ne(wcs, foo, L"oof"));
}

Test(bug521, ptr) {
static const char *const foo = "foo";
cr_assert(eq(ptr, foo, foo));
}
6 changes: 3 additions & 3 deletions test/full/failmessages.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ struct dummy_struct {
};

/* We need to provide basic functions for our dummy struct */
int cr_user_dummy_struct_eq(struct dummy_struct *a, struct dummy_struct *b)
int cr_user_dummy_struct_eq(const struct dummy_struct *a, const struct dummy_struct *b)
{
return a->a == b->a && a->b == b->b;
}

int cr_user_dummy_struct_zero(struct dummy_struct *a)
int cr_user_dummy_struct_zero(const struct dummy_struct *a)
{
return !a->a && !a->b;
}

char *cr_user_dummy_struct_tostr(struct dummy_struct *d)
char *cr_user_dummy_struct_tostr(const struct dummy_struct *d)
{
char *out;

Expand Down
1 change: 1 addition & 0 deletions test/full/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ full_tests = [

# bug-specific programs
'bug463.c',
'bug521.c',
]

if get_option('theories').enabled()
Expand Down