xref: /openbsd-src/regress/lib/libedit/readline/history.c (revision d4e67a97b48f1b52d1ab469d4665694e452560c5)
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