blob: e8020f77fb2d422b908b1389313fb947e2ff858e [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
Alexander Hansene3f1aa12024-07-10 11:57:17 +020024#include "util.h"
25
Andrew Jeffery5c359cc2023-04-18 22:50:07 +093026static ssize_t __read(int fd, void *buf, size_t len);
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080027#define read __read
Andrew Jeffery71e7a242020-02-12 22:58:16 +103028#include "config.c"
Andrew Jeffery5e7c0782020-02-10 12:12:36 +103029#include "console-socket.c"
30#define main __main
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080031#include "console-client.c"
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080032#undef read
Andrew Jeffery5e7c0782020-02-10 12:12:36 +103033#undef main
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080034
35struct test {
Andrew Jefferya72711a2023-04-18 18:19:41 +093036 enum esc_type esc_type;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080037 union {
38 struct ssh_esc_state ssh;
39 struct str_esc_state str;
40 } esc_state;
Andrew Jefferya72711a2023-04-18 18:19:41 +093041 const char *in[4];
42 size_t n_in;
43 const char *exp_out;
44 int exp_rc;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080045};
46
47struct test_ctx {
Andrew Jefferya72711a2023-04-18 18:19:41 +093048 struct console_client client;
49 struct test *test;
50 uint8_t out[4096];
51 size_t cur_in;
52 size_t cur_out;
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080053};
54
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080055struct test tests[] = {
56 {
57 /* no escape code */
Andrew Jefferya72711a2023-04-18 18:19:41 +093058 .esc_type = ESC_TYPE_SSH,
59 .in = { "a" },
60 .n_in = 1,
61 .exp_out = "a",
62 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080063 },
64 {
65 /* no escape code, multiple reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +093066 .esc_type = ESC_TYPE_SSH,
67 .in = { "a", "b" },
68 .n_in = 2,
69 .exp_out = "ab",
70 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080071 },
72 {
73 /* ssh escape in one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +093074 .esc_type = ESC_TYPE_SSH,
75 .in = { "a\r~." },
76 .n_in = 1,
77 .exp_out = "a\r",
78 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080079 },
80 {
81 /* ssh escape, partial ~ is not output. */
Andrew Jefferya72711a2023-04-18 18:19:41 +093082 .esc_type = ESC_TYPE_SSH,
83 .in = { "a\r~" },
84 .n_in = 1,
85 .exp_out = "a\r",
86 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080087 },
88 {
89 /* ssh escape split into individual reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +093090 .esc_type = ESC_TYPE_SSH,
91 .in = { "a", "\r", "~", "." },
92 .n_in = 4,
93 .exp_out = "a\r",
94 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +080095 },
96 {
97 /* ssh escape, escaped. */
Andrew Jefferya72711a2023-04-18 18:19:41 +093098 .esc_type = ESC_TYPE_SSH,
99 .in = { "a\r~~." },
100 .n_in = 1,
101 .exp_out = "a\r~.",
102 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800103 },
104 {
105 /* ssh escape, escaped ~, and not completed. */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930106 .esc_type = ESC_TYPE_SSH,
107 .in = { "a\r~~" },
108 .n_in = 1,
109 .exp_out = "a\r~",
110 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800111 },
112 {
113 /* str escape, no match */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930114 .esc_type = ESC_TYPE_STR,
115 .esc_state = { .str = { .str = (const uint8_t *)"c" } },
116 .in = { "ab" },
117 .n_in = 1,
118 .exp_out = "ab",
119 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800120 },
121 {
122 /* str escape, one byte, as one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930123 .esc_type = ESC_TYPE_STR,
124 .esc_state = { .str = { .str = (const uint8_t *)"b" } },
125 .in = { "abc" },
126 .n_in = 1,
127 .exp_out = "ab",
128 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800129 },
130 {
131 /* str escape, multiple bytes, as one read */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930132 .esc_type = ESC_TYPE_STR,
133 .esc_state = { .str = { .str = (const uint8_t *)"bc" } },
134 .in = { "abcd" },
135 .n_in = 1,
136 .exp_out = "abc",
137 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800138 },
139 {
140 /* str escape, multiple bytes, split over reads */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930141 .esc_type = ESC_TYPE_STR,
142 .esc_state = { .str = { .str = (const uint8_t *)"bc" } },
143 .in = { "ab", "cd" },
144 .n_in = 2,
145 .exp_out = "abc",
146 .exp_rc = PROCESS_ESC,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800147 },
148 {
149 /* str escape, not matched due to intermediate data */
Andrew Jefferya72711a2023-04-18 18:19:41 +0930150 .esc_type = ESC_TYPE_STR,
151 .esc_state = { .str = { .str = (const uint8_t *)"ab" } },
152 .in = { "acb" },
153 .n_in = 1,
154 .exp_out = "acb",
155 .exp_rc = PROCESS_EXIT,
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800156 },
157};
158
Jeremy Kerrc5ce2cb2019-07-26 09:21:35 +0800159struct 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}