diff mbox

[kvm-unit-tests,05/32] lib: better test name filtering

Message ID 20170421005004.137260-6-dmatlack@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

David Matlack April 21, 2017, 12:49 a.m. UTC
From: Peter Feiner <pfeiner@google.com>

Limited glob matching with leading or trailing '*'.

Tests (and globs of tests) can be excluded by prepending with a '-'.

Signed-off-by: Peter Feiner <pfeiner@google.com>
Signed-off-by: David Matlack <dmatlack@google.com>
---
 lib/libcflat.h |  2 ++
 lib/string.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 x86/vmx.c      | 52 +++++++++++++++++++++++++++-------------------------
 3 files changed, 70 insertions(+), 25 deletions(-)
diff mbox

Patch

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 96a37926f302..248fd023626e 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -105,6 +105,8 @@  extern void report_skip(const char *msg_fmt, ...);
 extern void report_info(const char *msg_fmt, ...);
 extern int report_summary(void);
 
+bool simple_glob(const char *text, const char *pattern);
+
 extern void dump_stack(void);
 extern void dump_frame_stack(const void *instruction, const void *frame);
 
diff --git a/lib/string.c b/lib/string.c
index 833f22be48c5..bc52d5c2695f 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -173,3 +173,44 @@  char *getenv(const char *name)
     }
     return NULL;
 }
+
+/* Very simple glob matching. Allows '*' at beginning and end of pattern. */
+bool simple_glob(const char *text, const char *pattern)
+{
+	bool star_start = false;
+	bool star_end = false;
+	size_t n = strlen(pattern);
+	char copy[n + 1];
+
+	if (pattern[0] == '*') {
+		pattern += 1;
+		n -= 1;
+		star_start = true;
+	}
+
+	strcpy(copy, pattern);
+
+	if (n > 0 && pattern[n - 1] == '*') {
+		n -= 1;
+		copy[n] = '\0';
+		star_end = true;
+	}
+
+	if (star_start && star_end)
+		return strstr(text, copy);
+
+	if (star_end)
+		return strstr(text, copy) == text;
+
+	if (star_start) {
+		size_t text_len = strlen(text);
+		const char *suffix;
+
+		if (n > text_len)
+			return false;
+		suffix = text + text_len - n;
+		return !strcmp(suffix, copy);
+	}
+
+	return !strcmp(text, copy);
+}
diff --git a/x86/vmx.c b/x86/vmx.c
index 0590b69ec1d2..651807a76a1e 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -1159,41 +1159,43 @@  out:
 
 extern struct vmx_test vmx_tests[];
 
-/* Match name with wanted allowing underscores in place of spaces. */
-static bool test_name_wanted(const char *name, const char *wanted)
+static bool
+test_wanted(const char *name, const char *filters[], int filter_count)
 {
+	int i;
+	bool positive = false;
+	bool match = false;
+	char clean_name[strlen(name) + 1];
+	char *c;
 	const char *n;
-	const char *w;
 
-	for (n = name, w = wanted; *n != '\0' && *w != '\0'; n++, w++) {
-		if (*n != *w && !(*n == ' ' && *w == '_'))
-			return false;
-	}
-	return *n == '\0' && *w == '\0';
-}
+	/* Replace spaces with underscores. */
+	n = name;
+	c = &clean_name[0];
+	do *c++ = (*n == ' ') ? '_' : *n;
+	while (*n++);
 
-static bool test_wanted(const char *name, char *wanted[], int nwanted)
-{
-	bool is_wanted = true;
-	int i;
-
-	if (!nwanted)
-		goto out;
+	for (i = 0; i < filter_count; i++) {
+		const char *filter = filters[i];
 
-	for (i = 0; i < nwanted; ++i) {
-		if (test_name_wanted(name, wanted[i]))
-			goto out;
+		if (filter[0] == '-') {
+			if (simple_glob(clean_name, filter + 1))
+				return false;
+		} else {
+			positive = true;
+			match |= simple_glob(clean_name, filter);
+		}
 	}
 
-	is_wanted = false;
-
-out:
-	if (is_wanted)
+	if (!positive || match) {
 		matched++;
-	return is_wanted;
+		return true;
+	} else {
+		return false;
+	}
 }
 
-int main(int argc, char *argv[])
+int main(int argc, const char *argv[])
 {
 	int i = 0;