1/*
2 * Copyright (c) 2003-2012 Tim Kientzle
3 * Copyright (c) 2012 Andres Mejia
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "test_utils.h"
28
29#include <stdlib.h>
30#include <string.h>
31
32/* Filter tests against a glob pattern. Returns non-zero if test matches
33 * pattern, zero otherwise. A '^' at the beginning of the pattern negates
34 * the return values (i.e. returns zero for a match, non-zero otherwise.
35 */
36static int
37test_filter(const char *pattern, const char *test)
38{
39	int retval = 0;
40	int negate = 0;
41	const char *p = pattern;
42	const char *t = test;
43
44	if (p[0] == '^')
45	{
46		negate = 1;
47		p++;
48	}
49
50	while (1)
51	{
52		if (p[0] == '\\')
53			p++;
54		else if (p[0] == '*')
55		{
56			while (p[0] == '*')
57				p++;
58			if (p[0] == '\\')
59				p++;
60			if ((t = strchr(t, p[0])) == 0)
61				break;
62		}
63		if (p[0] != t[0])
64			break;
65		if (p[0] == '\0') {
66			retval = 1;
67			break;
68		}
69		p++;
70		t++;
71	}
72
73	return (negate) ? !retval : retval;
74}
75
76int get_test_set(int *test_set, int limit, const char *test,
77	struct test_list_t *tests)
78{
79	int start, end;
80	int idx = 0;
81
82	if (test == NULL) {
83		/* Default: Run all tests. */
84		for (;idx < limit; idx++)
85			test_set[idx] = idx;
86		return (limit);
87	}
88	if (*test >= '0' && *test <= '9') {
89		const char *vp = test;
90		start = 0;
91		while (*vp >= '0' && *vp <= '9') {
92			start *= 10;
93			start += *vp - '0';
94			++vp;
95		}
96		if (*vp == '\0') {
97			end = start;
98		} else if (*vp == '-') {
99			++vp;
100			if (*vp == '\0') {
101				end = limit - 1;
102			} else {
103				end = 0;
104				while (*vp >= '0' && *vp <= '9') {
105					end *= 10;
106					end += *vp - '0';
107					++vp;
108				}
109			}
110		} else
111			return (-1);
112		if (start < 0 || end >= limit || start > end)
113			return (-1);
114		while (start <= end)
115			test_set[idx++] = start++;
116	} else {
117		for (start = 0; start < limit; ++start) {
118			const char *name = tests[start].name;
119			if (test_filter(test, name))
120				test_set[idx++] = start;
121		}
122	}
123	return ((idx == 0)?-1:idx);
124}
125