From 6944655455b3e89ae698faa0285fbc97c0ae76f6 Mon Sep 17 00:00:00 2001 From: German Osin Date: Thu, 18 Sep 2025 14:49:49 +0200 Subject: [PATCH 1/2] BE: Fixed filter comparators --- .../ui/service/ConsumerGroupService.java | 2 +- .../ui/service/KafkaConnectService.java | 2 +- .../kafbat/ui/service/index/NgramFilter.java | 21 ++++---- .../ui/service/index/SchemasFilter.java | 5 ++ .../index/AbstractNgramFilterTest.java | 42 ++++++++++++++++ .../service/index/AclBindingFilterTest.java | 43 +++++++++++++++++ .../index/ConsumerGroupFilterTest.java | 36 ++++++++++++++ .../index/KafkaConnectNgramFilterTest.java | 48 +++++++++++++++++++ .../ui/service/index/SchemasFilterTest.java | 32 +++++++++++++ 9 files changed, 221 insertions(+), 10 deletions(-) create mode 100644 api/src/test/java/io/kafbat/ui/service/index/AbstractNgramFilterTest.java create mode 100644 api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java create mode 100644 api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java create mode 100644 api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java create mode 100644 api/src/test/java/io/kafbat/ui/service/index/SchemasFilterTest.java diff --git a/api/src/main/java/io/kafbat/ui/service/ConsumerGroupService.java b/api/src/main/java/io/kafbat/ui/service/ConsumerGroupService.java index ae2a81d6f..dfee842e2 100644 --- a/api/src/main/java/io/kafbat/ui/service/ConsumerGroupService.java +++ b/api/src/main/java/io/kafbat/ui/service/ConsumerGroupService.java @@ -172,7 +172,7 @@ public Mono getConsumerGroupsPage( private Collection filterGroups(Collection groups, String search) { ClustersProperties.ClusterFtsProperties fts = clustersProperties.getFts(); ConsumerGroupFilter filter = new ConsumerGroupFilter(groups, fts.isEnabled(), fts.getConsumers()); - return filter.find(search, false); + return filter.find(search); } private Mono> loadSortedDescriptions(ReactiveAdminClient ac, diff --git a/api/src/main/java/io/kafbat/ui/service/KafkaConnectService.java b/api/src/main/java/io/kafbat/ui/service/KafkaConnectService.java index 43ae253cc..2d6dfae15 100644 --- a/api/src/main/java/io/kafbat/ui/service/KafkaConnectService.java +++ b/api/src/main/java/io/kafbat/ui/service/KafkaConnectService.java @@ -161,7 +161,7 @@ private List filterConnectors(List c ClustersProperties.ClusterFtsProperties fts = clustersProperties.getFts(); KafkaConnectNgramFilter filter = new KafkaConnectNgramFilter(connectors, fts.isEnabled(), fts.getConnect()); - return filter.find(search, false); + return filter.find(search); } private Stream getStringsForSearch(FullConnectorInfoDTO fullConnectorInfo) { diff --git a/api/src/main/java/io/kafbat/ui/service/index/NgramFilter.java b/api/src/main/java/io/kafbat/ui/service/index/NgramFilter.java index 58ab5d582..5afbd62a3 100644 --- a/api/src/main/java/io/kafbat/ui/service/index/NgramFilter.java +++ b/api/src/main/java/io/kafbat/ui/service/index/NgramFilter.java @@ -5,6 +5,7 @@ import com.google.common.cache.CacheBuilder; import io.kafbat.ui.config.ClustersProperties; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -35,18 +36,18 @@ public NgramFilter(ClustersProperties.NgramProperties properties, boolean enable .asMap(); public List find(String search) { - return find(search, true); + return find(search, null); } - public List find(String search, boolean sort) { + public List find(String search, Comparator comparator) { if (search == null || search.isBlank()) { - return list(this.getItems().stream().map(Tuple2::getT2), sort); + return list(this.getItems().stream().map(Tuple2::getT2), comparator); } if (!enabled) { return list(this.getItems() .stream() .filter(t -> t.getT1().stream().anyMatch(s -> CI.contains(s, search))) - .map(Tuple2::getT2), sort); + .map(Tuple2::getT2), comparator); } try { List> result = new ArrayList<>(); @@ -63,18 +64,22 @@ public List find(String search, boolean sort) { } } } - if (sort) { + + if (comparator == null) { result.sort((o1, o2) -> Double.compare(o2.score, o1.score)); + } else { + result.sort((o1, o2) -> comparator.compare(o1.item, o2.item)); } + return result.stream().map(r -> r.item).toList(); } catch (Exception e) { throw new RuntimeException(e); } } - private List list(Stream stream, boolean sort) { - if (sort) { - return stream.sorted().toList(); + private List list(Stream stream, Comparator comparator) { + if (comparator != null) { + return stream.sorted(comparator).toList(); } else { return stream.toList(); } diff --git a/api/src/main/java/io/kafbat/ui/service/index/SchemasFilter.java b/api/src/main/java/io/kafbat/ui/service/index/SchemasFilter.java index bfe1516ca..553e63e32 100644 --- a/api/src/main/java/io/kafbat/ui/service/index/SchemasFilter.java +++ b/api/src/main/java/io/kafbat/ui/service/index/SchemasFilter.java @@ -14,6 +14,11 @@ public SchemasFilter(Collection subjects, boolean enabled, ClustersPrope this.subjects = subjects.stream().map(g -> Tuples.of(List.of(g), g)).toList(); } + @Override + public List find(String search) { + return super.find(search, String::compareTo); + } + @Override protected List, String>> getItems() { return this.subjects; diff --git a/api/src/test/java/io/kafbat/ui/service/index/AbstractNgramFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/AbstractNgramFilterTest.java new file mode 100644 index 000000000..801104207 --- /dev/null +++ b/api/src/test/java/io/kafbat/ui/service/index/AbstractNgramFilterTest.java @@ -0,0 +1,42 @@ +package io.kafbat.ui.service.index; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.kafbat.ui.config.ClustersProperties; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +abstract class AbstractNgramFilterTest { + private final ClustersProperties.NgramProperties ngramProperties = new ClustersProperties.NgramProperties(); + + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void testFind(boolean enabled) { + List items = items(); + + NgramFilter filter = buildFilter(items, enabled, ngramProperties); + List resultNoSearch = filter.find(null); + assertThat(resultNoSearch).isNotEmpty().containsExactlyInAnyOrderElementsOf(items); + + List resultWithCompare = filter.find(null, comparator()); + assertThat(resultWithCompare).isNotEmpty().containsExactlyInAnyOrderElementsOf(items); + + Map.Entry example = example(items); + List resultNoCompare = filter.find(example.getKey()); + assertThat(resultNoCompare).isNotEmpty().contains(example.getValue()); + } + + protected abstract NgramFilter buildFilter(List items, + boolean enabled, + ClustersProperties.NgramProperties ngramProperties); + + protected abstract List items(); + + protected abstract Comparator comparator(); + + protected abstract Map.Entry example(List items); +} diff --git a/api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java new file mode 100644 index 000000000..e02d402f2 --- /dev/null +++ b/api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java @@ -0,0 +1,43 @@ +package io.kafbat.ui.service.index; + +import io.kafbat.ui.config.ClustersProperties; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; +import org.apache.kafka.common.acl.AccessControlEntry; +import org.apache.kafka.common.acl.AclBinding; +import org.apache.kafka.common.acl.AclOperation; +import org.apache.kafka.common.acl.AclPermissionType; +import org.apache.kafka.common.resource.PatternType; +import org.apache.kafka.common.resource.ResourcePattern; +import org.apache.kafka.common.resource.ResourceType; + +public class AclBindingFilterTest extends AbstractNgramFilterTest{ + @Override + protected NgramFilter buildFilter(List items, boolean enabled, + ClustersProperties.NgramProperties ngramProperties) { + return new AclBindingNgramFilter(items, enabled, ngramProperties); + } + + @Override + protected List items() { + return IntStream.range(0, 100).mapToObj(i -> + new AclBinding( + new ResourcePattern(ResourceType.TOPIC, "resource-"+i, PatternType.LITERAL), + new AccessControlEntry("principal-"+i, "*", AclOperation.ALL, AclPermissionType.ALLOW) + ) + ).toList(); + } + + @Override + protected Comparator comparator() { + return Comparator.comparing(a -> a.entry().principal()); + } + + @Override + protected Map.Entry example(List items) { + AclBinding binding = items.getFirst(); + return Map.entry(binding.entry().principal(), binding); + } +} diff --git a/api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java new file mode 100644 index 000000000..bbe0a586a --- /dev/null +++ b/api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java @@ -0,0 +1,36 @@ +package io.kafbat.ui.service.index; + +import io.kafbat.ui.config.ClustersProperties; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; +import org.apache.kafka.clients.admin.ConsumerGroupListing; + +class ConsumerGroupFilterTest extends AbstractNgramFilterTest { + + @Override + protected NgramFilter buildFilter(List items, + boolean enabled, + ClustersProperties.NgramProperties ngramProperties) { + return new ConsumerGroupFilter(items, enabled, ngramProperties); + } + + @Override + protected List items() { + return IntStream.range(0, 100).mapToObj(i -> + new ConsumerGroupListing("resource-"+i, true) + ).toList(); + } + + @Override + protected Comparator comparator() { + return Comparator.comparing(ConsumerGroupListing::groupId); + } + + @Override + protected Map.Entry example(List items) { + ConsumerGroupListing first = items.getFirst(); + return Map.entry(first.groupId(), first); + } +} diff --git a/api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java new file mode 100644 index 000000000..8ed8f1fad --- /dev/null +++ b/api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java @@ -0,0 +1,48 @@ +package io.kafbat.ui.service.index; + +import io.kafbat.ui.config.ClustersProperties; +import io.kafbat.ui.model.ConnectorStateDTO; +import io.kafbat.ui.model.ConnectorStatusDTO; +import io.kafbat.ui.model.ConnectorTypeDTO; +import io.kafbat.ui.model.FullConnectorInfoDTO; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +class KafkaConnectNgramFilterTest extends AbstractNgramFilterTest { + + @Override + protected NgramFilter buildFilter(List items, + boolean enabled, + ClustersProperties.NgramProperties ngramProperties) { + return new KafkaConnectNgramFilter(items, enabled, ngramProperties); + } + + @Override + protected List items() { + return IntStream.range(0, 100).mapToObj(i -> + new FullConnectorInfoDTO( + "connect-"+i, + "connector-"+i, + "class", + ConnectorTypeDTO.SINK, + List.of(), + new ConnectorStatusDTO(ConnectorStateDTO.RUNNING, "reason"), + 1, + 0 + ) + ).toList(); + } + + @Override + protected Comparator comparator() { + return Comparator.comparing(FullConnectorInfoDTO::getConnect); + } + + @Override + protected Map.Entry example(List items) { + FullConnectorInfoDTO first = items.getFirst(); + return Map.entry(first.getConnect(), first); + } +} diff --git a/api/src/test/java/io/kafbat/ui/service/index/SchemasFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/SchemasFilterTest.java new file mode 100644 index 000000000..32d1348e3 --- /dev/null +++ b/api/src/test/java/io/kafbat/ui/service/index/SchemasFilterTest.java @@ -0,0 +1,32 @@ +package io.kafbat.ui.service.index; + +import io.kafbat.ui.config.ClustersProperties; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; + +class SchemasFilterTest extends AbstractNgramFilterTest { + + @Override + protected NgramFilter buildFilter(List items, boolean enabled, + ClustersProperties.NgramProperties ngramProperties) { + return new SchemasFilter(items, enabled, ngramProperties); + } + + @Override + protected List items() { + return IntStream.range(0, 100).mapToObj(i -> "schema-" + i).toList(); + } + + @Override + protected Comparator comparator() { + return String::compareTo; + } + + @Override + protected Map.Entry example(List items) { + String item = items.getFirst(); + return Map.entry(item, item); + } +} From 520a4b6972580b58a136ccbf01b1cb0f35db17b1 Mon Sep 17 00:00:00 2001 From: German Osin Date: Thu, 18 Sep 2025 15:52:26 +0200 Subject: [PATCH 2/2] Fixed checkstyle --- .../io/kafbat/ui/service/index/AclBindingFilterTest.java | 6 +++--- .../io/kafbat/ui/service/index/ConsumerGroupFilterTest.java | 2 +- .../ui/service/index/KafkaConnectNgramFilterTest.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java index e02d402f2..4c54702bd 100644 --- a/api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java +++ b/api/src/test/java/io/kafbat/ui/service/index/AclBindingFilterTest.java @@ -13,7 +13,7 @@ import org.apache.kafka.common.resource.ResourcePattern; import org.apache.kafka.common.resource.ResourceType; -public class AclBindingFilterTest extends AbstractNgramFilterTest{ +public class AclBindingFilterTest extends AbstractNgramFilterTest { @Override protected NgramFilter buildFilter(List items, boolean enabled, ClustersProperties.NgramProperties ngramProperties) { @@ -24,8 +24,8 @@ protected NgramFilter buildFilter(List items, boolean en protected List items() { return IntStream.range(0, 100).mapToObj(i -> new AclBinding( - new ResourcePattern(ResourceType.TOPIC, "resource-"+i, PatternType.LITERAL), - new AccessControlEntry("principal-"+i, "*", AclOperation.ALL, AclPermissionType.ALLOW) + new ResourcePattern(ResourceType.TOPIC, "resource-" + i, PatternType.LITERAL), + new AccessControlEntry("principal-" + i, "*", AclOperation.ALL, AclPermissionType.ALLOW) ) ).toList(); } diff --git a/api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java index bbe0a586a..0d2b73030 100644 --- a/api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java +++ b/api/src/test/java/io/kafbat/ui/service/index/ConsumerGroupFilterTest.java @@ -19,7 +19,7 @@ protected NgramFilter buildFilter(List items() { return IntStream.range(0, 100).mapToObj(i -> - new ConsumerGroupListing("resource-"+i, true) + new ConsumerGroupListing("resource-" + i, true) ).toList(); } diff --git a/api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java b/api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java index 8ed8f1fad..66cf7db44 100644 --- a/api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java +++ b/api/src/test/java/io/kafbat/ui/service/index/KafkaConnectNgramFilterTest.java @@ -23,8 +23,8 @@ protected NgramFilter buildFilter(List items() { return IntStream.range(0, 100).mapToObj(i -> new FullConnectorInfoDTO( - "connect-"+i, - "connector-"+i, + "connect-" + i, + "connector-" + i, "class", ConnectorTypeDTO.SINK, List.of(),