blob: b3083b7c8bc77ceed7dba86880adf426a3b70b74 [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>
Andrew Jeffery5c359cc2023-04-18 22:50:07 +093018#include <errno.h>
19#include <limits.h>
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080020#include <stdint.h>
21#include <stdio.h>
Andrew Jeffery5c359cc2023-04-18 22:50:07 +093022#include <unistd.h>
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080023
Andrew Jeffery5c359cc2023-04-18 22:50:07 +093024static ssize_t __read(int fd, void *buf, size_t len);
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080025#define read __read
Andrew Jeffery71e7a242020-02-12 22:58:16 +103026#include "config.c"
Andrew Jeffery5e7c0782020-02-10 12:12:36 +103027#include "console-socket.c"
28#define main __main
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080029#include "console-client.c"
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080030#undef read
Andrew Jeffery5e7c0782020-02-10 12:12:36 +103031#undef main
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080032
33struct test {
Andrew Jefferya72711a2023-04-18 18:19:41 +093034 enum esc_type esc_type;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080035 union {
36 struct ssh_esc_state ssh;
37 struct str_esc_state str;
38 } esc_state;
Andrew Jefferya72711a2023-04-18 18:19:41 +093039 const char *in[4];
40 size_t n_in;
41 const char *exp_out;
42 int exp_rc;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080043};
44
45struct test_ctx {
Andrew Jefferya72711a2023-04-18 18:19:41 +093046 struct console_client client;
47 struct test *test;
48 uint8_t out[4096];
49 size_t cur_in;
50 size_t cur_out;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080051};
52
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080053struct test tests[] = {
54 {
55 /* no escape code */
Andrew Jefferya72711a2023-04-18 18:19:41 +093056 .esc_type = ESC_TYPE_SSH,
57 .in = { "a" },
58 .n_in = 1,
59 .exp_out = "a",
60 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080061 },
62 {
63 /* no escape code, multiple reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +093064 .esc_type = ESC_TYPE_SSH,
65 .in = { "a", "b" },
66 .n_in = 2,
67 .exp_out = "ab",
68 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080069 },
70 {
71 /* ssh escape in one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +093072 .esc_type = ESC_TYPE_SSH,
73 .in = { "a\r~." },
74 .n_in = 1,
75 .exp_out = "a\r",
76 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080077 },
78 {
79 /* ssh escape, partial ~ is not output. */
Andrew Jefferya72711a2023-04-18 18:19:41 +093080 .esc_type = ESC_TYPE_SSH,
81 .in = { "a\r~" },
82 .n_in = 1,
83 .exp_out = "a\r",
84 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080085 },
86 {
87 /* ssh escape split into individual reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +093088 .esc_type = ESC_TYPE_SSH,
89 .in = { "a", "\r", "~", "." },
90 .n_in = 4,
91 .exp_out = "a\r",
92 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080093 },
94 {
95 /* ssh escape, escaped. */
Andrew Jefferya72711a2023-04-18 18:19:41 +093096 .esc_type = ESC_TYPE_SSH,
97 .in = { "a\r~~." },
98 .n_in = 1,
99 .exp_out = "a\r~.",
100 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800101 },
102 {
103 /* ssh escape, escaped ~, and not completed. */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930104 .esc_type = ESC_TYPE_SSH,
105 .in = { "a\r~~" },
106 .n_in = 1,
107 .exp_out = "a\r~",
108 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800109 },
110 {
111 /* str escape, no match */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930112 .esc_type = ESC_TYPE_STR,
113 .esc_state = { .str = { .str = (const uint8_t *)"c" } },
114 .in = { "ab" },
115 .n_in = 1,
116 .exp_out = "ab",
117 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800118 },
119 {
120 /* str escape, one byte, as one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930121 .esc_type = ESC_TYPE_STR,
122 .esc_state = { .str = { .str = (const uint8_t *)"b" } },
123 .in = { "abc" },
124 .n_in = 1,
125 .exp_out = "ab",
126 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800127 },
128 {
129 /* str escape, multiple bytes, as one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930130 .esc_type = ESC_TYPE_STR,
131 .esc_state = { .str = { .str = (const uint8_t *)"bc" } },
132 .in = { "abcd" },
133 .n_in = 1,
134 .exp_out = "abc",
135 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800136 },
137 {
138 /* str escape, multiple bytes, split over reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930139 .esc_type = ESC_TYPE_STR,
140 .esc_state = { .str = { .str = (const uint8_t *)"bc" } },
141 .in = { "ab", "cd" },
142 .n_in = 2,
143 .exp_out = "abc",
144 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800145 },
146 {
147 /* str escape, not matched due to intermediate data */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930148 .esc_type = ESC_TYPE_STR,
149 .esc_state = { .str = { .str = (const uint8_t *)"ab" } },
150 .in = { "acb" },
151 .n_in = 1,
152 .exp_out = "acb",
153 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800154 },
155};
156
Andrew Jefferyf2232d52023-04-18 21:50:17 +0930157#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800158
159struct test_ctx ctxs[ARRAY_SIZE(tests)];
160
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800161int write_buf_to_fd(int fd, const uint8_t *buf, size_t len)
162{
163 struct test_ctx *ctx = &ctxs[fd];
164
165 assert(ctx->cur_out + len <= sizeof(ctx->out));
166 memcpy(ctx->out + ctx->cur_out, buf, len);
167 ctx->cur_out += len;
168
169 return 0;
170}
171
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930172static ssize_t __read(int fd, void *buf, size_t len)
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800173{
174 struct test_ctx *ctx = &ctxs[fd];
175 const char *inbuf;
176 size_t inlen;
177
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930178 if (len > SSIZE_MAX) {
179 errno = EINVAL;
180 return -1;
181 }
182
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930183 if (ctx->cur_in >= ctx->test->n_in) {
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800184 return 0;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930185 }
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800186
187 inbuf = ctx->test->in[ctx->cur_in];
188 inlen = strlen(inbuf);
189 assert(inlen <= len);
190 memcpy(buf, inbuf, inlen);
191 ctx->cur_in++;
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930192 return (ssize_t)inlen;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800193}
194
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930195void run_one_test(size_t idx, struct test *test, struct test_ctx *ctx)
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800196{
197 size_t exp_out_len;
198 int rc;
199
200 /* we store the index into the context array as a FD, so we
201 * can refer to it through the read & write callbacks.
202 */
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930203 assert(idx < INT_MAX);
204 ctx->client.console_sd = (int)idx;
205 ctx->client.fd_in = (int)idx;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800206 ctx->client.esc_type = test->esc_type;
207 memcpy(&ctx->client.esc_state, &test->esc_state,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930208 sizeof(test->esc_state));
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800209 ctx->test = test;
210
211 for (;;) {
212 rc = process_tty(&ctx->client);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930213 if (rc != PROCESS_OK) {
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800214 break;
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930215 }
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800216 }
217
218 exp_out_len = strlen(test->exp_out);
219
220#ifdef DEBUG
Andrew Jefferya72711a2023-04-18 18:19:41 +0930221 printf("got: rc %d %s(%d), exp: rc %d %s(%ld)\n", rc, ctx->out,
222 ctx->cur_out, test->exp_rc, test->exp_out, exp_out_len);
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800223 fflush(stdout);
224#endif
225 assert(rc == test->exp_rc);
226 assert(exp_out_len == ctx->cur_out);
227 assert(!memcmp(ctx->out, test->exp_out, exp_out_len));
228}
229
230int main(void)
231{
Andrew Jeffery8f548f62023-04-18 11:48:49 +0930232 size_t i;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800233
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930234 for (i = 0; i < ARRAY_SIZE(tests); i++) {
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800235 run_one_test(i, &tests[i], &ctxs[i]);
Andrew Jeffery2834c5b2023-04-19 12:47:09 +0930236 }
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800237
238 return EXIT_SUCCESS;
239}