From 848cb697ce280c2084fa658f83766b5e7891ae1b Mon Sep 17 00:00:00 2001 From: Lukas Forer Date: Fri, 27 Dec 2024 09:41:25 +0100 Subject: [PATCH] Support complex queries --- .../nf/test/commands/RunTestsCommand.java | 13 ++- .../nf/test/core/TagQueryExpression.java | 75 ++++++++++++++++ .../nf/test/core/TestSuiteResolverTest.java | 87 +++++++++++++++---- 3 files changed, 156 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/askimed/nf/test/core/TagQueryExpression.java diff --git a/src/main/java/com/askimed/nf/test/commands/RunTestsCommand.java b/src/main/java/com/askimed/nf/test/commands/RunTestsCommand.java index f13a9dad..cc3fb636 100644 --- a/src/main/java/com/askimed/nf/test/commands/RunTestsCommand.java +++ b/src/main/java/com/askimed/nf/test/commands/RunTestsCommand.java @@ -132,6 +132,11 @@ public class RunTestsCommand extends AbstractCommand { "--tag" }, split = ",", description = "Execute only tests with this tag", required = false, showDefaultValue = Visibility.ALWAYS) private List tags = new Vector(); + @Option(names = { + "--query" }, description = "Execute only tests that match this expression", required = false) + private String query = null; + + private static Logger log = LoggerFactory.getLogger(RunTestsCommand.class); @Override @@ -254,7 +259,13 @@ public Integer execute() throws Exception { environment.setPluginManager(manager); TestSuiteResolver testSuiteResolver = new TestSuiteResolver(environment); - List testSuits = testSuiteResolver.parse(scripts, new TagQuery(tags)); + + TagQuery tagQuery = new TagQuery(tags); + if (query != null) { + tagQuery = new TagQueryExpression(query); + } + + List testSuits = testSuiteResolver.parse(scripts, tagQuery); testSuits.sort(TestSuiteSorter.getDefault()); if (shard != null && !testSuits.isEmpty()) { diff --git a/src/main/java/com/askimed/nf/test/core/TagQueryExpression.java b/src/main/java/com/askimed/nf/test/core/TagQueryExpression.java new file mode 100644 index 00000000..1060618c --- /dev/null +++ b/src/main/java/com/askimed/nf/test/core/TagQueryExpression.java @@ -0,0 +1,75 @@ +package com.askimed.nf.test.core; + +import groovy.util.Eval; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TagQueryExpression extends TagQuery { + + private String query; + + public TagQueryExpression(String query) { + this.query = query; + } + + public boolean matches(ITaggable taggable) { + if (query == null || query.trim().isEmpty()) { + return true; + } + + Map bindingContext = createBindingContext(taggable); + + try { + return (Boolean) Eval.me("tags", bindingContext.get("tags"), query); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid query: " + query, e); + } + } + + private Map createBindingContext(ITaggable taggable) { + Map tagMap = new HashMap<>(); + Map context = new HashMap<>(); + + // Add tags from the current taggable + taggable.getTags().forEach(tag -> { + tagMap.put(tag.toLowerCase(), true); + }); + tagMap.put(taggable.getName(), true); + + // Add parent tags recursively + ITaggable parent = taggable.getParent(); + while (parent != null) { + parent.getTags().forEach(tag -> { + tagMap.put(tag.toLowerCase(), true); + }); + tagMap.put(parent.getName(), true); + parent = parent.getParent(); + } + + context.put("tags", new DefaultTagMap(tagMap)); // Map for key-based access + context.put("query", query); // The actual query as a string + + return context; + } + + @Override + public String toString() { + return query; + } + + + // Custom map to handle missing keys + private static class DefaultTagMap extends HashMap { + public DefaultTagMap(Map map) { + super(map); + } + + @Override + public Boolean get(Object key) { + return super.getOrDefault(key, false); + } + } +} diff --git a/src/test/java/com/askimed/nf/test/core/TestSuiteResolverTest.java b/src/test/java/com/askimed/nf/test/core/TestSuiteResolverTest.java index b6c36346..a5e5b231 100644 --- a/src/test/java/com/askimed/nf/test/core/TestSuiteResolverTest.java +++ b/src/test/java/com/askimed/nf/test/core/TestSuiteResolverTest.java @@ -79,6 +79,13 @@ public void executeTestSuiteByName() throws Throwable { Assertions.assertTrue(tests.contains("test 1")); Assertions.assertTrue(tests.contains("test 2")); } + { + TagQuery query = new TagQueryExpression("tags['suite 1']"); + List tests = collectTests(query); + Assertions.assertEquals(2, tests.size()); + Assertions.assertTrue(tests.contains("test 1")); + Assertions.assertTrue(tests.contains("test 2")); + } } @Test @@ -95,36 +102,80 @@ public void executeTestsByTag() throws Throwable { Assertions.assertEquals(1, tests.size()); Assertions.assertTrue(tests.contains("test 1")); } + { + TagQuery query = new TagQueryExpression("tags['tag2']"); + List tests = collectTests(query); + Assertions.assertEquals(1, tests.size()); + Assertions.assertTrue(tests.contains("test 1")); + } } @Test public void executeTestsByTagAcrossSuites() throws Throwable { - - TagQuery query = new TagQuery("tag5"); - List tests = collectTests(query); - Assertions.assertEquals(2, tests.size()); - Assertions.assertTrue(tests.contains("test 2")); - Assertions.assertTrue(tests.contains("test 3")); + { + TagQuery query = new TagQuery("tag5"); + List tests = collectTests(query); + Assertions.assertEquals(2, tests.size()); + Assertions.assertTrue(tests.contains("test 2")); + Assertions.assertTrue(tests.contains("test 3")); + } + { + TagQuery query = new TagQueryExpression("tags['tag5']"); + List tests = collectTests(query); + Assertions.assertEquals(2, tests.size()); + Assertions.assertTrue(tests.contains("test 2")); + Assertions.assertTrue(tests.contains("test 3")); + } + { + TagQuery query = new TagQuery("!tag5"); + List tests = collectTests(query); + Assertions.assertEquals(1, tests.size()); + Assertions.assertTrue(!tests.contains("test 2")); + Assertions.assertTrue(!tests.contains("test 3")); + } + { + TagQuery query = new TagQueryExpression("!tags['tag5']"); + List tests = collectTests(query); + Assertions.assertEquals(1, tests.size()); + Assertions.assertTrue(!tests.contains("test 2")); + Assertions.assertTrue(!tests.contains("test 3")); + } } @Test public void executeTestsBySuiteTag() throws Throwable { - - TagQuery query = new TagQuery("tag1"); - List tests = collectTests(query); - Assertions.assertEquals(2, tests.size()); - Assertions.assertTrue(tests.contains("test 1")); - Assertions.assertTrue(tests.contains("test 2")); + { + TagQuery query = new TagQuery("tag1"); + List tests = collectTests(query); + Assertions.assertEquals(2, tests.size()); + Assertions.assertTrue(tests.contains("test 1")); + Assertions.assertTrue(tests.contains("test 2")); + } + { + TagQuery query = new TagQueryExpression("tags['tag1']"); + List tests = collectTests(query); + Assertions.assertEquals(2, tests.size()); + Assertions.assertTrue(tests.contains("test 1")); + Assertions.assertTrue(tests.contains("test 2")); + } } @Test public void executeTestsByMultipleTags() throws Throwable { - - TagQuery query = new TagQuery("tag3", "tag4"); - List tests = collectTests(query); - Assertions.assertEquals(2, tests.size()); - Assertions.assertTrue(tests.contains("test 1")); - Assertions.assertTrue(tests.contains("test 2")); + { + TagQuery query = new TagQuery("tag3", "tag4"); + List tests = collectTests(query); + Assertions.assertEquals(2, tests.size()); + Assertions.assertTrue(tests.contains("test 1")); + Assertions.assertTrue(tests.contains("test 2")); + } + { + TagQueryExpression query = new TagQueryExpression("tags['tag3'] || tags['tag4']"); + List tests = collectTests(query); + Assertions.assertEquals(2, tests.size()); + Assertions.assertTrue(tests.contains("test 1")); + Assertions.assertTrue(tests.contains("test 2")); + } } protected List collectTests(TagQuery query) throws Throwable {