File size: 4,646 Bytes
78d2150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "../../unity/unity.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

/* The following globals and functions are defined in dd.c and are
   visible here because this test file is included into the same
   translation unit. We simply use them. */
extern void alloc_ibuf(void);

/* Globals from dd.c (file-scope static there, but visible here as we're
   included into the same translation unit):
   - static idx_t page_size;
   - static idx_t input_blocksize;
   - static int conversions_mask;
   - static char *ibuf;
   - static char *obuf;
   - enum conversion flags including C_SWAB
   - static char *swab_buffer(char *buf, idx_t *nread, int *saved_byte);
*/

/* Forward declarations to inform the compiler; definitions are above in dd.c */
extern char *swab_buffer(char *buf, idx_t *nread, int *saved_byte);

/* From dd.c enum */
/* We don't redeclare C_SWAB; using it directly as it's an enum constant
   defined earlier in dd.c. */

static size_t get_page_size_fallback(void)
{
    long ps = -1;
#ifdef _SC_PAGESIZE
    ps = sysconf(_SC_PAGESIZE);
#elif defined(_SC_PAGE_SIZE)
    ps = sysconf(_SC_PAGE_SIZE);
#endif
    if (ps <= 0)
        return 4096; /* reasonable default */
    return (size_t)ps;
}

void setUp(void)
{
    /* Ensure a clean slate for each test. */
    if (ibuf) {
        free(ibuf);
    }
    ibuf = NULL;
    /* obuf may alias ibuf in some modes; clear to avoid dangling pointer. */
    obuf = NULL;

    /* Reasonable defaults for globals used by alloc_ibuf. */
    page_size = (typeof(page_size))get_page_size_fallback();
    input_blocksize = 64; /* small, safe size */
    conversions_mask = 0; /* no special conversions by default */
}

void tearDown(void)
{
    if (ibuf) {
        free(ibuf);
        ibuf = NULL;
    }
    obuf = NULL;
}

static void assert_pointer_aligned(void *p, size_t align)
{
    /* Unity doesn't have direct alignment assert; use generic assert. */
    TEST_ASSERT_NOT_NULL_MESSAGE(p, "Pointer is NULL; expected an allocated buffer");
    TEST_ASSERT_EQUAL_UINT64_MESSAGE(0ULL, ((uintptr_t)p) % align,
                                     "Allocated buffer is not aligned to page_size");
}

void test_alloc_ibuf_basic_allocation_and_alignment(void)
{
    /* Given defaults from setUp, allocate ibuf. */
    alloc_ibuf();

    /* Then ibuf should be non-NULL and page aligned. */
    assert_pointer_aligned(ibuf, (size_t)page_size);

    /* We can touch within input_blocksize range safely. */
    ibuf[0] = (char)0xAA;
    ibuf[input_blocksize - 1] = (char)0x55;
    TEST_ASSERT_EQUAL_HEX8((char)0xAA, ibuf[0]);
    TEST_ASSERT_EQUAL_HEX8((char)0x55, ibuf[input_blocksize - 1]);
}

void test_alloc_ibuf_idempotent_no_realloc(void)
{
    /* First allocation */
    alloc_ibuf();
    char *first = ibuf;
    TEST_ASSERT_NOT_NULL(first);

    /* Change globals to values that would cause a different allocation
       if alloc_ibuf() didn't early return, then call again. */
    input_blocksize = 128; /* different size */
    conversions_mask = C_SWAB; /* request extra byte */
    alloc_ibuf();

    /* Expect the same pointer; function should return early if ibuf is set. */
    TEST_ASSERT_EQUAL_PTR(first, ibuf);
}

void test_alloc_ibuf_with_swab_extra_byte_supports_swab_buffer(void)
{
    /* Ensure conv=swab set so alloc_ibuf allocates an extra byte. */
    conversions_mask = C_SWAB;
    input_blocksize = 6; /* Small even size to exercise swab */

    alloc_ibuf();
    assert_pointer_aligned(ibuf, (size_t)page_size);

    /* Fill buffer with known pattern: A B C D E F */
    const char pattern[6] = { 'A', 'B', 'C', 'D', 'E', 'F' };
    memcpy(ibuf, pattern, sizeof(pattern));

    /* swab_buffer writes to buf[*nread] when prev_saved<0 and *nread is even,
       which requires the extra byte allocated by alloc_ibuf() when C_SWAB set. */
    int saved_byte = -1;
    typeof(input_blocksize) nread = input_blocksize; /* 6 */

    char *start = swab_buffer(ibuf, &nread, &saved_byte);

    /* For even nread=6 and no previous saved byte, swab_buffer returns buf+1.
       The 6 bytes starting at start should be BA DC FE. */
    TEST_ASSERT_EQUAL_PTR(ibuf + 1, start);
    TEST_ASSERT_EQUAL_INT64(6, nread);
    TEST_ASSERT_EQUAL_INT(-1, saved_byte);

    const char expected[6] = { 'B', 'A', 'D', 'C', 'F', 'E' };
    TEST_ASSERT_EQUAL_MEMORY(expected, start, sizeof(expected));
}

int main(void)
{
    UNITY_BEGIN();
    RUN_TEST(test_alloc_ibuf_basic_allocation_and_alignment);
    RUN_TEST(test_alloc_ibuf_idempotent_no_realloc);
    RUN_TEST(test_alloc_ibuf_with_swab_extra_byte_supports_swab_buffer);
    return UNITY_END();
}