This commit is contained in:
Jonathan Shook 2025-01-08 13:04:55 -06:00
parent a28d321aaf
commit 8e6a2b4f7c
12 changed files with 60 additions and 43 deletions

View File

@ -18,8 +18,6 @@ package io.nosqlbench.adapter.cqld4;
import io.nosqlbench.adapter.cqld4.opmappers.Cqld4CoreOpMapper;
import io.nosqlbench.adapter.cqld4.optypes.Cqld4BaseOp;
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.templating.ParsedOp;
import io.nosqlbench.nb.api.config.standard.NBConfigModel;
import io.nosqlbench.nb.api.config.standard.NBConfiguration;
import io.nosqlbench.adapters.api.activityimpl.OpMapper;

View File

@ -19,7 +19,7 @@ package io.nosqlbench.adapters.api.activityimpl;
import com.codahale.metrics.Timer;
import groovy.lang.Binding;
import io.nosqlbench.adapters.api.activityimpl.uniform.Space;
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.Verifier;
import io.nosqlbench.adapters.api.activityimpl.uniform.ValidatorSource;
import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.CycleOp;
import io.nosqlbench.adapters.api.evalctx.*;
@ -37,7 +37,6 @@ import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.LongFunction;
@ -239,7 +238,7 @@ public abstract class BaseOpDispenser<OP extends CycleOp<?>, SPACE extends Space
}
@Override
public List<Validator> getValidator(NBComponent parent, ParsedOp pop, OpLookup lookup) {
public List<Verifier> getValidator(NBComponent parent, ParsedOp pop, OpLookup lookup) {
return CoreOpValidators.getValidator(this, pop, lookup);
}

View File

@ -2,13 +2,13 @@ package io.nosqlbench.adapters.api.activityimpl;
/*
* Copyright (c) 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
@ -18,7 +18,7 @@ package io.nosqlbench.adapters.api.activityimpl;
*/
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.Verifier;
import io.nosqlbench.adapters.api.templating.ParsedOp;
import io.nosqlbench.engine.api.templating.TypeAndTarget;
import io.nosqlbench.nb.api.components.core.NBComponent;
@ -32,8 +32,8 @@ import java.util.Optional;
public class CoreOpValidators {
private static final Logger logger = LogManager.getLogger(CoreOpValidators.class);
public static List<Validator> getValidator(NBComponent parent, ParsedOp pop, OpLookup lookup) {
List<Validator> validators = new ArrayList();
public static List<Verifier> getValidator(NBComponent parent, ParsedOp pop, OpLookup lookup) {
List<Verifier> validators = new ArrayList();
Optional<TypeAndTarget<CoreValidators, Object>> optionalValidator = pop.getOptionalTypeAndTargetEnum(
CoreValidators.class, Object.class);

View File

@ -2,13 +2,13 @@ package io.nosqlbench.adapters.api.activityimpl;
/*
* Copyright (c) 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
@ -18,13 +18,13 @@ package io.nosqlbench.adapters.api.activityimpl;
*/
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.Verifier;
public enum CoreValidators {
verify_fields(FieldVerifier.class);
private final Class<? extends Validator> validatorImpl;
private final Class<? extends Verifier> validatorImpl;
CoreValidators(Class<? extends Validator> validatorClass) {
CoreValidators(Class<? extends Verifier> validatorClass) {
this.validatorImpl = validatorClass;
}
}

View File

@ -17,8 +17,7 @@ package io.nosqlbench.adapters.api.activityimpl;
* under the License.
*/
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.Verifier;
import io.nosqlbench.adapters.api.activityimpl.uniform.opwrappers.DiffType;
import io.nosqlbench.adapters.api.templating.ParsedOp;
import io.nosqlbench.nb.api.components.core.NBComponent;
@ -32,8 +31,19 @@ import java.util.*;
import java.util.function.LongFunction;
import java.util.stream.Collectors;
// TODO: Make op(verifyref) use tags, and require 1
public class FieldVerifier implements Validator {
/// The field verifier is a type of result checker which can assert
/// that fields in an op result match the values expected, or in other
/// words, that the data is _correct_.
///
/// The field verifier works with another optional capability, called
/// _field capture_ which is able to extract the results of an operation
/// into a specific set of named fields, asserting their value types, and
/// renaming the results if needed.
///
/// Together field capture and field verify behaviors allow an adapter-agnostic
/// way of asserting correctness of results. Further details on how this
/// works will be provided in a separate doc, with examples.
public class FieldVerifier implements Verifier {
private final LongFunction<Map<String, Object>> expectedValuesF;
private final DiffType diffType;
@ -108,13 +118,24 @@ public class FieldVerifier implements Validator {
this.fieldNames = fields.toArray(new String[fields.size()]);
this.bindingNames = bindings.toArray(new String[bindings.size()]);
this.expectedValuesF = pop.newOrderedMapBinder(bindingNames);
}
/// This is not stable yet, and may change again soon
///
/// There are two ways a field verifier is expected to be configured:
/// 1. By reference to another op template which is presumed to have written
/// the data to be verified.
/// 2. Directly, by telling the field verifier the names, value bindings, and level
/// of verification.
private void parseFieldSpec(
String fieldSpec, OpLookup lookup, List<String> fields,
List<String> bindings, CapturePoints captures, ParsedOp pop
) {
// This is an indirect way of configuring a verifier. A user specifies
// a tag filter which is meant to locate another op template within the
// current workload template (it can be an active or inactive op template)
// and that referenced template is used to derive the field names, bindings,
// etc to verify against results of this op templates result values.
if (fieldSpec.startsWith("op(") && fieldSpec.endsWith(")")) {
String toLookup = fieldSpec.substring("op(".length(), fieldSpec.length() - 1);
Optional<ParsedOp> referenced = lookup.lookup(toLookup);
@ -127,7 +148,11 @@ public class FieldVerifier implements Validator {
throw new OpConfigError(
"no op found for verify setting '" + fieldSpec + "' " + "for op " + "template" + " '" + pop.getName() + "'");
}
} else {
}
// This is the direct way of configuring a verifier.
// See verify.md for details on the supported format. As this is experimental, this doc
// should be updated when this code is stable.
else {
String[] vfields = fieldSpec.split("\\s*,\\s*");
for (String vfield : vfields) {
// if (vfield.equals("*")) {
@ -160,7 +185,7 @@ public class FieldVerifier implements Validator {
/// operator for the respective type.
/// @return a count of differences between the row and the reference values
@Override
public void validate(long cycle, Object data) {
public void verify(long cycle, Object data) {
if (data instanceof Map<?, ?> r) {
Map<String, ?> result = (Map<String, ?>) r;
Map<String, Object> referenceMap = this.expectedValuesF.apply(cycle);

View File

@ -23,10 +23,9 @@ import io.nosqlbench.adapters.api.templating.ParsedOp;
import io.nosqlbench.nb.api.components.core.NBComponent;
import java.util.List;
import java.util.Optional;
/// A [DriverAdapter] may implement this interface to provide adapter-specific
/// validators.
public interface ValidatorSource {
List<Validator> getValidator(NBComponent parent, ParsedOp pop, OpLookup lookup);
List<Verifier> getValidator(NBComponent parent, ParsedOp pop, OpLookup lookup);
}

View File

@ -17,9 +17,8 @@ package io.nosqlbench.adapters.api.activityimpl.uniform;
* under the License.
*/
import io.nosqlbench.nb.api.components.core.NBNamedElement;
public interface Validator<RESULT> extends NBNamedElement {
public void validate(long cycle, RESULT result);
public interface Verifier<RESULT> extends NBNamedElement {
public void verify(long cycle, RESULT result);
}

View File

@ -16,15 +16,15 @@
package io.nosqlbench.adapters.api.activityimpl.uniform.opwrappers;
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.Verifier;
import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.CycleOp;
public class AssertingOp<T> implements CycleOp<T> {
private final CycleOp<T> op;
private final Validator<T> validator;
private final Verifier<T> validator;
public AssertingOp(CycleOp<T> op, Validator<T> validator) {
public AssertingOp(CycleOp<T> op, Verifier<T> validator) {
this.op = op;
this.validator = validator;
}
@ -32,7 +32,7 @@ public class AssertingOp<T> implements CycleOp<T> {
@Override
public T apply(long value) {
T result = op.apply(value);
validator.validate(value, result);
validator.verify(value, result);
return result;
}
}

View File

@ -20,20 +20,20 @@ import io.nosqlbench.adapters.api.activityimpl.BaseOpDispenser;
import io.nosqlbench.adapters.api.activityimpl.OpDispenser;
import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.adapters.api.activityimpl.uniform.Space;
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.Verifier;
import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.CycleOp;
import io.nosqlbench.adapters.api.templating.ParsedOp;
public class AssertingOpDispenser<S extends Space, RESULT> extends BaseOpDispenser<CycleOp<RESULT>, S> {
private final OpDispenser<CycleOp<RESULT>> realDispenser;
private final Validator<RESULT> validator;
private final Verifier<RESULT> validator;
public AssertingOpDispenser(
DriverAdapter<CycleOp<RESULT>, S> adapter,
ParsedOp pop,
OpDispenser<CycleOp<RESULT>> realDispenser,
Validator<RESULT> validator
Verifier<RESULT> validator
) {
super(adapter, pop, adapter.getSpaceFunc(pop));
this.realDispenser = realDispenser;

View File

@ -16,7 +16,6 @@
package io.nosqlbench.adapters.api.activityimpl.uniform.opwrappers;
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.CycleOp;
import java.util.Map;

View File

@ -266,7 +266,7 @@ public class NBConfiguration {
/// [NBReconfigurable#applyConfig(NBConfiguration)] method
///
/// This eventing will occur whether or not the value was actually changed. Spurious
/// evenging of duplicate values should be considered an design bug.
/// eventing of duplicate values should be considered a design bug.
///
/// Any holders of an updated configurations must maintain their own copies if necessary for
/// deltas.

View File

@ -22,18 +22,16 @@ import io.nosqlbench.adapters.api.activityimpl.OpDispenser;
import io.nosqlbench.adapters.api.activityimpl.OpLookup;
import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.adapters.api.activityimpl.uniform.Space;
import io.nosqlbench.adapters.api.activityimpl.uniform.Validator;
import io.nosqlbench.adapters.api.activityimpl.uniform.Verifier;
import io.nosqlbench.adapters.api.activityimpl.uniform.ValidatorSource;
import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.CycleOp;
import io.nosqlbench.adapters.api.activityimpl.uniform.opwrappers.AssertingOpDispenser;
import io.nosqlbench.adapters.api.templating.ParsedOp;
import io.nosqlbench.nb.api.errors.OpConfigError;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/// This is a functional wrapper layer which will upgrade a basic [CycleOp] to
/// one that has a validator provided by it's [DriverAdapter], so long as the
@ -61,8 +59,8 @@ public class OpAssertions {
}
for (ValidatorSource source : sources) {
List<Validator> validator = source.getValidator(adapter, pop, lookup);
for (Validator v : validator) {
List<Verifier> validator = source.getValidator(adapter, pop, lookup);
for (Verifier v : validator) {
dispenser = new AssertingOpDispenser(adapter, pop, dispenser, v);
logger.trace("added post-run validator for op '" + pop.getName() + "'");
}