blob: b818889ef59fe16215f395713da9e2c943deb858 [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
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800183 if (ctx->cur_in >= ctx->test->n_in)
184 return 0;
185
186 inbuf = ctx->test->in[ctx->cur_in];
187 inlen = strlen(inbuf);
188 assert(inlen <= len);
189 memcpy(buf, inbuf, inlen);
190 ctx->cur_in++;
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930191 return (ssize_t)inlen;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800192}
193
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930194void run_one_test(size_t idx, struct test *test, struct test_ctx *ctx)
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800195{
196 size_t exp_out_len;
197 int rc;
198
199 /* we store the index into the context array as a FD, so we
200 * can refer to it through the read & write callbacks.
201 */
Andrew Jeffery5c359cc2023-04-18 22:50:07 +0930202 assert(idx < INT_MAX);
203 ctx->client.console_sd = (int)idx;
204 ctx->client.fd_in = (int)idx;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800205 ctx->client.esc_type = test->esc_type;
206 memcpy(&ctx->client.esc_state, &test->esc_state,
Andrew Jefferya72711a2023-04-18 18:19:41 +0930207 sizeof(test->esc_state));
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800208 ctx->test = test;
209
210 for (;;) {
211 rc = process_tty(&ctx->client);
212 if (rc != PROCESS_OK)
213 break;
214 }
215
216 exp_out_len = strlen(test->exp_out);
217
218#ifdef DEBUG
Andrew Jefferya72711a2023-04-18 18:19:41 +0930219 printf("got: rc %d %s(%d), exp: rc %d %s(%ld)\n", rc, ctx->out,
220 ctx->cur_out, test->exp_rc, test->exp_out, exp_out_len);
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800221 fflush(stdout);
222#endif
223 assert(rc == test->exp_rc);
224 assert(exp_out_len == ctx->cur_out);
225 assert(!memcmp(ctx->out, test->exp_out, exp_out_len));
226}
227
228int main(void)
229{
Andrew Jeffery8f548f62023-04-18 11:48:49 +0930230 size_t i;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800231
232 for (i = 0; i < ARRAY_SIZE(tests); i++)
233 run_one_test(i, &tests[i], &ctxs[i]);
234
235 return EXIT_SUCCESS;
236}