Skip to content

Commit db6bfda

Browse files
committed
Add union tests
1 parent 34f0cdd commit db6bfda

14 files changed

Lines changed: 564 additions & 0 deletions

tests/unit/union_addrof_external.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// translation-fail
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
#include <string.h>
6+
7+
struct header {
8+
uint16_t tag;
9+
uint16_t port;
10+
uint32_t addr;
11+
char pad[8];
12+
};
13+
14+
struct Storage {
15+
union {
16+
struct header h;
17+
char raw[128];
18+
} buffer;
19+
};
20+
21+
static void external_writer(void *out, size_t cap) {
22+
unsigned char src[16] = {0};
23+
src[0] = 2;
24+
src[1] = 0;
25+
src[2] = 0x00;
26+
src[3] = 0x50;
27+
src[4] = 0x7F;
28+
src[5] = 0x00;
29+
src[6] = 0x00;
30+
src[7] = 0x01;
31+
size_t n = sizeof(src) < cap ? sizeof(src) : cap;
32+
memcpy(out, src, n);
33+
}
34+
35+
int main(void) {
36+
struct Storage s;
37+
memset(&s, 0, sizeof(s));
38+
39+
external_writer((void *)&s.buffer, sizeof(s.buffer));
40+
41+
assert(s.buffer.h.tag == 2);
42+
assert(((unsigned char *)&s.buffer.h.port)[0] == 0x00);
43+
assert(((unsigned char *)&s.buffer.h.port)[1] == 0x50);
44+
45+
assert(s.buffer.raw[0] == 2);
46+
assert((unsigned char)s.buffer.raw[3] == 0x50);
47+
48+
return 0;
49+
}

tests/unit/union_basic.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <assert.h>
2+
3+
union basic {
4+
int i;
5+
float f;
6+
};
7+
8+
int main(void) {
9+
union basic u;
10+
11+
u.i = 42;
12+
assert(u.i == 42);
13+
14+
u.f = 3.14f;
15+
assert(u.f == 3.14f);
16+
17+
return 0;
18+
}

tests/unit/union_cross_arm_cast.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// translation-fail
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
#include <string.h>
6+
7+
struct header_a {
8+
uint16_t tag;
9+
char data[14];
10+
};
11+
12+
struct header_b {
13+
uint16_t tag;
14+
uint16_t port;
15+
uint32_t flags;
16+
uint8_t body[16];
17+
uint32_t extra;
18+
};
19+
20+
struct Storage {
21+
unsigned int len;
22+
union {
23+
struct header_a a;
24+
struct header_b b;
25+
char raw[64];
26+
} u;
27+
};
28+
29+
int main(void) {
30+
struct Storage s;
31+
memset(&s, 0, sizeof(s));
32+
33+
s.u.a.tag = 10;
34+
s.len = sizeof(struct header_b);
35+
36+
((struct header_b *)(void *)&s.u.a)->extra = 0xDEADBEEF;
37+
38+
assert(s.u.b.extra == 0xDEADBEEF);
39+
assert(s.u.b.tag == 10);
40+
41+
s.u.b.port = 0x1F90;
42+
assert(((unsigned char *)&s.u.raw)[2] == 0x90);
43+
assert(((unsigned char *)&s.u.raw)[3] == 0x1F);
44+
45+
return 0;
46+
}

tests/unit/union_field_alignment.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// translation-fail
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
6+
struct chunk {
7+
struct chunk *next;
8+
union {
9+
uint8_t data[1];
10+
void *dummy;
11+
} x;
12+
};
13+
14+
int main(void) {
15+
struct chunk c;
16+
c.next = 0;
17+
c.x.data[0] = 0xAB;
18+
19+
assert(c.x.data[0] == 0xAB);
20+
assert(sizeof(c.x) >= sizeof(void *));
21+
assert(((uintptr_t)&c.x % _Alignof(void *)) == 0);
22+
return 0;
23+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// translation-fail
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
8+
struct chunk {
9+
size_t dlen;
10+
union {
11+
uint8_t data[1];
12+
void *dummy;
13+
} x;
14+
};
15+
16+
int main(void) {
17+
size_t chunk_size = 32;
18+
struct chunk *c = (struct chunk *)malloc(sizeof(struct chunk) + chunk_size);
19+
c->dlen = chunk_size;
20+
21+
for (size_t i = 0; i < chunk_size; i++) {
22+
c->x.data[i] = (uint8_t)(i & 0xFF);
23+
}
24+
for (size_t i = 0; i < chunk_size; i++) {
25+
assert(c->x.data[i] == (uint8_t)(i & 0xFF));
26+
}
27+
28+
uint8_t *p = &c->x.data[10];
29+
assert(*p == 10);
30+
*p = 0xAA;
31+
assert(c->x.data[10] == 0xAA);
32+
33+
free(c);
34+
return 0;
35+
}

tests/unit/union_memset_memcpy.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// translation-fail
2+
#include <assert.h>
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
#include <string.h>
6+
7+
struct header_a {
8+
uint16_t tag;
9+
char data[14];
10+
};
11+
12+
struct header_b {
13+
uint16_t tag;
14+
uint16_t port;
15+
uint32_t addr;
16+
char zero[8];
17+
};
18+
19+
struct Storage {
20+
union {
21+
struct header_a a;
22+
struct header_b b;
23+
char raw[256];
24+
} buffer;
25+
};
26+
27+
int main(void) {
28+
struct Storage s;
29+
30+
memset(&s, 0, sizeof(s));
31+
assert(s.buffer.a.tag == 0);
32+
assert(s.buffer.b.port == 0);
33+
assert(s.buffer.raw[0] == 0);
34+
assert(s.buffer.raw[255] == 0);
35+
36+
unsigned char wire[16] = {0};
37+
wire[0] = 2;
38+
wire[2] = 0x50;
39+
wire[3] = 0x00;
40+
wire[4] = 0x7F;
41+
wire[5] = 0x00;
42+
wire[6] = 0x00;
43+
wire[7] = 0x01;
44+
size_t len = 16;
45+
assert(len <= sizeof(s.buffer.raw));
46+
memcpy(&s.buffer.raw, wire, len);
47+
48+
assert(s.buffer.b.tag == 2);
49+
assert(((unsigned char *)&s.buffer.b.port)[0] == 0x50);
50+
51+
memset(&s, 0, sizeof(s));
52+
assert(s.buffer.b.tag == 0);
53+
54+
return 0;
55+
}

tests/unit/union_nested.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// translation-fail
2+
#include <assert.h>
3+
#include <stdint.h>
4+
#include <string.h>
5+
6+
struct header {
7+
uint16_t tag;
8+
char data[14];
9+
};
10+
11+
struct inner {
12+
union {
13+
struct header h;
14+
char raw[128];
15+
} buffer;
16+
};
17+
18+
struct Outer {
19+
int kind;
20+
int subtype;
21+
int proto;
22+
unsigned int len;
23+
union {
24+
struct header h;
25+
struct inner nested;
26+
} body;
27+
};
28+
29+
int main(void) {
30+
struct Outer ex;
31+
memset(&ex, 0, sizeof(ex));
32+
33+
ex.kind = 2;
34+
ex.subtype = 1;
35+
ex.proto = 6;
36+
ex.len = sizeof(struct header);
37+
ex.body.h.tag = 2;
38+
ex.body.h.data[0] = 'X';
39+
40+
assert(ex.body.h.tag == 2);
41+
assert(ex.body.h.data[0] == 'X');
42+
43+
assert(ex.body.nested.buffer.h.tag == 2);
44+
return 0;
45+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// translation-fail
2+
#include <assert.h>
3+
4+
struct node_a {
5+
int n;
6+
};
7+
8+
struct node_b {
9+
void *data;
10+
struct node_b *next;
11+
};
12+
13+
int main(void) {
14+
struct node_a a = {123};
15+
16+
union {
17+
struct node_a *to_a;
18+
struct node_b *to_b;
19+
} ptr;
20+
21+
ptr.to_a = &a;
22+
struct node_b *out = ptr.to_b;
23+
24+
assert((void *)out == (void *)&a);
25+
return 0;
26+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// translation-fail
2+
#include <assert.h>
3+
4+
int main(void) {
5+
long x = -1;
6+
7+
union {
8+
unsigned long *to_ulong;
9+
long *to_long;
10+
} lptr;
11+
12+
lptr.to_long = &x;
13+
*lptr.to_ulong = 42UL;
14+
15+
assert(x == 42);
16+
return 0;
17+
}

tests/unit/union_struct_dual_use.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// translation-fail
2+
#include <assert.h>
3+
#include <string.h>
4+
5+
struct Inner {
6+
int a;
7+
int b;
8+
};
9+
10+
static int sum_inner(struct Inner *i) { return i->a + i->b; }
11+
12+
struct Outer {
13+
union {
14+
struct Inner inner;
15+
char raw[16];
16+
} u;
17+
};
18+
19+
int main(void) {
20+
struct Inner standalone;
21+
standalone.a = 3;
22+
standalone.b = 4;
23+
assert(sum_inner(&standalone) == 7);
24+
25+
struct Outer outer;
26+
memset(&outer, 0, sizeof(outer));
27+
outer.u.inner.a = 3;
28+
outer.u.inner.b = 4;
29+
assert(sum_inner(&outer.u.inner) == 7);
30+
31+
assert((unsigned char)outer.u.raw[0] == 3);
32+
assert((unsigned char)outer.u.raw[4] == 4);
33+
34+
return 0;
35+
}

0 commit comments

Comments
 (0)