File size: 3,506 Bytes
e996a55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#include "unity/unity.h"
#include "zlib.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#ifdef _WIN32
#  include <io.h>
#  include <fcntl.h>
#  define CLOSE _close
#else
#  include <unistd.h>
#  include <fcntl.h>
#  include <sys/types.h>
#  include <sys/stat.h>
#  define CLOSE close
#endif

/* Helper: create a temporary read/write file descriptor.
   On POSIX, use mkstemp and unlink it immediately.
   On Windows, use tmpfile and duplicate its descriptor so fclose won't impact it. */
static int make_temp_fd(void) {
#ifdef _WIN32
    FILE *fp = tmpfile();
    TEST_ASSERT_NOT_NULL_MESSAGE(fp, "tmpfile() failed");
    int fd = _dup(_fileno(fp));
    /* Close the FILE*, leaving the duplicated fd open */
    fclose(fp);
    TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "_dup() failed to duplicate file descriptor");
    return fd;
#else
    char templ[] = "gzdopen_test_XXXXXX";
    int fd = mkstemp(templ);
    TEST_ASSERT_TRUE_MESSAGE(fd >= 0, "mkstemp() failed to create temporary file");
    /* Unlink so the file is removed after close */
    unlink(templ);
    return fd;
#endif
}

void setUp(void) {
    /* Setup code here, or leave empty */
}

void tearDown(void) {
    /* Cleanup code here, or leave empty */
}

/* fd == -1 should return NULL */
void test_gzdopen_fd_invalid_returns_null(void) {
    gzFile gz = gzdopen(-1, "rb");
    TEST_ASSERT_NULL(gz);
}

/* Mode lacking 'r', 'w', or 'a' should return NULL */
void test_gzdopen_mode_missing_rwab_returns_null(void) {
    int fd = make_temp_fd();
    gzFile gz = gzdopen(fd, "b");
    TEST_ASSERT_NULL(gz);
    /* Close the fd ourselves since gzdopen failed */
    CLOSE(fd);
}

/* Mode containing '+' should return NULL */
void test_gzdopen_mode_with_plus_returns_null(void) {
    int fd = make_temp_fd();
    gzFile gz = gzdopen(fd, "w+");
    TEST_ASSERT_NULL(gz);
    CLOSE(fd);
}

/* Valid read mode should succeed */
void test_gzdopen_read_mode_returns_valid_handle(void) {
    int fd = make_temp_fd();
    gzFile gz = gzdopen(fd, "rb");
    TEST_ASSERT_NOT_NULL(gz);
    /* gzclose should succeed and will close the fd */
    int rc = gzclose(gz);
    TEST_ASSERT_EQUAL_INT(0, rc);
}

/* Valid append mode should succeed */
void test_gzdopen_append_mode_returns_valid_handle(void) {
    int fd = make_temp_fd();
    gzFile gz = gzdopen(fd, "ab");
    TEST_ASSERT_NOT_NULL(gz);
    int rc = gzclose(gz);
    TEST_ASSERT_EQUAL_INT(0, rc);
}

/* Forcing transparent read ('T') in read mode should fail */
void test_gzdopen_read_mode_with_T_returns_null(void) {
    int fd = make_temp_fd();
    gzFile gz = gzdopen(fd, "rbT");
    TEST_ASSERT_NULL(gz);
    CLOSE(fd);
}

/* Valid write mode with options should succeed */
void test_gzdopen_write_mode_with_options_returns_valid_handle(void) {
    int fd = make_temp_fd();
    /* compression level '9' and strategy 'h' (Huffman only) in mode string */
    gzFile gz = gzdopen(fd, "wb9h");
    TEST_ASSERT_NOT_NULL(gz);
    int rc = gzclose(gz);
    TEST_ASSERT_EQUAL_INT(0, rc);
}

int main(void) {
    UNITY_BEGIN();

    RUN_TEST(test_gzdopen_fd_invalid_returns_null);
    RUN_TEST(test_gzdopen_mode_missing_rwab_returns_null);
    RUN_TEST(test_gzdopen_mode_with_plus_returns_null);
    RUN_TEST(test_gzdopen_read_mode_returns_valid_handle);
    RUN_TEST(test_gzdopen_append_mode_returns_valid_handle);
    RUN_TEST(test_gzdopen_read_mode_with_T_returns_null);
    RUN_TEST(test_gzdopen_write_mode_with_options_returns_valid_handle);

    return UNITY_END();
}