blob: d7a9957cfc13b83d40138692b188bbc783b12d91 [file] [log] [blame]
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +08001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
18#include <stdint.h>
19#include <stdio.h>
20
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080021#define read __read
Andrew Jeffery71e7a242020-02-12 22:58:16 +103022#include "config.c"
Andrew Jeffery5e7c0782020-02-10 12:12:36 +103023#include "console-socket.c"
24#define main __main
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080025#include "console-client.c"
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080026#undef read
Andrew Jeffery5e7c0782020-02-10 12:12:36 +103027#undef main
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080028
29struct test {
Andrew Jefferya72711a2023-04-18 18:19:41 +093030 enum esc_type esc_type;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080031 union {
32 struct ssh_esc_state ssh;
33 struct str_esc_state str;
34 } esc_state;
Andrew Jefferya72711a2023-04-18 18:19:41 +093035 const char *in[4];
36 size_t n_in;
37 const char *exp_out;
38 int exp_rc;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080039};
40
41struct test_ctx {
Andrew Jefferya72711a2023-04-18 18:19:41 +093042 struct console_client client;
43 struct test *test;
44 uint8_t out[4096];
45 size_t cur_in;
46 size_t cur_out;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080047};
48
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080049struct test tests[] = {
50 {
51 /* no escape code */
Andrew Jefferya72711a2023-04-18 18:19:41 +093052 .esc_type = ESC_TYPE_SSH,
53 .in = { "a" },
54 .n_in = 1,
55 .exp_out = "a",
56 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080057 },
58 {
59 /* no escape code, multiple reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +093060 .esc_type = ESC_TYPE_SSH,
61 .in = { "a", "b" },
62 .n_in = 2,
63 .exp_out = "ab",
64 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080065 },
66 {
67 /* ssh escape in one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +093068 .esc_type = ESC_TYPE_SSH,
69 .in = { "a\r~." },
70 .n_in = 1,
71 .exp_out = "a\r",
72 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080073 },
74 {
75 /* ssh escape, partial ~ is not output. */
Andrew Jefferya72711a2023-04-18 18:19:41 +093076 .esc_type = ESC_TYPE_SSH,
77 .in = { "a\r~" },
78 .n_in = 1,
79 .exp_out = "a\r",
80 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080081 },
82 {
83 /* ssh escape split into individual reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +093084 .esc_type = ESC_TYPE_SSH,
85 .in = { "a", "\r", "~", "." },
86 .n_in = 4,
87 .exp_out = "a\r",
88 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080089 },
90 {
91 /* ssh escape, escaped. */
Andrew Jefferya72711a2023-04-18 18:19:41 +093092 .esc_type = ESC_TYPE_SSH,
93 .in = { "a\r~~." },
94 .n_in = 1,
95 .exp_out = "a\r~.",
96 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080097 },
98 {
99 /* ssh escape, escaped ~, and not completed. */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930100 .esc_type = ESC_TYPE_SSH,
101 .in = { "a\r~~" },
102 .n_in = 1,
103 .exp_out = "a\r~",
104 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800105 },
106 {
107 /* str escape, no match */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930108 .esc_type = ESC_TYPE_STR,
109 .esc_state = { .str = { .str = (const uint8_t *)"c" } },
110 .in = { "ab" },
111 .n_in = 1,
112 .exp_out = "ab",
113 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800114 },
115 {
116 /* str escape, one byte, as one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930117 .esc_type = ESC_TYPE_STR,
118 .esc_state = { .str = { .str = (const uint8_t *)"b" } },
119 .in = { "abc" },
120 .n_in = 1,
121 .exp_out = "ab",
122 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800123 },
124 {
125 /* str escape, multiple bytes, as one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930126 .esc_type = ESC_TYPE_STR,
127 .esc_state = { .str = { .str = (const uint8_t *)"bc" } },
128 .in = { "abcd" },
129 .n_in = 1,
130 .exp_out = "abc",
131 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800132 },
133 {
134 /* str escape, multiple bytes, split over reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930135 .esc_type = ESC_TYPE_STR,
136 .esc_state = { .str = { .str = (const uint8_t *)"bc" } },
137 .in = { "ab", "cd" },
138 .n_in = 2,
139 .exp_out = "abc",
140 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800141 },
142 {
143 /* str escape, not matched due to intermediate data */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930144 .esc_type = ESC_TYPE_STR,
145 .esc_state = { .str = { .str = (const uint8_t *)"ab" } },
146 .in = { "acb" },
147 .n_in = 1,
148 .exp_out = "acb",
149 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800150 },
151};
152
Andrew Jefferyf2232d52023-04-18 21:50:17 +0930153#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800154
155struct test_ctx ctxs[ARRAY_SIZE(tests)];
156
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800157int write_buf_to_fd(int fd, const uint8_t *buf, size_t len)
158{
159 struct test_ctx *ctx = &ctxs[fd];
160
161 assert(ctx->cur_out + len <= sizeof(ctx->out));
162 memcpy(ctx->out + ctx->cur_out, buf, len);
163 ctx->cur_out += len;
164
165 return 0;
166}
167
168ssize_t __read(int fd, void *buf, size_t len)
169{
170 struct test_ctx *ctx = &ctxs[fd];
171 const char *inbuf;
172 size_t inlen;
173
174 if (ctx->cur_in >= ctx->test->n_in)
175 return 0;
176
177 inbuf = ctx->test->in[ctx->cur_in];
178 inlen = strlen(inbuf);
179 assert(inlen <= len);
180 memcpy(buf, inbuf, inlen);
181 ctx->cur_in++;
182 return inlen;
183}
184
185void run_one_test(int idx, struct test *test, struct test_ctx *ctx)
186{
187 size_t exp_out_len;
188 int rc;
189
190 /* we store the index into the context array as a FD, so we
191 * can refer to it through the read & write callbacks.
192 */
193 ctx->client.console_sd = idx;
194 ctx->client.fd_in = idx;
195 ctx->client.esc_type = test->esc_type;
196 memcpy(&ctx->client.esc_state, &test->esc_state,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930197 sizeof(test->esc_state));
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800198 ctx->test = test;
199
200 for (;;) {
201 rc = process_tty(&ctx->client);
202 if (rc != PROCESS_OK)
203 break;
204 }
205
206 exp_out_len = strlen(test->exp_out);
207
208#ifdef DEBUG
Andrew Jefferya72711a2023-04-18 18:19:41 +0930209 printf("got: rc %d %s(%d), exp: rc %d %s(%ld)\n", rc, ctx->out,
210 ctx->cur_out, test->exp_rc, test->exp_out, exp_out_len);
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800211 fflush(stdout);
212#endif
213 assert(rc == test->exp_rc);
214 assert(exp_out_len == ctx->cur_out);
215 assert(!memcmp(ctx->out, test->exp_out, exp_out_len));
216}
217
218int main(void)
219{
Andrew Jeffery8f548f62023-04-18 11:48:49 +0930220 size_t i;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800221
222 for (i = 0; i < ARRAY_SIZE(tests); i++)
223 run_one_test(i, &tests[i], &ctxs[i]);
224
225 return EXIT_SUCCESS;
226}