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