enable label filtering and validation

This commit is contained in:
Jonathan Shook 2023-09-09 20:31:15 -05:00
parent 31a75cd2e9
commit 186e87ac1b
19 changed files with 504 additions and 34 deletions

View File

@ -16,6 +16,7 @@
package io.nosqlbench.engine.api.activityapi.cyclelog.filters.tristate;
import io.nosqlbench.api.filtering.TristateFilter;
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.ResultReadable;
import java.util.function.Predicate;

View File

@ -16,6 +16,7 @@
package io.nosqlbench.engine.api.activityapi.cyclelog.filters.tristate;
import io.nosqlbench.api.filtering.TristateFilter;
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.ResultReadable;
import java.util.ArrayList;

View File

@ -16,6 +16,7 @@
package io.nosqlbench.engine.api.activityapi.cyclelog.filters.tristate;
import io.nosqlbench.api.filtering.TristateFilter;
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.ResultReadable;
import java.util.Arrays;

View File

@ -19,7 +19,7 @@ package io.nosqlbench.engine.api.activityapi.cyclelog.tristate;
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.MutableCycleResult;
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.ResultReadable;
import io.nosqlbench.engine.api.activityapi.cyclelog.filters.tristate.ResultFilteringSieve;
import io.nosqlbench.engine.api.activityapi.cyclelog.filters.tristate.TristateFilter;
import io.nosqlbench.api.filtering.TristateFilter;
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.CycleResult;
import org.junit.jupiter.api.Test;

View File

@ -400,7 +400,7 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
}
NBCLI.logger.debug("initializing annotators with config:'{}'", annotatorsConfig);
Annotators.init(annotatorsConfig);
Annotators.init(annotatorsConfig, options.getAnnotateLabelSpec());
Annotators.recordAnnotation(
Annotation.newBuilder()
.element(this)

View File

@ -52,6 +52,8 @@ public class NBCLIOptions {
private static final Map<String, String> DEFAULT_LABELS = Map.of("appname", "nosqlbench");
private static final String METRICS_PREFIX = "--metrics-prefix";
private static final String ANNOTATE_EVENTS = "--annotate";
private static final String ANNOTATE_LABELSPEC = "--annotate-labelspec";
private static final String ANNOTATORS_CONFIG = "--annotators";
private static final String PROMPUSH_CONFIG = "--prompush";
@ -200,6 +202,7 @@ public class NBCLIOptions {
private boolean wantsListApps;
private boolean dedicatedVerificationLogger;
private boolean wantsConsoleMetrics =true;
private String annotateLabelSpec="";
public boolean wantsLoggedMetrics() { return this.wantsConsoleMetrics; }
public boolean isWantsListApps() {
@ -258,6 +261,10 @@ public class NBCLIOptions {
this.dedicatedVerificationLogger = true;
}
public String getAnnotateLabelSpec() {
return annotateLabelSpec;
}
public enum Mode {
ParseGlobalsOnly,
ParseAllOptions
@ -497,6 +504,9 @@ public class NBCLIOptions {
arglist.removeFirst();
this.wantsConsoleMetrics =false;
break;
case ANNOTATE_LABELSPEC:
arglist.removeFirst();
this.annotateLabelSpec = this.readWordOrThrow(arglist, "labels validator specification");
default:
nonincludes.addLast(arglist.removeFirst());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 nosqlbench
* Copyright (c) 2022-2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,13 +18,10 @@ package io.nosqlbench.engine.core.annotation;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.nosqlbench.api.config.standard.*;
import io.nosqlbench.nb.annotations.Service;
import io.nosqlbench.api.annotations.Annotation;
import io.nosqlbench.api.annotations.Annotator;
import io.nosqlbench.api.config.standard.ConfigLoader;
import io.nosqlbench.api.config.standard.NBConfigurable;
import io.nosqlbench.api.config.standard.NBConfiguration;
import io.nosqlbench.api.config.standard.NBMapConfigurable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -43,6 +40,8 @@ public class Annotators {
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private static List<Annotator> annotators;
private static NBLabelsFilter filter;
private static NBLabelsValidator validator;
/**
* Initialize the active annotators. This method must be called before any others.
@ -50,7 +49,10 @@ public class Annotators {
* @param annotatorsConfig A (possibly empty) set of annotator configurations, in any form
* supported by {@link ConfigLoader}
*/
public synchronized static void init(String annotatorsConfig) {
public synchronized static void init(String annotatorsConfig, String annotateLabelSpec) {
filter = new NBLabelsFilter(annotateLabelSpec);
validator = new NBLabelsValidator(annotateLabelSpec);
ConfigLoader loader = new ConfigLoader();
annotators = new ArrayList<>();
@ -120,6 +122,8 @@ public class Annotators {
}
public static synchronized void recordAnnotation(Annotation annotation) {
annotation.applyLabelFunction(filter);
annotation.applyLabelFunction(validator);
for (Annotator annotator : getAnnotators()) {
try {
logger.trace(() -> "calling annotator " + annotator.getClass().getAnnotation(Service.class).selector());

View File

@ -20,6 +20,7 @@ import io.nosqlbench.api.config.NBLabeledElement;
import io.nosqlbench.api.config.NBLabels;
import java.util.Map;
import java.util.function.Function;
/**
* This is a general purpose representation of an event that describes
@ -75,6 +76,7 @@ public interface Annotation extends NBLabeledElement {
*/
NBLabels getLabels();
void applyLabelFunction(Function<NBLabels,NBLabels> labelfunc);
/**
* The details are an ordered map of all the content that you would want the user to see.
*

View File

@ -27,8 +27,10 @@ import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.TimeZone;
import java.util.function.Function;
public class MutableAnnotation implements Annotation {
@ -36,6 +38,8 @@ public class MutableAnnotation implements Annotation {
private String session = "SESSION_UNNAMED";
private final ZoneId GMT = ZoneId.of("GMT");
private final LinkedList<Function<NBLabels,NBLabels>> labelfuncs = new LinkedList<>();
@Expose
private Layer layer;
@ -48,6 +52,8 @@ public class MutableAnnotation implements Annotation {
@Expose
private Map<String, String> details = new LinkedHashMap<>();
NBLabels labels = NBLabels.forKV();
private final ZoneId zoneid = ZoneId.of("GMT");
private NBLabeledElement element;
@ -69,6 +75,7 @@ public class MutableAnnotation implements Annotation {
private void setElement(NBLabeledElement element) {
this.element = element;
this.labels = element.getLabels();
}
public void setSession(String sessionName) {
@ -108,7 +115,16 @@ public class MutableAnnotation implements Annotation {
@Override
public NBLabels getLabels() {
return element.getLabels();
NBLabels labels= element.getLabels();
for (Function<NBLabels, NBLabels> f : labelfuncs) {
labels = f.apply(labels);
}
return labels;
}
@Override
public void applyLabelFunction(Function<NBLabels, NBLabels> labelfunc) {
labelfuncs.add(labelfunc);
}
@Override

View File

@ -153,6 +153,9 @@ public class MapLabels implements NBLabels {
}
public String toString() {
if (labels.size()==0) {
return "{}";
}
StringBuilder sb = new StringBuilder("{");
labels.forEach((k,v) -> {
sb.append(k).append(":\\\"").append(v).append("\\\"").append(",");
@ -204,4 +207,19 @@ public class MapLabels implements NBLabels {
for (int i = 0; i < labelsAndValues.length; i+=2) childLabels.put(labelsAndValues[i].toString(), labelsAndValues[i + 1].toString());
return childLabels;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MapLabels mapLabels = (MapLabels) o;
return Objects.equals(labels, mapLabels.labels);
}
@Override
public int hashCode() {
return labels != null ? labels.hashCode() : 0;
}
}

View File

@ -33,14 +33,14 @@ public class NBLabelSpec {
throw new BasicError("Unable to parse labels to set:" + labeldata);
}
if (parts[1].startsWith("#")) {
buf = buf.and(NBLabels.forKV().andInstances(parts[0], parts[1].substring(1)));
buf = buf.and(NBLabels.forKV().and(parts[0], parts[1].substring(1)));
} else if (parts[1].startsWith("$")) {
buf = buf.and(NBLabels.forKV().andTypes(parts[0], parts[1].substring(1)));
buf = buf.and(NBLabels.forKV().and(parts[0], parts[1].substring(1)));
} else {
// if (parts[1].matches(".*[0-9]+.*")) {
// throw new BasicError("You have specified an auxiliary tag which contains numbers in its value (" + component + "), but you have not designated it as a dimension, as in " + parts[0] + ":$" + parts[1] + " or an instance value, as in " + parts[0] + ":#" + parts[1]);
// }
buf = buf.and(NBLabels.forKV().andTypes(parts[0], parts[1]));
buf = buf.and(NBLabels.forKV().and(parts[0], parts[1]));
}
}
return buf;

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.api.config.standard;
import io.nosqlbench.api.config.NBLabels;
import io.nosqlbench.api.filtering.FilteringSieve;
import io.nosqlbench.api.filtering.TristateFilter;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Pattern;
public class NBLabelsFilter implements Function<NBLabels, NBLabels> {
private final FilteringSieve<String> filter;
public NBLabelsFilter(String config) {
FilteringSieve.Builder<String> filterBuilder = new FilteringSieve.Builder<>();
for (String component : config.split("[ ;,]")) {
TristateFilter.Policy policyForStage = TristateFilter.Policy.Keep;
if (component.startsWith("-")) {
component = component.substring(1);
policyForStage = TristateFilter.Policy.Discard;
} else if (component.startsWith("+")) {
component = component.substring(1);
}
Pattern pattern = Pattern.compile(component);
filterBuilder = filterBuilder.withPhase(s -> pattern.matcher(s).matches(), policyForStage);
}
filterBuilder=filterBuilder.keepByDefault();
this.filter = filterBuilder.build();
}
@Override
public NBLabels apply(NBLabels labels) {
Map<String, String> filteredMap = filter.filterMapKeys(labels.asMap());
return NBLabels.forMap(filteredMap);
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.api.config.standard;
import io.nosqlbench.api.config.NBLabels;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
public class NBLabelsValidator implements Function<NBLabels, NBLabels> {
private final static Logger logger = LogManager.getLogger(NBLabelsValidator.class);
private final String config;
private final List<String> requiredFields = new ArrayList<>();
private final List<String> disallowedFields = new ArrayList<>();
public NBLabelsValidator(String config) {
this.config = config;
for (String component : config.split("[ ;,]")) {
if (component.startsWith("-")) disallowedFields.add(component.substring(1));
if (component.startsWith("+")) requiredFields.add(component.substring(1));
}
}
@Override
public NBLabels apply(NBLabels labels) {
Set<String> keyset = labels.asMap().keySet();
LinkedList<String> missingFields = new LinkedList<>(requiredFields);
LinkedList<String> extraneousFields = new LinkedList<>(disallowedFields);
missingFields.removeIf(keyset::contains);
extraneousFields.removeIf(extra -> !keyset.contains(extra));
Result result = new Result(config, missingFields, extraneousFields);
if (!result.isError()) {
return labels;
}
logger.warn(result);
throw new RuntimeException(result.toString());
}
record Result(String config, LinkedList<String> missingFields, LinkedList<String> extraneousFields) {
public boolean isError() {
return !missingFields.isEmpty() || !extraneousFields.isEmpty();
}
@Override
public String toString() {
StringBuilder err = new StringBuilder();
if (!missingFields.isEmpty()) {
err.append("The label set is missing required label names: ").append(missingFields).append("\n");
}
if (!extraneousFields.isEmpty()) {
err.append("The label set has disallowed label names: ").append(extraneousFields).append("\n");
}
if (!err.isEmpty()) {
err.append("This is controlled by the labeling policy: '").append(config).append("'\n");
}
return err.toString();
}
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.api.filtering;
import java.util.function.Predicate;
public class FilterPhase<T> implements TristateFilter<T> {
private final Predicate<T> predicate;
private final Policy policy;
public FilterPhase(Predicate<T> predicate, Policy policy) {
this.predicate = predicate;
this.policy = policy;
}
@Override
public Policy apply(T cycleResult) {
if (predicate.test(cycleResult)) {
return policy;
}
return Policy.Ignore;
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.api.filtering;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
public class FilteringSieve<T> implements TristateFilter<T>{
private final List<TristateFilter<T>> sieve;
private final Policy defaultPolicy;
public FilteringSieve(Policy defaultPolicy, List<TristateFilter<T>> filterPhases) {
this.sieve = filterPhases;
this.defaultPolicy = defaultPolicy;
}
@Override
public Policy apply(T element) {
for (TristateFilter<T> tTristateFilter : sieve) {
Policy phaseResult = tTristateFilter.apply(element);
if (phaseResult!=Policy.Ignore) return phaseResult;
}
return defaultPolicy;
}
public static class Builder<T> {
private final List<TristateFilter<T>> phaseFilters = new ArrayList<>();
private Policy defaultPolicy = Policy.Ignore;
public Builder<T> keepByDefault() {
this.defaultPolicy = Policy.Keep;
return this;
}
public Builder<T> discardByDefault() {
this.defaultPolicy = Policy.Discard;
return this;
}
public Builder<T> withPhase(Predicate<T> predicate, Policy policy) {
this.phaseFilters.add(new FilterPhase<>(predicate,policy));
return this;
}
public Builder<T> withPhase(TristateFilter<T> phaseFilter) {
this.phaseFilters.add(phaseFilter);
return this;
}
public FilteringSieve<T> build() {
return new FilteringSieve<>(defaultPolicy, phaseFilters);
}
}
public List<T> filterList(ArrayList<T> input) {
ArrayList<T> result = new ArrayList<T>();
for (T in : input) if (apply(in).equals(TristateFilter.Policy.Keep)) result.add(in);
return result;
}
public <U> Map<T,U> filterMapKeys(Map<T,U> input) {
Map<T,U> result = new LinkedHashMap<T,U>();
for (T k : input.keySet()) {
if (apply(k).equals(Policy.Keep)) {
result.put(k,input.get(k));
}
}
return result;
}
}

View File

@ -14,23 +14,24 @@
* limitations under the License.
*/
package io.nosqlbench.engine.api.activityapi.cyclelog.filters.tristate;
package io.nosqlbench.api.filtering;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* A tri-state filter allows for flexible configuration of
* <P>A tri-state filter allows for flexible configuration of
* multi-phase filtering. It effectively allows a conditional behavior
* for filtering logic that can answer "yes", "no", <em>and</em> "I don't know."
* </P>
*
* This can also be used to build classic bi-state filtering, such as
* <P>This can also be used to build classic bi-state filtering, such as
* filters that use a boolean predicate to say "keep" or "discard." Where the
* tri-state filtering pattern shines, however, is in the ability to combine
* different filtering rules to build a sophisticated filter at run-time
* that bi-state filtering would prevent.
* that bi-state filtering would prevent.</P>
*
* In contrast to the bi-state filter, the default policy that is applied when
* <P>In contrast to the bi-state filter, the default policy that is applied when
* <em>not</em> matching an item with the predicate is to simply ignore it.
* This means that in order to implement both matching and discarding
* policies like a bi-state filter, you must do one of the following:
@ -38,22 +39,22 @@ import java.util.function.Predicate;
* <li>Implement a default policy that overrides the "Ignore" action.</li>
* <li>Use both "keep" and "discard" predicates together in sequence.</li>
* </ul>
* </P>
*
* The two techniques above are not mutually exclusive. In practice, tri-state
* <P>The two techniques above are not mutually exclusive. In practice, tri-state
* filters are used to build up chains of filters which can delegate down
* the chain if up-stream filters do not have enough information to make
* a keep or discard determination. Even in chained filters will have a
* default policy that will override the "ignore" outcome.
* default policy that will override the "ignore" outcome.</P>
*
* Filter chains that
* <P>Filter chains that
* have a default "exclude" policy that overrides "ignore" policies are
* called "exclusive" filters. Their counterparts are "inclusive" filters.
* In other words, Exclusive tri-state filters include an element if and only
* if there was a matching include rule before any matching exclude rules
* or the end of the filter chain.
* Inclusive tri-state filters exclude an element if and only if there was
* a matching exclude rule before any matching include rules or the end of
* the filter chain.
* or the end of the filter chain, whereas inclusive tri-state filters exclude
* an element if and only if there was a matching exclude rule before any matching
* include rules or the end of the filter chain.</P>
*/
public interface TristateFilter<T> extends Function<T, TristateFilter.Policy> {
@ -62,9 +63,8 @@ public interface TristateFilter<T> extends Function<T, TristateFilter.Policy> {
/**
* The filter action determines what action is taken for a given
* element that matches the predicate. If the whether to include or exclude a result
* of the filter matching. If the filter does not match, then neither
* include nor exclude are presumed. See the class docs for more details.
* element that matches the predicate.
*/
enum Policy {
Keep,
@ -74,11 +74,17 @@ public interface TristateFilter<T> extends Function<T, TristateFilter.Policy> {
/**
* Create a predicate that will override any Ignore outcomes with the provided policy.
* @param defaultPolicy The policy that will override non-actionable outcomes
*
* @param defaultPolicy
* The policy that will override non-actionable outcomes
* @return a Predicate that can be used to filter elements
*/
default Predicate<T> toDefaultingPredicate(Policy defaultPolicy) {
return new DefaultingPredicate<>(this,defaultPolicy);
return new DefaultingPredicate<>(this, defaultPolicy);
}
default TristateFilter<T> toDefaultingFilter(Policy defaultPolicy) {
return new DefaultingTriStateFilter(this,defaultPolicy);
}
class DefaultingPredicate<T> implements Predicate<T> {
@ -93,10 +99,10 @@ public interface TristateFilter<T> extends Function<T, TristateFilter.Policy> {
@Override
public boolean test(T t) {
Policy policyResult = filter.apply(t);
if (policyResult==Policy.Ignore) {
policyResult= defaultPolicy;
if (policyResult == Policy.Ignore) {
policyResult = defaultPolicy;
}
return policyResult==Policy.Keep;
return policyResult == Policy.Keep;
}
}
@ -104,11 +110,13 @@ public interface TristateFilter<T> extends Function<T, TristateFilter.Policy> {
/**
* Create a predicate that will return true if and only if the filter
* outcome matches the provided policy.
* @param matchingPolicy The policy that will signal true in the predicate.
*
* @param matchingPolicy
* The policy that will signal true in the predicate.
* @return a Predicate that can be used to filter elements
*/
default Predicate<T> toMatchingPredicate(Policy matchingPolicy) {
return new MatchingPredicate<>(this,matchingPolicy);
return new MatchingPredicate<>(this, matchingPolicy);
}
class MatchingPredicate<T> implements Predicate<T> {
@ -122,9 +130,25 @@ public interface TristateFilter<T> extends Function<T, TristateFilter.Policy> {
@Override
public boolean test(T t) {
return filter.apply(t)==matchOn;
return filter.apply(t) == matchOn;
}
}
class DefaultingTriStateFilter<U> implements TristateFilter<U> {
private final TristateFilter<U> wrappedFilter;
private final Policy defaultPolicy;
public DefaultingTriStateFilter(TristateFilter<U> innerFilter, Policy defaultPolicy) {
this.wrappedFilter = innerFilter;
this.defaultPolicy = defaultPolicy;
}
@Override
public Policy apply(U cycleResult) {
Policy policy = wrappedFilter.apply(cycleResult);
if (policy!=Policy.Ignore) return policy;
return defaultPolicy;
}
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.api.config.standard;
import io.nosqlbench.api.config.NBLabels;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class NBLabelsFilterTest {
@Test
public void testFilterLablesWildcardExclude() {
NBLabelsFilter f1 = new NBLabelsFilter("+abcd,-.*");
assertThat(f1.apply(NBLabels.forKV("abc", "def"))).isEqualTo(NBLabels.forKV());
assertThat(f1.apply(NBLabels.forKV("abcd", "defg"))).isEqualTo(NBLabels.forKV("abcd", "defg"));
assertThat(f1.apply(NBLabels.forKV("a_bcd", "def"))).isEqualTo(NBLabels.forKV());
}
@Test
public void testFilterLabelsWildcardInclude(){
NBLabelsFilter f2 = new NBLabelsFilter("-abcd,+.*");
assertThat(f2.apply(NBLabels.forKV("abc", "def"))).isEqualTo(NBLabels.forKV("abc", "def"));
assertThat(f2.apply(NBLabels.forKV("abcd", "defg","hijk","lmnop"))).isEqualTo(NBLabels.forKV("hijk","lmnop"));
assertThat(f2.apply(NBLabels.forKV("a_bcd", "def"))).isEqualTo(NBLabels.forKV("a_bcd","def"));}
@Test
public void testFilteredLabelsBasicNames() {
NBLabelsFilter f3 = new NBLabelsFilter("abcd,bcde,-fghi");
assertThat(f3.apply(NBLabels.forKV("abc", "def", "abcd","abcd"))).isEqualTo(NBLabels.forKV("abc","def","abcd", "abcd"));
assertThat(f3.apply(NBLabels.forKV("abcd", "defg"))).isEqualTo(NBLabels.forKV("abcd","defg"));
assertThat(f3.apply(NBLabels.forKV("bcde","sdf","a_bcd", "def","fghi","fghi"))).isEqualTo(NBLabels.forKV("bcde","sdf","a_bcd","def"));
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.api.config.standard;
import io.nosqlbench.api.config.NBLabels;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
class NBLabelsValidatorTest {
@Test
public void testNoViolations() {
NBLabelsValidator lv = new NBLabelsValidator("+needed -disallowed indifferent");
assertThat(lv.apply(NBLabels.forKV("needed","haveit","indifferent","isalsoallowed")))
.isEqualTo(NBLabels.forKV("needed","haveit","indifferent","isalsoallowed"));
}
@Test
public void testExtraneousViolations() {
NBLabelsValidator lv = new NBLabelsValidator("+needed -disallowed indifferent");
assertThrows(RuntimeException.class, () -> lv.apply(NBLabels.forKV("needed","haveit","indifferent","isalsoallowed","disallowed","neversaynever")));
}
@Test
public void TestMissingViolations() {
NBLabelsValidator lv = new NBLabelsValidator("+needed -disallowed indifferent");
assertThrows(RuntimeException.class, () -> lv.apply(NBLabels.forKV("indifferent","isalsoallowed","unrelated","events")));
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.api.filtering;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class FilteringSieveTest {
@Test
public void testStringFilteringSieve() {
FilteringSieve<String> filter = new FilteringSieve.Builder<String>()
.withPhase(s -> s.equals("amatch"), TristateFilter.Policy.Keep)
.withPhase(s -> s.equals("a mismatch"), TristateFilter.Policy.Discard)
.build();
assertThat(filter.apply("amatch")).isEqualTo(TristateFilter.Policy.Keep);
assertThat(filter.apply("a mismatch")).isEqualTo(TristateFilter.Policy.Discard);
assertThat(filter.apply("a something else")).isEqualTo(TristateFilter.Policy.Ignore);
TristateFilter<String> butDiscard = filter.toDefaultingFilter(TristateFilter.Policy.Discard);
assertThat(butDiscard.apply("a something else")).isEqualTo(TristateFilter.Policy.Discard);
}
}