1*d4e67a97Sbluhm /* $OpenBSD: history.c,v 1.7 2017/07/05 15:31:45 bluhm Exp $ */
2ff514af6Sschwarze /*
3ff514af6Sschwarze * Copyright (c) 2016 Bastian Maerkisch <bmaerkisch@web.de>
475b77ce0Sschwarze * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
5ff514af6Sschwarze *
6ff514af6Sschwarze * Permission to use, copy, modify, and distribute these tests for any
7ff514af6Sschwarze * purpose with or without fee is hereby granted, provided that the above
8ff514af6Sschwarze * copyright notice and this permission notice appear in all copies.
9ff514af6Sschwarze *
10ff514af6Sschwarze * THESE TESTS ARE PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11ff514af6Sschwarze * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12ff514af6Sschwarze * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13ff514af6Sschwarze * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14ff514af6Sschwarze * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15ff514af6Sschwarze * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16ff514af6Sschwarze * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17ff514af6Sschwarze */
18ff514af6Sschwarze #include <err.h>
1975b77ce0Sschwarze #include <stdarg.h>
2075b77ce0Sschwarze #include <stdio.h>
21ff514af6Sschwarze #include <string.h>
22ff514af6Sschwarze
23ff514af6Sschwarze #ifdef READLINE
24ff514af6Sschwarze #include <readline/history.h>
25ff514af6Sschwarze #else
26036f87feSschwarze #include <readline/readline.h>
27ff514af6Sschwarze #endif
28ff514af6Sschwarze
29ff514af6Sschwarze
3075b77ce0Sschwarze /*
3175b77ce0Sschwarze * Test infrastructure function.
3275b77ce0Sschwarze * At the beginning of each test, call as "msg(__func__);".
3375b77ce0Sschwarze * Upon failure, call as "msg(fmt, ...);".
3475b77ce0Sschwarze * At the end of each test, call as "return msg(NULL);".
3575b77ce0Sschwarze */
3675b77ce0Sschwarze int
msg(const char * fmt,...)3775b77ce0Sschwarze msg(const char *fmt, ...)
3875b77ce0Sschwarze {
3975b77ce0Sschwarze static const char *testname = NULL;
4075b77ce0Sschwarze static int failed = 0;
4175b77ce0Sschwarze va_list ap;
4275b77ce0Sschwarze
4375b77ce0Sschwarze if (testname == NULL) {
4475b77ce0Sschwarze using_history();
4575b77ce0Sschwarze unstifle_history();
4675b77ce0Sschwarze testname = fmt;
4775b77ce0Sschwarze return 0;
4875b77ce0Sschwarze }
4975b77ce0Sschwarze
5075b77ce0Sschwarze if (fmt == NULL) {
5175b77ce0Sschwarze clear_history();
5275b77ce0Sschwarze unstifle_history();
5375b77ce0Sschwarze testname = NULL;
5475b77ce0Sschwarze if (failed == 0)
5575b77ce0Sschwarze return 0;
5675b77ce0Sschwarze failed = 0;
5775b77ce0Sschwarze return 1;
5875b77ce0Sschwarze }
5975b77ce0Sschwarze
6075b77ce0Sschwarze fprintf(stderr, "%s: ", testname);
6175b77ce0Sschwarze va_start(ap, fmt);
6275b77ce0Sschwarze vfprintf(stderr, fmt, ap);
6375b77ce0Sschwarze va_end(ap);
6475b77ce0Sschwarze fputc('\n', stderr);
6575b77ce0Sschwarze failed = 1;
6675b77ce0Sschwarze return 1;
6775b77ce0Sschwarze }
6875b77ce0Sschwarze
6975b77ce0Sschwarze void
check_current(const char * descr,const char * want)7075b77ce0Sschwarze check_current(const char *descr, const char *want)
7175b77ce0Sschwarze {
7275b77ce0Sschwarze HIST_ENTRY *he;
7375b77ce0Sschwarze
7475b77ce0Sschwarze he = current_history();
7575b77ce0Sschwarze
7675b77ce0Sschwarze if (want == NULL) {
7775b77ce0Sschwarze if (he != NULL)
7875b77ce0Sschwarze msg("Failed to move beyond the newest entry.");
7975b77ce0Sschwarze return;
8075b77ce0Sschwarze }
8175b77ce0Sschwarze
8275b77ce0Sschwarze if (he == NULL)
8375b77ce0Sschwarze msg("%s is NULL.", descr);
8475b77ce0Sschwarze else if (strcmp(he->line, want) != 0)
8575b77ce0Sschwarze msg("%s is \"%s\" instead of \"%s\".", descr, he->line, want);
8675b77ce0Sschwarze }
8775b77ce0Sschwarze
8875b77ce0Sschwarze void
check_get(int idx,const char * want)8975b77ce0Sschwarze check_get(int idx, const char *want)
9075b77ce0Sschwarze {
9175b77ce0Sschwarze HIST_ENTRY *he;
9275b77ce0Sschwarze
9375b77ce0Sschwarze if ((he = history_get(history_base + idx)) == NULL)
9475b77ce0Sschwarze msg("Get %d+%d returned NULL.", history_base, idx);
9575b77ce0Sschwarze else if (he->line == NULL)
9675b77ce0Sschwarze msg("Get %d+%d returned line == NULL.", history_base, idx);
9775b77ce0Sschwarze else if (strcmp(he->line, want) != 0)
9875b77ce0Sschwarze msg("Get %d+%d returned \"%s\" instead of \"%s\".",
9975b77ce0Sschwarze history_base, idx, he->line, want);
10075b77ce0Sschwarze }
10175b77ce0Sschwarze
10275b77ce0Sschwarze
103ff514af6Sschwarze /* Fails if previous and next are interchanged. */
104ff514af6Sschwarze int
test_movement_direction(void)105ff514af6Sschwarze test_movement_direction(void)
106ff514af6Sschwarze {
10775b77ce0Sschwarze msg(__func__);
108ff514af6Sschwarze add_history("111");
109ff514af6Sschwarze add_history("222");
110ff514af6Sschwarze
111ff514af6Sschwarze while (previous_history() != NULL);
11275b77ce0Sschwarze check_current("Oldest entry", "111");
113ff514af6Sschwarze
114ff514af6Sschwarze /*
115ff514af6Sschwarze * Move to the most recent end of the history.
116ff514af6Sschwarze * This moves past the newest entry.
117ff514af6Sschwarze */
118ff514af6Sschwarze while (next_history() != NULL);
11975b77ce0Sschwarze check_current(NULL, NULL);
120ff514af6Sschwarze
12175b77ce0Sschwarze return msg(NULL);
122ff514af6Sschwarze }
123ff514af6Sschwarze
124ff514af6Sschwarze
125ff514af6Sschwarze /* Fails if the position is counted from the recent end. */
126ff514af6Sschwarze int
test_where(void)127ff514af6Sschwarze test_where(void)
128ff514af6Sschwarze {
12975b77ce0Sschwarze int ret;
130ff514af6Sschwarze
13175b77ce0Sschwarze msg(__func__);
132ff514af6Sschwarze
133ff514af6Sschwarze /*
134ff514af6Sschwarze * Adding four elements since set_pos(0) doesn't work
135ff514af6Sschwarze * for some versions of libedit.
136ff514af6Sschwarze */
137ff514af6Sschwarze add_history("111");
138ff514af6Sschwarze add_history("222");
139ff514af6Sschwarze add_history("333");
140ff514af6Sschwarze add_history("444");
141ff514af6Sschwarze
142ff514af6Sschwarze /* Set the pointer to the element "222". */
143ff514af6Sschwarze history_set_pos(1);
14475b77ce0Sschwarze if ((ret = where_history()) != 1)
14575b77ce0Sschwarze msg("Where returned %d instead of 1.", ret);
146ff514af6Sschwarze
14775b77ce0Sschwarze return msg(NULL);
148ff514af6Sschwarze }
149ff514af6Sschwarze
150f1ea67b5Sschwarze
151a30cee79Sschwarze /*
152a30cee79Sschwarze * Fails if the argument of history_get()
153a30cee79Sschwarze * does not refer to the zero-based index + history_base.
154a30cee79Sschwarze */
155a30cee79Sschwarze int
test_get(void)156a30cee79Sschwarze test_get(void)
157a30cee79Sschwarze {
15875b77ce0Sschwarze msg(__func__);
159a30cee79Sschwarze add_history("111");
160a30cee79Sschwarze add_history("222");
161a30cee79Sschwarze add_history("333");
162a30cee79Sschwarze add_history("444");
163a30cee79Sschwarze
164a30cee79Sschwarze /* Try to retrieve second element. */
16575b77ce0Sschwarze check_get(1, "222");
166a30cee79Sschwarze
16775b77ce0Sschwarze return msg(NULL);
168a30cee79Sschwarze }
169a30cee79Sschwarze
170a30cee79Sschwarze
171ff514af6Sschwarze /* Fails if set_pos returns 0 for success and -1 for failure. */
172ff514af6Sschwarze int
test_set_pos_return_values(void)173ff514af6Sschwarze test_set_pos_return_values(void)
174ff514af6Sschwarze {
175ff514af6Sschwarze int ret;
176ff514af6Sschwarze
17775b77ce0Sschwarze msg(__func__);
178ff514af6Sschwarze add_history("111");
179ff514af6Sschwarze add_history("222");
180ff514af6Sschwarze
181ff514af6Sschwarze /* This should fail. */
18275b77ce0Sschwarze if ((ret = history_set_pos(-1)) != 0)
18375b77ce0Sschwarze msg("Set_pos(-1) returned %d instead of 0.", ret);
184ff514af6Sschwarze
185ff514af6Sschwarze /*
186ff514af6Sschwarze * This should succeed.
187ff514af6Sschwarze * Note that we do not use the index 0 here, since that
188ff514af6Sschwarze * actually fails for some versions of libedit.
189ff514af6Sschwarze */
19075b77ce0Sschwarze if ((ret = history_set_pos(1)) != 1)
19175b77ce0Sschwarze msg("Set_pos(1) returned %d instead of 1.", ret);
192ff514af6Sschwarze
19375b77ce0Sschwarze return msg(NULL);
194ff514af6Sschwarze }
195ff514af6Sschwarze
196ff514af6Sschwarze
197ff514af6Sschwarze /* Fails if the index is one-based. */
198ff514af6Sschwarze int
test_set_pos_index(void)199ff514af6Sschwarze test_set_pos_index(void)
200ff514af6Sschwarze {
20175b77ce0Sschwarze msg(__func__);
202ff514af6Sschwarze add_history("111");
203ff514af6Sschwarze add_history("222");
204ff514af6Sschwarze
205ff514af6Sschwarze /* Do not test return value here since that might be broken, too. */
206ff514af6Sschwarze history_set_pos(0);
20775b77ce0Sschwarze check_current("Entry 0", "111");
208ff514af6Sschwarze
209ff514af6Sschwarze history_set_pos(1);
21075b77ce0Sschwarze check_current("Entry 1", "222");
211ff514af6Sschwarze
21275b77ce0Sschwarze return msg(NULL);
213ff514af6Sschwarze }
214ff514af6Sschwarze
215ff514af6Sschwarze
216ff514af6Sschwarze /* Fails if remove does not renumber. */
217ff514af6Sschwarze int
test_remove(void)218ff514af6Sschwarze test_remove(void)
219ff514af6Sschwarze {
22075b77ce0Sschwarze msg(__func__);
221ff514af6Sschwarze add_history("111");
222ff514af6Sschwarze add_history("222");
223ff514af6Sschwarze add_history("333");
22443cf2f44Sschwarze add_history("444");
225ff514af6Sschwarze
226ff514af6Sschwarze /* Remove the second item "222"; the index is zero-based. */
227ff514af6Sschwarze remove_history(1);
228ff514af6Sschwarze
229ff514af6Sschwarze /*
230ff514af6Sschwarze * Try to get the new second element using history_get.
231ff514af6Sschwarze * The argument of get is based on history_base.
232ff514af6Sschwarze */
23375b77ce0Sschwarze check_get(1, "333");
234ff514af6Sschwarze
235ff514af6Sschwarze /*
236ff514af6Sschwarze * Try to get the second element using set_pos/current.
237ff514af6Sschwarze * The index is zero-based.
238ff514af6Sschwarze */
239ff514af6Sschwarze history_set_pos(1);
24075b77ce0Sschwarze check_current("Entry 1", "333");
241ff514af6Sschwarze
24243cf2f44Sschwarze /* Remove the new second item "333". */
24343cf2f44Sschwarze remove_history(1);
24475b77ce0Sschwarze check_get(1, "444");
24543cf2f44Sschwarze
24675b77ce0Sschwarze return msg(NULL);
247ff514af6Sschwarze }
248ff514af6Sschwarze
249ff514af6Sschwarze
250ff514af6Sschwarze /* Fails if stifle doesn't discard existing entries. */
251ff514af6Sschwarze int
test_stifle_size(void)252ff514af6Sschwarze test_stifle_size(void)
253ff514af6Sschwarze {
25475b77ce0Sschwarze msg(__func__);
255ff514af6Sschwarze add_history("111");
256ff514af6Sschwarze add_history("222");
257ff514af6Sschwarze add_history("333");
258ff514af6Sschwarze
259ff514af6Sschwarze /* Reduce the size of the history. */
260ff514af6Sschwarze stifle_history(2);
261ff514af6Sschwarze if (history_length != 2)
26275b77ce0Sschwarze msg("Length is %d instead of 2.", history_length);
263ff514af6Sschwarze
26475b77ce0Sschwarze return msg(NULL);
265ff514af6Sschwarze }
266ff514af6Sschwarze
267ff514af6Sschwarze
268ff514af6Sschwarze /* Fails if add doesn't increase history_base if the history is full. */
269ff514af6Sschwarze int
test_stifle_base(void)270ff514af6Sschwarze test_stifle_base(void)
271ff514af6Sschwarze {
27275b77ce0Sschwarze msg(__func__);
273ff514af6Sschwarze stifle_history(2);
274ff514af6Sschwarze
275ff514af6Sschwarze /* Add one more than the maximum size. */
276ff514af6Sschwarze add_history("111");
277ff514af6Sschwarze add_history("222");
278ff514af6Sschwarze add_history("333");
279ff514af6Sschwarze
280ff514af6Sschwarze /* The history_base should have changed. */
281ff514af6Sschwarze if (history_base != 2)
28275b77ce0Sschwarze msg("Base is %d instead of 2.", history_base);
283ff514af6Sschwarze
28475b77ce0Sschwarze return msg(NULL);
285ff514af6Sschwarze }
286ff514af6Sschwarze
287ff514af6Sschwarze
288ff514af6Sschwarze int
main(void)289ff514af6Sschwarze main(void)
290ff514af6Sschwarze {
291ff514af6Sschwarze int fail = 0;
292ff514af6Sschwarze
29375b77ce0Sschwarze fail += test_movement_direction();
29475b77ce0Sschwarze fail += test_where();
29575b77ce0Sschwarze fail += test_get();
29675b77ce0Sschwarze fail += test_set_pos_return_values();
29775b77ce0Sschwarze fail += test_set_pos_index();
29875b77ce0Sschwarze fail += test_remove();
29975b77ce0Sschwarze fail += test_stifle_size();
30075b77ce0Sschwarze fail += test_stifle_base();
30175b77ce0Sschwarze
302ff514af6Sschwarze if (fail)
303ff514af6Sschwarze errx(1, "%d test(s) failed.", fail);
304ff514af6Sschwarze return 0;
305ff514af6Sschwarze }
306