1 /*
2 * This file and its contents are licensed under the Apache License 2.0.
3 * Please see the included NOTICE for copyright information and
4 * LICENSE-APACHE for a copy of the license.
5 */
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <time.h>
11 #include <unistd.h>
12 #include <postgres.h>
13
14 #include "conn_internal.h"
15 #include "conn_mock.h"
16
17 #define MOCK_MAX_BUF_SIZE 1024
18
19 typedef struct MockConnection
20 {
21 Connection conn;
22 char recv_buf[MOCK_MAX_BUF_SIZE];
23 int recv_buf_offset;
24 int recv_buf_len;
25 } MockConnection;
26
27 static int
mock_connect(Connection * conn,const char * host,const char * servname,int port)28 mock_connect(Connection *conn, const char *host, const char *servname, int port)
29 {
30 return 0;
31 }
32
33 static void
mock_close(Connection * conn)34 mock_close(Connection *conn)
35 {
36 return;
37 }
38
39 static ssize_t
mock_write(Connection * conn,const char * buf,size_t writelen)40 mock_write(Connection *conn, const char *buf, size_t writelen)
41 {
42 return writelen;
43 }
44
45 static ssize_t
mock_read(Connection * conn,char * buf,size_t readlen)46 mock_read(Connection *conn, char *buf, size_t readlen)
47 {
48 size_t bytes_to_read = 0;
49 size_t max = readlen;
50 MockConnection *mock = (MockConnection *) conn;
51
52 if (mock->recv_buf_offset >= mock->recv_buf_len)
53 return 0;
54
55 if (max >= mock->recv_buf_len - mock->recv_buf_offset)
56 max = mock->recv_buf_len - mock->recv_buf_offset;
57
58 /* Now read a random amount */
59 while (bytes_to_read == 0)
60 {
61 bytes_to_read = rand() % (max + 1);
62 }
63 memcpy(buf, mock->recv_buf + mock->recv_buf_offset, bytes_to_read);
64 mock->recv_buf_offset += bytes_to_read;
65
66 return bytes_to_read;
67 }
68
69 static int
mock_init(Connection * conn)70 mock_init(Connection *conn)
71 {
72 srand(time(0));
73 return 0;
74 }
75
76 static ConnOps mock_ops = {
77 .size = sizeof(MockConnection),
78 .init = mock_init,
79 .connect = mock_connect,
80 .close = mock_close,
81 .write = mock_write,
82 .read = mock_read,
83 };
84
85 ssize_t
ts_connection_mock_set_recv_buf(Connection * conn,char * buf,size_t buf_len)86 ts_connection_mock_set_recv_buf(Connection *conn, char *buf, size_t buf_len)
87 {
88 MockConnection *mock = (MockConnection *) conn;
89
90 if (buf_len > MOCK_MAX_BUF_SIZE)
91 return -1;
92
93 memcpy(mock->recv_buf, buf, buf_len);
94 mock->recv_buf_len = buf_len;
95 return mock->recv_buf_len;
96 }
97
98 extern void _conn_mock_init(void);
99 extern void _conn_mock_fini(void);
100
101 void
_conn_mock_init(void)102 _conn_mock_init(void)
103 {
104 ts_connection_register(CONNECTION_MOCK, &mock_ops);
105 }
106
107 void
_conn_mock_fini(void)108 _conn_mock_fini(void)
109 {
110 }
111