1 
2 #include <fcntl.h>
3 #include <mongoc.h>
4 #include <mongoc-stream-private.h>
5 #include <stdlib.h>
6 
7 #include "TestSuite.h"
8 
9 
10 static void
test_buffered_basic(void)11 test_buffered_basic (void)
12 {
13    mongoc_stream_t *stream;
14    mongoc_stream_t *buffered;
15    mongoc_iovec_t iov;
16    ssize_t r;
17    char buf[16236];
18 
19    stream =
20       mongoc_stream_file_new_for_path (BINARY_DIR "/reply2.dat", O_RDONLY, 0);
21    BSON_ASSERT (stream);
22 
23    /* buffered assumes ownership of stream */
24    buffered = mongoc_stream_buffered_new (stream, 1024);
25 
26    /* try to read large chunk larger than buffer. */
27    iov.iov_len = sizeof buf;
28    iov.iov_base = buf;
29    r = mongoc_stream_readv (buffered, &iov, 1, iov.iov_len, -1);
30    if (r != iov.iov_len) {
31       char msg[100];
32 
33       bson_snprintf (msg,
34                      100,
35                      "Expected %lld got %llu",
36                      (long long) r,
37                      (unsigned long long) iov.iov_len);
38       ASSERT_CMPSTR (msg, "failed");
39    }
40 
41    /* cleanup */
42    mongoc_stream_destroy (buffered);
43 }
44 
45 
46 static void
test_buffered_oversized(void)47 test_buffered_oversized (void)
48 {
49    mongoc_stream_t *stream;
50    mongoc_stream_t *buffered;
51    mongoc_iovec_t iov;
52    ssize_t r;
53    char buf[16236];
54 
55    stream =
56       mongoc_stream_file_new_for_path (BINARY_DIR "/reply2.dat", O_RDONLY, 0);
57    BSON_ASSERT (stream);
58 
59    /* buffered assumes ownership of stream */
60    buffered = mongoc_stream_buffered_new (stream, 20000);
61 
62    /* try to read large chunk larger than buffer. */
63    iov.iov_len = sizeof buf;
64    iov.iov_base = buf;
65    r = mongoc_stream_readv (buffered, &iov, 1, iov.iov_len, -1);
66    if (r != iov.iov_len) {
67       char msg[100];
68 
69       bson_snprintf (msg,
70                      100,
71                      "Expected %lld got %llu",
72                      (long long) r,
73                      (unsigned long long) iov.iov_len);
74       ASSERT_CMPSTR (msg, "failed");
75    }
76 
77    /* cleanup */
78    mongoc_stream_destroy (buffered);
79 }
80 
81 
82 typedef struct {
83    mongoc_stream_t vtable;
84    ssize_t rval;
85 } failing_stream_t;
86 
87 static ssize_t
failing_stream_writev(mongoc_stream_t * stream,mongoc_iovec_t * iov,size_t iovcnt,int32_t timeout_msec)88 failing_stream_writev (mongoc_stream_t *stream,
89                        mongoc_iovec_t *iov,
90                        size_t iovcnt,
91                        int32_t timeout_msec)
92 {
93    failing_stream_t *fstream = (failing_stream_t *) stream;
94 
95    return fstream->rval;
96 }
97 
98 void
failing_stream_destroy(mongoc_stream_t * stream)99 failing_stream_destroy (mongoc_stream_t *stream)
100 {
101    bson_free (stream);
102 }
103 
104 static mongoc_stream_t *
failing_stream_new(ssize_t rval)105 failing_stream_new (ssize_t rval)
106 {
107    failing_stream_t *stream;
108 
109    stream = bson_malloc0 (sizeof *stream);
110    stream->vtable.type = 999;
111    stream->vtable.writev = failing_stream_writev;
112    stream->vtable.destroy = failing_stream_destroy;
113    stream->rval = rval;
114 
115    return (mongoc_stream_t *) stream;
116 }
117 
118 
119 static void
test_stream_writev_full(void)120 test_stream_writev_full (void)
121 {
122    mongoc_stream_t *error_stream = failing_stream_new (-1);
123    mongoc_stream_t *short_stream = failing_stream_new (10);
124    mongoc_stream_t *success_stream = failing_stream_new (100);
125    char bufa[20];
126    char bufb[80];
127    bool r;
128    mongoc_iovec_t iov[2];
129    bson_error_t error = {0};
130    const char *error_message = "Failure during socket delivery: ";
131    const char *short_message = "Failure to send all requested bytes (only "
132                                "sent: 10/100 in 100ms) during socket delivery";
133 
134    iov[0].iov_base = bufa;
135    iov[0].iov_len = sizeof (bufa);
136    iov[1].iov_base = bufb;
137    iov[1].iov_len = sizeof (bufb);
138 
139    errno = EINVAL;
140    r = _mongoc_stream_writev_full (error_stream, iov, 2, 100, &error);
141 
142    BSON_ASSERT (!r);
143    ASSERT_CMPINT (error.domain, ==, MONGOC_ERROR_STREAM);
144    ASSERT_CMPINT (error.code, ==, MONGOC_ERROR_STREAM_SOCKET);
145    ASSERT_STARTSWITH (error.message, error_message);
146 
147    errno = 0;
148    r = _mongoc_stream_writev_full (short_stream, iov, 2, 100, &error);
149    BSON_ASSERT (!r);
150    ASSERT_CMPINT (error.domain, ==, MONGOC_ERROR_STREAM);
151    ASSERT_CMPINT (error.code, ==, MONGOC_ERROR_STREAM_SOCKET);
152    ASSERT_CMPSTR (error.message, short_message);
153 
154    errno = 0;
155    r = _mongoc_stream_writev_full (success_stream, iov, 2, 100, &error);
156    BSON_ASSERT (r);
157 
158    mongoc_stream_destroy (error_stream);
159    mongoc_stream_destroy (short_stream);
160    mongoc_stream_destroy (success_stream);
161 }
162 
163 
164 void
test_stream_install(TestSuite * suite)165 test_stream_install (TestSuite *suite)
166 {
167    TestSuite_Add (suite, "/Stream/buffered/basic", test_buffered_basic);
168    TestSuite_Add (suite, "/Stream/buffered/oversized", test_buffered_oversized);
169    TestSuite_Add (suite, "/Stream/writev_full", test_stream_writev_full);
170 }
171