blob: 0f35ffcd4a5e023d4dd0c823286d8af5b56f78aa [file] [log] [blame]
Andrew Jeffery9a6ba892023-07-18 22:22:14 +09301#include "container-of.h"
2#include "transport.h"
3#include "test.h"
4
5#include <errno.h>
6#include <stdlib.h>
7#include <string.h>
8#include <unistd.h>
9
10struct pldm_transport_test {
11 struct pldm_transport transport;
12 const struct pldm_transport_test_descriptor *seq;
13 size_t count;
14 size_t cursor;
15 int timerfd;
16};
17
18#define transport_to_test(ptr) \
19 container_of(ptr, struct pldm_transport_test, transport)
20
21LIBPLDM_ABI_TESTING
22struct pldm_transport *pldm_transport_test_core(struct pldm_transport_test *ctx)
23{
24 return &ctx->transport;
25}
26
27#ifdef PLDM_HAS_POLL
28#include <poll.h>
29LIBPLDM_ABI_TESTING
30int pldm_transport_test_init_pollfd(struct pldm_transport *ctx,
31 struct pollfd *pollfd)
32{
33 static const struct itimerspec disable = {
34 .it_value = { 0, 0 },
35 .it_interval = { 0, 0 },
36 };
37 struct pldm_transport_test *test = transport_to_test(ctx);
38 const struct pldm_transport_test_descriptor *desc;
39 int rc;
40
41 rc = timerfd_settime(test->timerfd, 0, &disable, NULL);
42 if (rc < 0) {
43 return PLDM_REQUESTER_POLL_FAIL;
44 }
45
46 if (test->cursor >= test->count) {
47 return PLDM_REQUESTER_POLL_FAIL;
48 }
49
50 desc = &test->seq[test->cursor];
51
Thu Nguyenf56e4dc2023-07-24 10:39:47 +070052 if (desc->type == PLDM_TRANSPORT_TEST_ELEMENT_LATENCY) {
53 rc = timerfd_settime(test->timerfd, 0, &desc->latency, NULL);
54 if (rc < 0) {
55 return PLDM_REQUESTER_POLL_FAIL;
56 }
Andrew Jeffery9a6ba892023-07-18 22:22:14 +093057
Thu Nguyenf56e4dc2023-07-24 10:39:47 +070058 /* This was an explicit latency element, so now move beyond it for recv */
59 test->cursor++;
60 } else if (desc->type == PLDM_TRANSPORT_TEST_ELEMENT_MSG_RECV) {
61 /* Expire the timer immediately so it appears ready */
62 static const struct itimerspec ready = {
63 .it_value = { 0, 1 },
64 .it_interval = { 0, 0 },
65 };
66 rc = timerfd_settime(test->timerfd, 0, &ready, NULL);
67 if (rc < 0) {
68 return PLDM_REQUESTER_POLL_FAIL;
69 }
70
71 /* Don't increment test->cursor as recv needs to consume the current test element */
72 } else {
Andrew Jeffery9a6ba892023-07-18 22:22:14 +093073 return PLDM_REQUESTER_POLL_FAIL;
74 }
75
76 pollfd->fd = test->timerfd;
77 pollfd->events = POLLIN;
78
Andrew Jeffery9a6ba892023-07-18 22:22:14 +093079 return 0;
80}
81#endif
82
83static pldm_requester_rc_t pldm_transport_test_recv(struct pldm_transport *ctx,
84 pldm_tid_t tid,
85 void **pldm_resp_msg,
86 size_t *resp_msg_len)
87{
88 struct pldm_transport_test *test = transport_to_test(ctx);
89 const struct pldm_transport_test_descriptor *desc;
90 void *msg;
91
92 (void)tid;
93
94 if (test->cursor >= test->count) {
95 return PLDM_REQUESTER_RECV_FAIL;
96 }
97
98 desc = &test->seq[test->cursor];
99
100 if (desc->type != PLDM_TRANSPORT_TEST_ELEMENT_MSG_RECV) {
101 return PLDM_REQUESTER_RECV_FAIL;
102 }
103
104 msg = malloc(desc->recv_msg.len);
105 if (!msg) {
106 return PLDM_REQUESTER_RECV_FAIL;
107 }
108
109 memcpy(msg, desc->recv_msg.msg, desc->recv_msg.len);
110 *pldm_resp_msg = msg;
111 *resp_msg_len = desc->recv_msg.len;
112
113 test->cursor++;
114
115 return PLDM_REQUESTER_SUCCESS;
116}
117
118static pldm_requester_rc_t pldm_transport_test_send(struct pldm_transport *ctx,
119 pldm_tid_t tid,
120 const void *pldm_req_msg,
121 size_t req_msg_len)
122{
123 struct pldm_transport_test *test = transport_to_test(ctx);
124 const struct pldm_transport_test_descriptor *desc;
125
126 if (test->cursor > test->count) {
127 return PLDM_REQUESTER_SEND_FAIL;
128 }
129
130 desc = &test->seq[test->cursor];
131
132 if (desc->type != PLDM_TRANSPORT_TEST_ELEMENT_MSG_SEND) {
133 return PLDM_REQUESTER_SEND_FAIL;
134 }
135
136 if (desc->send_msg.dst != tid) {
137 return PLDM_REQUESTER_SEND_FAIL;
138 }
139
140 if (desc->send_msg.len != req_msg_len) {
141 return PLDM_REQUESTER_SEND_FAIL;
142 }
143
144 if (memcmp(desc->send_msg.msg, pldm_req_msg, req_msg_len) != 0) {
145 return PLDM_REQUESTER_SEND_FAIL;
146 }
147
148 test->cursor++;
149
150 return PLDM_REQUESTER_SUCCESS;
151}
152
153LIBPLDM_ABI_TESTING
154int pldm_transport_test_init(struct pldm_transport_test **ctx,
155 const struct pldm_transport_test_descriptor *seq,
156 size_t count)
157{
158 int rc;
159
160 if (!ctx || *ctx) {
161 return -EINVAL;
162 }
163
164 struct pldm_transport_test *test = malloc(sizeof(*test));
165 if (!test) {
166 return -ENOMEM;
167 }
168
169 test->transport.name = "TEST";
170 test->transport.version = 1;
171 test->transport.recv = pldm_transport_test_recv;
172 test->transport.send = pldm_transport_test_send;
173 test->transport.init_pollfd = pldm_transport_test_init_pollfd;
174 test->seq = seq;
175 test->count = count;
176 test->cursor = 0;
177 test->timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
178 if (test->timerfd < 0) {
179 rc = -errno;
180 goto cleanup_test;
181 }
182
183 *ctx = test;
184
185 return 0;
186
187cleanup_test:
188 free(test);
189 return rc;
190}
191
192LIBPLDM_ABI_TESTING
193void pldm_transport_test_destroy(struct pldm_transport_test *ctx)
194{
195 close(ctx->timerfd);
196 free(ctx);
197}