diff options
79 files changed, 1455 insertions, 1576 deletions
diff --git a/client/js/app/yarn.lock b/client/js/app/yarn.lock index d6f0e6d1a1e..933d0ba8010 100644 --- a/client/js/app/yarn.lock +++ b/client/js/app/yarn.lock @@ -1315,10 +1315,10 @@ dependencies: "@babel/runtime" "^7.13.10" -"@remix-run/router@1.15.2": - version "1.15.2" - resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.2.tgz#35726510d332ba5349c6398d13259d5da184553d" - integrity sha512-+Rnav+CaoTE5QJc4Jcwh5toUpnVLKYbpU6Ys0zqbakqbaLQHeglLVHPfxOiQqdNmUy5C2lXz5dwC6tQNX2JW2Q== +"@remix-run/router@1.15.3": + version "1.15.3" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.3.tgz#d2509048d69dbb72d5389a14945339f1430b2d3c" + integrity sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w== "@rollup/rollup-android-arm-eabi@4.12.0": version "4.12.0" @@ -4645,19 +4645,19 @@ react-refresh@^0.14.0: integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== react-router-dom@^6: - version "6.22.2" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.22.2.tgz#8233968a8a576f3006e5549c80f3527d2598fc9c" - integrity sha512-WgqxD2qySEIBPZ3w0sHH+PUAiamDeszls9tzqMPBDA1YYVucTBXLU7+gtRfcSnhe92A3glPnvSxK2dhNoAVOIQ== + version "6.22.3" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.22.3.tgz#9781415667fd1361a475146c5826d9f16752a691" + integrity sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw== dependencies: - "@remix-run/router" "1.15.2" - react-router "6.22.2" + "@remix-run/router" "1.15.3" + react-router "6.22.3" -react-router@6.22.2: - version "6.22.2" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.22.2.tgz#27e77e4c635a5697693b922d131d773451c98a5b" - integrity sha512-YD3Dzprzpcq+tBMHBS822tCjnWD3iIZbTeSXMY9LPSG541EfoBGyZ3bS25KEnaZjLcmQpw2AVLkFyfgXY8uvcw== +react-router@6.22.3: + version "6.22.3" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.22.3.tgz#9d9142f35e08be08c736a2082db5f0c9540a885e" + integrity sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ== dependencies: - "@remix-run/router" "1.15.2" + "@remix-run/router" "1.15.3" react-textarea-autosize@8.3.4: version "8.3.4" diff --git a/config-model/src/main/java/com/yahoo/schema/derived/AttributeFields.java b/config-model/src/main/java/com/yahoo/schema/derived/AttributeFields.java index e747235dc3c..92f7e87209a 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/AttributeFields.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/AttributeFields.java @@ -12,6 +12,7 @@ import com.yahoo.schema.document.Sorting; import com.yahoo.vespa.config.search.AttributesConfig; import com.yahoo.vespa.indexinglanguage.expressions.ToPositionExpression; +import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -27,7 +28,7 @@ import static com.yahoo.schema.document.ComplexAttributeFieldUtils.isSupportedCo * * @author bratseth */ -public class AttributeFields extends Derived implements AttributesConfig.Producer { +public class AttributeFields extends Derived { public enum FieldSet {ALL, FAST_ACCESS} @@ -178,12 +179,16 @@ public class AttributeFields extends Derived implements AttributesConfig.Produce return "attributes"; } - @Override public void getConfig(AttributesConfig.Builder builder) { - //TODO This is just to get some exporting tests to work, Should be undone and removed getConfig(builder, FieldSet.ALL, 77777); } + public void export(String toDirectory) throws IOException { + var builder = new AttributesConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + private boolean isAttributeInFieldSet(Attribute attribute, FieldSet fs) { return (fs == FieldSet.ALL) || ((fs == FieldSet.FAST_ACCESS) && attribute.isFastAccess()); } diff --git a/config-model/src/main/java/com/yahoo/schema/derived/Derived.java b/config-model/src/main/java/com/yahoo/schema/derived/Derived.java index 3ed9807b8f1..f4311912584 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/Derived.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/Derived.java @@ -2,7 +2,6 @@ package com.yahoo.schema.derived; import com.yahoo.config.ConfigInstance; -import com.yahoo.config.ConfigInstance.Builder; import com.yahoo.document.Field; import com.yahoo.io.IOUtils; import com.yahoo.schema.Index; @@ -14,7 +13,6 @@ import com.yahoo.text.StringUtilities; import java.io.IOException; import java.io.Writer; -import java.lang.reflect.Method; import java.util.List; /** @@ -22,7 +20,7 @@ import java.util.List; * * @author bratseth */ -public abstract class Derived implements Exportable { +public abstract class Derived { private String name; @@ -88,23 +86,13 @@ public abstract class Derived implements Exportable { return labels ? getName() : String.valueOf(number); } - /** - * Exports this derived configuration to its .cfg file - * in toDirectory - * - * @param toDirectory the directory to export to, or null - * - */ - public void export(String toDirectory) throws IOException { + protected void export(String toDirectory, ConfigInstance cfg) throws IOException { Writer writer = null; try { String fileName = getDerivedName() + ".cfg"; - if (toDirectory != null) - writer = IOUtils.createWriter(toDirectory + "/" + fileName,false); - try { - exportBuilderConfig(writer); - } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException e) { - throw new RuntimeException(e); + if (toDirectory != null) { + writer = IOUtils.createWriter(toDirectory + "/" + fileName, false); + exportConfig(writer, cfg); } } finally { @@ -112,30 +100,10 @@ public abstract class Derived implements Exportable { } } - /** - * Checks what this is a producer of, instantiate that and export to writer - */ - // TODO move to ReflectionUtil, and move that to unexported pkg - private void exportBuilderConfig(Writer writer) throws ReflectiveOperationException, SecurityException, IllegalArgumentException, IOException { - for (Class<?> intf : getClass().getInterfaces()) { - if (ConfigInstance.Producer.class.isAssignableFrom(intf)) { - Class<?> configClass = intf.getEnclosingClass(); - String builderClassName = configClass.getCanonicalName()+"$Builder"; - Class<?> builderClass = Class.forName(builderClassName); - ConfigInstance.Builder builder = (Builder) builderClass.getDeclaredConstructor().newInstance(); - Method getConfig = getClass().getMethod("getConfig", builderClass); - getConfig.invoke(this, builder); - ConfigInstance inst = (ConfigInstance) configClass.getConstructor(builderClass).newInstance(builder); - List<String> payloadL = ConfigInstance.serialize(inst); - String payload = StringUtilities.implodeMultiline(payloadL); - writer.write(payload); - } - } - } - - @Override - public String getFileName() { - return getDerivedName() + ".cfg"; + private void exportConfig(Writer writer, ConfigInstance cfg) throws IOException { + List<String> payloadL = ConfigInstance.serialize(cfg); + String payload = StringUtilities.implodeMultiline(payloadL); + writer.write(payload); } } diff --git a/config-model/src/main/java/com/yahoo/schema/derived/DerivedConfiguration.java b/config-model/src/main/java/com/yahoo/schema/derived/DerivedConfiguration.java index bc1c097ea4b..e303e878550 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/DerivedConfiguration.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/DerivedConfiguration.java @@ -12,6 +12,7 @@ import com.yahoo.schema.RankProfileRegistry; import com.yahoo.schema.Schema; import com.yahoo.schema.derived.validation.Validation; import com.yahoo.vespa.config.search.AttributesConfig; +import com.yahoo.vespa.config.search.core.OnnxModelsConfig; import com.yahoo.vespa.config.search.core.RankingConstantsConfig; import com.yahoo.vespa.model.container.search.QueryProfiles; @@ -126,10 +127,15 @@ public class DerivedConfiguration { } public void exportConstants(String toDirectory) throws IOException { - RankingConstantsConfig.Builder b = new RankingConstantsConfig.Builder(); - rankProfileList.getConfig(b); + var b = new RankingConstantsConfig.Builder() + .constant(rankProfileList.getConstantsConfig()); exportCfg(b.build(), toDirectory + "/" + "ranking-constants.cfg"); } + public void exportOnnxModels(String toDirectory) throws IOException { + var b = new OnnxModelsConfig.Builder() + .model(rankProfileList.getOnnxConfig()); + exportCfg(b.build(), toDirectory + "/" + "onnx-models.cfg"); + } private static void exportCfg(ConfigInstance instance, String fileName) throws IOException { Writer writer = null; diff --git a/config-model/src/main/java/com/yahoo/schema/derived/Exportable.java b/config-model/src/main/java/com/yahoo/schema/derived/Exportable.java deleted file mode 100644 index 983be8bf13a..00000000000 --- a/config-model/src/main/java/com/yahoo/schema/derived/Exportable.java +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.schema.derived; - -/** - * Classes exportable to configurations - * - * @author bratseth - */ -public interface Exportable { - - /** - * Exports the configuration of this object - * - * - * @param toDirectory the directory to export to, does not write to disk if null - * @throws java.io.IOException if exporting fails, some files may still be created - */ - public void export(String toDirectory) throws java.io.IOException; - - /** - * The (short) name of the exported file - * @return a String with the (short) name of the exported file - */ - public String getFileName(); - -} diff --git a/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedConstants.java b/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedConstants.java index 91ab1ad9172..275fbe82ad4 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedConstants.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedConstants.java @@ -10,6 +10,7 @@ import com.yahoo.vespa.config.search.core.RankingConstantsConfig; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; /** @@ -25,7 +26,7 @@ public class FileDistributedConstants { public FileDistributedConstants(FileRegistry fileRegistry, Collection<RankProfile.Constant> constants) { Map<String, DistributableConstant> distributableConstants = new LinkedHashMap<>(); for (var constant : constants) { - if ( ! constant.valuePath().isPresent()) continue; + if (constant.valuePath().isEmpty()) continue; var distributableConstant = new DistributableConstant(constant.name().simpleArgument().get(), constant.type(), @@ -41,23 +42,21 @@ public class FileDistributedConstants { /** Returns a read-only map of the constants in this indexed by name. */ public Map<String, DistributableConstant> asMap() { return constants; } - public void getConfig(RankingConstantsConfig.Builder builder) { - for (var constant : constants.values()) { - builder.constant(new RankingConstantsConfig.Constant.Builder() - .name(constant.getName()) - .fileref(constant.getFileReference()) - .type(constant.getType())); - } + private static RankingConstantsConfig.Constant.Builder toConfig(DistributableConstant constant) { + return new RankingConstantsConfig.Constant.Builder() + .name(constant.getName()) + .fileref(constant.getFileReference()) + .type(constant.getType()); + } + + public List<RankingConstantsConfig.Constant.Builder> getConfig() { + return constants.values().stream().map(FileDistributedConstants::toConfig).toList(); } public static class DistributableConstant extends DistributableResource { private final TensorType tensorType; - public DistributableConstant(String name, TensorType type, String fileName) { - this(name, type, fileName, PathType.FILE); - } - public DistributableConstant(String name, TensorType type, String fileName, PathType pathType) { super(name, fileName, pathType); this.tensorType = type; diff --git a/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedOnnxModels.java b/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedOnnxModels.java index 1cc33cc4180..6e50e3c094c 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedOnnxModels.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/FileDistributedOnnxModels.java @@ -5,9 +5,11 @@ import com.yahoo.config.application.api.FileRegistry; import com.yahoo.schema.OnnxModel; import com.yahoo.vespa.config.search.core.OnnxModelsConfig; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.logging.Logger; @@ -16,13 +18,10 @@ import java.util.logging.Logger; * * @author bratseth */ -public class FileDistributedOnnxModels extends Derived implements OnnxModelsConfig.Producer { +public class FileDistributedOnnxModels { private static final Logger log = Logger.getLogger(FileDistributedOnnxModels.class.getName()); - @Override - public String getDerivedName() { return "onnx-models"; } - private final Map<String, OnnxModel> models; public FileDistributedOnnxModels(FileRegistry fileRegistry, Collection<OnnxModel> models) { @@ -47,30 +46,36 @@ public class FileDistributedOnnxModels extends Derived implements OnnxModelsConf public Map<String, OnnxModel> asMap() { return models; } - public void getConfig(OnnxModelsConfig.Builder builder) { + private static OnnxModelsConfig.Model.Builder toConfig(OnnxModel model) { + OnnxModelsConfig.Model.Builder builder = new OnnxModelsConfig.Model.Builder(); + builder.dry_run_on_setup(true); + builder.name(model.getName()); + builder.fileref(model.getFileReference()); + model.getInputMap().forEach((name, source) -> builder.input(new OnnxModelsConfig.Model.Input.Builder().name(name).source(source))); + model.getOutputMap().forEach((name, as) -> builder.output(new OnnxModelsConfig.Model.Output.Builder().name(name).as(as))); + if (model.getStatelessExecutionMode().isPresent()) + builder.stateless_execution_mode(model.getStatelessExecutionMode().get()); + if (model.getStatelessInterOpThreads().isPresent()) + builder.stateless_interop_threads(model.getStatelessInterOpThreads().get()); + if (model.getStatelessIntraOpThreads().isPresent()) + builder.stateless_intraop_threads(model.getStatelessIntraOpThreads().get()); + if (model.getGpuDevice().isPresent()) { + builder.gpu_device(model.getGpuDevice().get().deviceNumber()); + builder.gpu_device_required(model.getGpuDevice().get().required()); + } + return builder; + } + + public List<OnnxModelsConfig.Model.Builder> getConfig() { + List<OnnxModelsConfig.Model.Builder> cfgList = new ArrayList<>(); for (OnnxModel model : models.values()) { if ("".equals(model.getFileReference())) log.warning("Illegal file reference " + model); // Let tests pass ... we should find a better way else { - OnnxModelsConfig.Model.Builder modelBuilder = new OnnxModelsConfig.Model.Builder(); - modelBuilder.dry_run_on_setup(true); - modelBuilder.name(model.getName()); - modelBuilder.fileref(model.getFileReference()); - model.getInputMap().forEach((name, source) -> modelBuilder.input(new OnnxModelsConfig.Model.Input.Builder().name(name).source(source))); - model.getOutputMap().forEach((name, as) -> modelBuilder.output(new OnnxModelsConfig.Model.Output.Builder().name(name).as(as))); - if (model.getStatelessExecutionMode().isPresent()) - modelBuilder.stateless_execution_mode(model.getStatelessExecutionMode().get()); - if (model.getStatelessInterOpThreads().isPresent()) - modelBuilder.stateless_interop_threads(model.getStatelessInterOpThreads().get()); - if (model.getStatelessIntraOpThreads().isPresent()) - modelBuilder.stateless_intraop_threads(model.getStatelessIntraOpThreads().get()); - if (model.getGpuDevice().isPresent()) { - modelBuilder.gpu_device(model.getGpuDevice().get().deviceNumber()); - modelBuilder.gpu_device_required(model.getGpuDevice().get().required()); - } - builder.model(modelBuilder); + cfgList.add(toConfig(model)); } } + return cfgList; } } diff --git a/config-model/src/main/java/com/yahoo/schema/derived/ImportedFields.java b/config-model/src/main/java/com/yahoo/schema/derived/ImportedFields.java index a781adcefb7..e5e28ccea27 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/ImportedFields.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/ImportedFields.java @@ -9,6 +9,7 @@ import com.yahoo.schema.document.ImportedComplexField; import com.yahoo.schema.document.ImportedField; import com.yahoo.vespa.config.search.ImportedFieldsConfig; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -22,7 +23,7 @@ import static com.yahoo.schema.document.ComplexAttributeFieldUtils.isMapOfSimple * * @author geirst */ -public class ImportedFields extends Derived implements ImportedFieldsConfig.Producer { +public class ImportedFields extends Derived { private Optional<com.yahoo.schema.document.ImportedFields> importedFields = Optional.empty(); @@ -40,7 +41,6 @@ public class ImportedFields extends Derived implements ImportedFieldsConfig.Prod return "imported-fields"; } - @Override public void getConfig(ImportedFieldsConfig.Builder builder) { // Replace if (importedFields.isPresent()) { @@ -50,6 +50,12 @@ public class ImportedFields extends Derived implements ImportedFieldsConfig.Prod } } + public void export(String toDirectory) throws IOException { + var builder = new ImportedFieldsConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + private static boolean isNestedFieldName(String fieldName) { return fieldName.indexOf('.') != -1; } diff --git a/config-model/src/main/java/com/yahoo/schema/derived/IndexInfo.java b/config-model/src/main/java/com/yahoo/schema/derived/IndexInfo.java index b0cf4a0013c..c1b698df55f 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/IndexInfo.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/IndexInfo.java @@ -24,6 +24,7 @@ import com.yahoo.schema.processing.NGramMatch; import com.yahoo.vespa.documentmodel.SummaryField; import com.yahoo.search.config.IndexInfoConfig; +import java.io.IOException; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -34,7 +35,7 @@ import java.util.Set; * * @author bratseth */ -public class IndexInfo extends Derived implements IndexInfoConfig.Producer { +public class IndexInfo extends Derived { private static final String CMD_ATTRIBUTE = "attribute"; private static final String CMD_DEFAULT_POSITION = "default-position"; @@ -314,7 +315,6 @@ public class IndexInfo extends Derived implements IndexInfoConfig.Producer { return true; } - @Override public void getConfig(IndexInfoConfig.Builder builder) { // Append IndexInfoConfig.Indexinfo.Builder iiB = new IndexInfoConfig.Indexinfo.Builder(); @@ -335,6 +335,12 @@ public class IndexInfo extends Derived implements IndexInfoConfig.Producer { builder.indexinfo(iiB); } + public void export(String toDirectory) throws IOException { + var builder = new IndexInfoConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + // TODO: Move this to the FieldSetSettings processor (and rename it) as that already has to look at this. private void addFieldSetCommands(IndexInfoConfig.Indexinfo.Builder iiB, FieldSet fieldSet) { for (String qc : fieldSet.queryCommands()) { diff --git a/config-model/src/main/java/com/yahoo/schema/derived/IndexSchema.java b/config-model/src/main/java/com/yahoo/schema/derived/IndexSchema.java index 1c22e80e579..34ed9f2f60c 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/IndexSchema.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/IndexSchema.java @@ -12,6 +12,7 @@ import com.yahoo.schema.document.FieldSet; import com.yahoo.schema.document.ImmutableSDField; import com.yahoo.vespa.config.search.IndexschemaConfig; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -24,7 +25,7 @@ import java.util.Map; * * @author geirst */ -public class IndexSchema extends Derived implements IndexschemaConfig.Producer { +public class IndexSchema extends Derived { private final List<IndexField> fields = new ArrayList<>(); private final Map<String, FieldCollection> collections = new LinkedHashMap<>(); @@ -131,13 +132,18 @@ public class IndexSchema extends Derived implements IndexschemaConfig.Producer { return fsB; } - @Override public void getConfig(IndexschemaConfig.Builder icB) { // Replace icB.indexfield(fields.stream().map(IndexSchema::createIndexFieldConfig).toList()); icB.fieldset(fieldSets.values().stream().map(IndexSchema::createFieldSetConfig).toList()); } + public void export(String toDirectory) throws IOException { + var builder = new IndexschemaConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + static List<Field> flattenField(Field field) { DataType fieldType = field.getDataType(); if (fieldType.getPrimitiveType() != null){ diff --git a/config-model/src/main/java/com/yahoo/schema/derived/IndexingScript.java b/config-model/src/main/java/com/yahoo/schema/derived/IndexingScript.java index 7245e3f266d..60d27c617f1 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/IndexingScript.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/IndexingScript.java @@ -11,7 +11,6 @@ import com.yahoo.vespa.indexinglanguage.ExpressionVisitor; import com.yahoo.vespa.indexinglanguage.expressions.AttributeExpression; import com.yahoo.vespa.indexinglanguage.expressions.ClearStateExpression; import com.yahoo.vespa.indexinglanguage.expressions.Expression; -import com.yahoo.vespa.indexinglanguage.expressions.ForEachExpression; import com.yahoo.vespa.indexinglanguage.expressions.GuardExpression; import com.yahoo.vespa.indexinglanguage.expressions.InputExpression; import com.yahoo.vespa.indexinglanguage.expressions.OutputExpression; @@ -22,6 +21,7 @@ import com.yahoo.vespa.indexinglanguage.expressions.StatementExpression; import com.yahoo.vespa.indexinglanguage.expressions.TokenizeExpression; import com.yahoo.vespa.indexinglanguage.expressions.ZCurveExpression; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -35,7 +35,7 @@ import java.util.Set; * * @author bratseth */ -public final class IndexingScript extends Derived implements IlscriptsConfig.Producer { +public final class IndexingScript extends Derived { private final List<String> docFields = new ArrayList<>(); private final List<Expression> expressions = new ArrayList<>(); @@ -93,7 +93,6 @@ public final class IndexingScript extends Derived implements IlscriptsConfig.Pro return "ilscripts"; } - @Override public void getConfig(IlscriptsConfig.Builder configBuilder) { // Append IlscriptsConfig.Ilscript.Builder ilscriptBuilder = new IlscriptsConfig.Ilscript.Builder(); @@ -103,6 +102,12 @@ public final class IndexingScript extends Derived implements IlscriptsConfig.Pro configBuilder.ilscript(ilscriptBuilder); } + public void export(String toDirectory) throws IOException { + var builder = new IlscriptsConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + private static class DropTokenize extends ExpressionConverter { @Override protected boolean shouldConvert(Expression exp) { diff --git a/config-model/src/main/java/com/yahoo/schema/derived/Juniperrc.java b/config-model/src/main/java/com/yahoo/schema/derived/Juniperrc.java index a39fa642f34..58e77cedaf1 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/Juniperrc.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/Juniperrc.java @@ -6,6 +6,7 @@ import com.yahoo.vespa.documentmodel.SummaryField; import com.yahoo.vespa.documentmodel.SummaryTransform; import com.yahoo.vespa.config.search.summary.JuniperrcConfig; +import java.io.IOException; import java.util.ArrayList; import java.util.Set; import java.util.stream.Collectors; @@ -15,7 +16,7 @@ import java.util.stream.Collectors; * * @author Simon Thoresen Hult */ -public class Juniperrc extends Derived implements JuniperrcConfig.Producer { +public class Juniperrc extends Derived { private static final int Mb = 1024 * 1024; @@ -43,8 +44,13 @@ public class Juniperrc extends Derived implements JuniperrcConfig.Producer { } } - @Override - protected String getDerivedName() { return "juniperrc"; } + public void export(String toDirectory) throws IOException { + var builder = new JuniperrcConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + + @Override protected String getDerivedName() { return "juniperrc"; } private static JuniperrcConfig.Override.Builder createOverride(String name) { return new JuniperrcConfig.Override.Builder() @@ -55,7 +61,6 @@ public class Juniperrc extends Derived implements JuniperrcConfig.Producer { .surround_max(64*Mb); } - @Override public void getConfig(JuniperrcConfig.Builder builder) { // Replace if (!boldingFields.isEmpty()) { diff --git a/config-model/src/main/java/com/yahoo/schema/derived/RankProfileList.java b/config-model/src/main/java/com/yahoo/schema/derived/RankProfileList.java index 0a419768aaf..b08629d68a3 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/RankProfileList.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/RankProfileList.java @@ -4,6 +4,7 @@ package com.yahoo.schema.derived; import ai.vespa.rankingexpression.importer.configmodelview.ImportedMlModels; import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.model.deploy.DeployState; +import com.yahoo.schema.RankingExpressionBody; import com.yahoo.search.query.profile.QueryProfileRegistry; import com.yahoo.schema.LargeRankingExpressions; import com.yahoo.schema.OnnxModel; @@ -16,6 +17,7 @@ import com.yahoo.vespa.config.search.core.OnnxModelsConfig; import com.yahoo.vespa.config.search.core.RankingConstantsConfig; import com.yahoo.vespa.config.search.core.RankingExpressionsConfig; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -32,7 +34,7 @@ import java.util.concurrent.Future; * * @author bratseth */ -public class RankProfileList extends Derived implements RankProfilesConfig.Producer { +public class RankProfileList extends Derived { private final Map<String, RawRankProfile> rankProfiles; private final FileDistributedConstants constants; @@ -190,32 +192,32 @@ public class RankProfileList extends Derived implements RankProfilesConfig.Produ public FileDistributedConstants constants() { return constants; } public FileDistributedOnnxModels getOnnxModels() { return onnxModels; } - @Override - public String getDerivedName() { return "rank-profiles"; } + @Override public String getDerivedName() { return "rank-profiles"; } - @Override - public void export(String toDirectory) throws java.io.IOException { - super.export(toDirectory); - onnxModels.export(toDirectory); + public void export(String toDirectory) throws IOException { + export(toDirectory, new RankProfilesConfig.Builder().rankprofile(getRankProfilesConfig()).build()); } - @Override - public void getConfig(RankProfilesConfig.Builder builder) { - for (RawRankProfile rank : rankProfiles.values() ) { - rank.getConfig(builder); - } + public List<RankProfilesConfig.Rankprofile.Builder> getRankProfilesConfig() { + return rankProfiles.values().stream().map(RawRankProfile::getConfig).toList(); + } + + private static RankingExpressionsConfig.Expression.Builder toConfig(RankingExpressionBody expr) { + return new RankingExpressionsConfig.Expression.Builder() + .name(expr.getName()) + .fileref(expr.getFileReference()); } - public void getConfig(RankingExpressionsConfig.Builder builder) { - largeRankingExpressions.expressions().forEach((expr) -> builder.expression.add(new RankingExpressionsConfig.Expression.Builder().name(expr.getName()).fileref(expr.getFileReference()))); + public List<RankingExpressionsConfig.Expression.Builder> getExpressionsConfig() { + return largeRankingExpressions.expressions().stream().map(RankProfileList::toConfig).toList(); } - public void getConfig(RankingConstantsConfig.Builder builder) { - constants.getConfig(builder); + public List<RankingConstantsConfig.Constant.Builder> getConstantsConfig() { + return constants.getConfig(); } - public void getConfig(OnnxModelsConfig.Builder builder) { - onnxModels.getConfig(builder); + public List<OnnxModelsConfig.Model.Builder> getOnnxConfig() { + return onnxModels.getConfig(); } } diff --git a/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java b/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java index db76d6397fc..b057624f055 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java @@ -43,7 +43,7 @@ import java.util.Set; * * @author bratseth */ -public class RawRankProfile implements RankProfilesConfig.Producer { +public class RawRankProfile { /** A reusable compressor with default settings */ private static final Compressor compressor = new Compressor(); @@ -130,12 +130,11 @@ public class RawRankProfile implements RankProfilesConfig.Producer { */ public List<Pair<String, String>> configProperties() { return decompress(compressedProperties); } - @Override - public void getConfig(RankProfilesConfig.Builder builder) { + public RankProfilesConfig.Rankprofile.Builder getConfig() { RankProfilesConfig.Rankprofile.Builder b = new RankProfilesConfig.Rankprofile.Builder().name(getName()); getRankProperties(b); buildNormalizers(b); - builder.rankprofile(b); + return b; } @Override diff --git a/config-model/src/main/java/com/yahoo/schema/derived/SchemaInfo.java b/config-model/src/main/java/com/yahoo/schema/derived/SchemaInfo.java index fb6d7fb70ec..19a045ac444 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/SchemaInfo.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/SchemaInfo.java @@ -21,6 +21,7 @@ import com.yahoo.schema.RankProfileRegistry; import com.yahoo.schema.Schema; import com.yahoo.searchlib.rankingexpression.Reference; +import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -32,7 +33,7 @@ import java.util.Map; * * @author bratseth */ -public final class SchemaInfo extends Derived implements SchemaInfoConfig.Producer { +public final class SchemaInfo extends Derived { private final Schema schema; @@ -63,7 +64,6 @@ public final class SchemaInfo extends Derived implements SchemaInfoConfig.Produc return rankProfileInfos; } - @Override public void getConfig(SchemaInfoConfig.Builder builder) { // Append var schemaBuilder = new SchemaInfoConfig.Schema.Builder(); @@ -75,6 +75,12 @@ public final class SchemaInfo extends Derived implements SchemaInfoConfig.Produc builder.schema(schemaBuilder); } + public void export(String toDirectory) throws IOException { + var builder = new SchemaInfoConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + private void addFieldsConfig(SchemaInfoConfig.Schema.Builder schemaBuilder) { for (var field : schema.allFieldsList()) { addFieldConfig(field, schemaBuilder); diff --git a/config-model/src/main/java/com/yahoo/schema/derived/Summaries.java b/config-model/src/main/java/com/yahoo/schema/derived/Summaries.java index 51c648aa1be..1f0c6f7e761 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/Summaries.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/Summaries.java @@ -7,6 +7,7 @@ import com.yahoo.schema.Schema; import com.yahoo.vespa.documentmodel.DocumentSummary; import com.yahoo.vespa.config.search.SummaryConfig; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -15,7 +16,7 @@ import java.util.List; * * @author bratseth */ -public class Summaries extends Derived implements SummaryConfig.Producer { +public class Summaries extends Derived { private final boolean useV8GeoPositions; private final List<SummaryClass> summaries; @@ -36,15 +37,18 @@ public class Summaries extends Derived implements SummaryConfig.Producer { public List<SummaryClass> asList() { return summaries; } - @Override - protected String getDerivedName() { return "summary"; } + @Override protected String getDerivedName() { return "summary"; } - @Override public void getConfig(SummaryConfig.Builder builder) { // Replace builder.defaultsummaryid(summaries.isEmpty() ? -1 : summaries.get(0).hashCode()); builder.usev8geopositions(useV8GeoPositions); builder.classes(summaries.stream().map(SummaryClass::getSummaryClassConfig).toList()); - } + } + public void export(String toDirectory) throws IOException { + var builder = new SummaryConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } } diff --git a/config-model/src/main/java/com/yahoo/schema/derived/SummaryClass.java b/config-model/src/main/java/com/yahoo/schema/derived/SummaryClass.java index 799324d26e9..398897c6b78 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/SummaryClass.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/SummaryClass.java @@ -11,6 +11,7 @@ import com.yahoo.vespa.documentmodel.DocumentSummary; import com.yahoo.vespa.documentmodel.SummaryField; import com.yahoo.vespa.documentmodel.SummaryTransform; +import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.logging.Level; @@ -119,11 +120,9 @@ public class SummaryClass extends Derived { return classBuilder; } - @Override - public int hashCode() { return id; } + @Override public int hashCode() { return id; } - @Override - protected String getDerivedName() { return "summary"; } + @Override protected String getDerivedName() { return "summary"; } @Override public String toString() { diff --git a/config-model/src/main/java/com/yahoo/schema/derived/VsmFields.java b/config-model/src/main/java/com/yahoo/schema/derived/VsmFields.java index b2b2e9d3a14..6992ac70a1a 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/VsmFields.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/VsmFields.java @@ -25,13 +25,14 @@ import com.yahoo.schema.document.SDField; import com.yahoo.schema.processing.TensorFieldProcessor; import com.yahoo.vespa.config.search.vsm.VsmfieldsConfig; +import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; /** * Vertical streaming matcher field specification */ -public class VsmFields extends Derived implements VsmfieldsConfig.Producer { +public class VsmFields extends Derived { private final Map<String, StreamingField> fields=new LinkedHashMap<>(); private final Map<String, StreamingDocumentType> doctypes=new LinkedHashMap<>(); @@ -106,13 +107,18 @@ public class VsmFields extends Derived implements VsmfieldsConfig.Producer { return "vsmfields"; } - @Override public void getConfig(VsmfieldsConfig.Builder vsB) { // Replace vsB.fieldspec(fields.values().stream().map(StreamingField::getFieldSpecConfig).toList()); vsB.documenttype(doctypes.values().stream().map(StreamingDocumentType::getDocTypeConfig).toList()); } + public void export(String toDirectory) throws IOException { + var builder = new VsmfieldsConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } + private static boolean isAttributeField(ImmutableSDField field, boolean isStructField, boolean ignoreAttributeAspect) { if (field.doesAttributing()) { return true; diff --git a/config-model/src/main/java/com/yahoo/schema/derived/VsmSummary.java b/config-model/src/main/java/com/yahoo/schema/derived/VsmSummary.java index 248cca33bc6..7507ef95482 100644 --- a/config-model/src/main/java/com/yahoo/schema/derived/VsmSummary.java +++ b/config-model/src/main/java/com/yahoo/schema/derived/VsmSummary.java @@ -9,14 +9,18 @@ import com.yahoo.vespa.documentmodel.DocumentSummary; import com.yahoo.vespa.documentmodel.SummaryField; import com.yahoo.vespa.config.search.vsm.VsmsummaryConfig; -import java.util.*; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * Vertical streaming matcher summary specification * * @author bratseth */ -public class VsmSummary extends Derived implements VsmsummaryConfig.Producer { +public class VsmSummary extends Derived { private final Map<SummaryField, List<String>> summaryMap = new java.util.LinkedHashMap<>(1); @@ -89,12 +93,10 @@ public class VsmSummary extends Derived implements VsmsummaryConfig.Producer { return ret; } - @Override - public String getDerivedName() { + @Override public String getDerivedName() { return "vsmsummary"; } - @Override public void getConfig(VsmsummaryConfig.Builder vB) { // Replace vB.fieldmap( @@ -105,5 +107,10 @@ public class VsmSummary extends Derived implements VsmsummaryConfig.Producer { ).toList() ); } - + + public void export(String toDirectory) throws IOException { + var builder = new VsmsummaryConfig.Builder(); + getConfig(builder); + export(toDirectory, builder.build()); + } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java index ffd346f704f..62979404025 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerModelEvaluation.java @@ -55,25 +55,25 @@ public class ContainerModelEvaluation implements @Override public void getConfig(RankProfilesConfig.Builder builder) { - rankProfileList.getConfig(builder); + builder.rankprofile(rankProfileList.getRankProfilesConfig()); } @Override public void getConfig(RankingConstantsConfig.Builder builder) { - rankProfileList.getConfig(builder); + builder.constant(rankProfileList.getConstantsConfig()); } @Override public void getConfig(OnnxModelsConfig.Builder builder) { if (onnxModels != null) { - onnxModels.getConfig(builder); + builder.model(onnxModels.getConfig()); } else { - rankProfileList.getConfig(builder); + builder.model(rankProfileList.getOnnxConfig()); } } public void getConfig(RankingExpressionsConfig.Builder builder) { - rankProfileList.getConfig(builder); + builder.expression(rankProfileList.getExpressionsConfig()); } public static Handler getHandler() { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ml/ModelsEvaluatorTester.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ml/ModelsEvaluatorTester.java index 800e766706b..bc936dc7441 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ml/ModelsEvaluatorTester.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ml/ModelsEvaluatorTester.java @@ -115,27 +115,27 @@ public class ModelsEvaluatorTester { } private static RankProfilesConfig getRankProfilesConfig(RankProfileList rankProfileList) { - RankProfilesConfig.Builder builder = new RankProfilesConfig.Builder(); - rankProfileList.getConfig(builder); - return builder.build(); + return new RankProfilesConfig.Builder() + .rankprofile(rankProfileList.getRankProfilesConfig()) + .build(); } private static RankingConstantsConfig getRankingConstantConfig(RankProfileList rankProfileList) { - RankingConstantsConfig.Builder builder = new RankingConstantsConfig.Builder(); - rankProfileList.getConfig(builder); - return builder.build(); + return new RankingConstantsConfig.Builder() + .constant(rankProfileList.getConstantsConfig()) + .build(); } private static RankingExpressionsConfig getRankingExpressionsConfig(RankProfileList rankProfileList) { - RankingExpressionsConfig.Builder builder = new RankingExpressionsConfig.Builder(); - rankProfileList.getConfig(builder); - return builder.build(); + return new RankingExpressionsConfig.Builder() + .expression(rankProfileList.getExpressionsConfig()) + .build(); } private static OnnxModelsConfig getOnnxModelsConfig(RankProfileList rankProfileList) { - OnnxModelsConfig.Builder builder = new OnnxModelsConfig.Builder(); - rankProfileList.getConfig(builder); - return builder.build(); + return new OnnxModelsConfig.Builder() + .model(rankProfileList.getOnnxConfig()) + .build(); } private static FileAcquirer createFileAcquirer(MockFileRegistry fileRegistry, File appDir) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/search/DocumentDatabase.java b/config-model/src/main/java/com/yahoo/vespa/model/search/DocumentDatabase.java index 334f8d4314a..ed571266f1b 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/search/DocumentDatabase.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/search/DocumentDatabase.java @@ -68,14 +68,20 @@ public class DocumentDatabase extends AnyConfigProducer implements // These methods append as multiple databases join config => TODO will loose information - not good @Override public void getConfig(AttributesConfig.Builder builder) { derivedCfg.getConfig(builder); } - @Override public void getConfig(RankProfilesConfig.Builder builder) { derivedCfg.getRankProfileList().getConfig(builder); } - - // These methods append, TODO unknown usage and consequences - @Override public void getConfig(RankingExpressionsConfig.Builder builder) { derivedCfg.getRankProfileList().getConfig(builder); } - @Override public void getConfig(RankingConstantsConfig.Builder builder) { derivedCfg.getRankProfileList().getConfig(builder); } - @Override public void getConfig(OnnxModelsConfig.Builder builder) { derivedCfg.getRankProfileList().getConfig(builder); } // Below methods will replace config completely + @Override public void getConfig(OnnxModelsConfig.Builder builder) { + builder.model(derivedCfg.getRankProfileList().getOnnxConfig()); + } + @Override public void getConfig(RankingExpressionsConfig.Builder builder) { + builder.expression(derivedCfg.getRankProfileList().getExpressionsConfig()); + } + @Override public void getConfig(RankingConstantsConfig.Builder builder) { + builder.constant(derivedCfg.getRankProfileList().getConstantsConfig()); + } + @Override public void getConfig(RankProfilesConfig.Builder builder) { + builder.rankprofile(derivedCfg.getRankProfileList().getRankProfilesConfig()); + } @Override public void getConfig(IndexschemaConfig.Builder builder) { derivedCfg.getIndexSchema().getConfig(builder); } @Override public void getConfig(JuniperrcConfig.Builder builder) { derivedCfg.getJuniperrc().getConfig(builder); } @Override public void getConfig(SummaryConfig.Builder builder) { derivedCfg.getSummaries().getConfig(builder); } diff --git a/config-model/src/test/java/com/yahoo/schema/derived/AbstractExportingTestCase.java b/config-model/src/test/java/com/yahoo/schema/derived/AbstractExportingTestCase.java index 7686289f11c..7d7ed2b23eb 100644 --- a/config-model/src/test/java/com/yahoo/schema/derived/AbstractExportingTestCase.java +++ b/config-model/src/test/java/com/yahoo/schema/derived/AbstractExportingTestCase.java @@ -70,6 +70,7 @@ public abstract class AbstractExportingTestCase extends AbstractSchemaTestCase { DerivedConfiguration.exportDocuments(new DocumentTypes().produce(builder.getModel(), new DocumenttypesConfig.Builder()), path); DerivedConfiguration.exportQueryProfiles(builder.getQueryProfileRegistry(), path); config.exportConstants(path); + config.exportOnnxModels(path); return config; } diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/secret/Key.java b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/Key.java new file mode 100644 index 00000000000..3de482b9cc6 --- /dev/null +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/Key.java @@ -0,0 +1,41 @@ +package com.yahoo.container.jdisc.secret; + +import java.util.Objects; + +public class Key { + + private final String keyGroup; + private final String keyName; + + public Key(String keyGroup, String keyName) { + this.keyGroup = keyGroup; + this.keyName = keyName; + } + + public String keyGroup() { + return keyGroup; + } + + public String keyName() { + return keyName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Key that = (Key) o; + if ( ! (that.keyGroup.equals(keyGroup))) return false; + if ( ! (that.keyName.equals(keyName))) return false; + return true; + } + + @Override + public int hashCode() { + return Objects.hash(keyGroup, keyName); + } + + @Override + public String toString() { return "key group: " + keyGroup + ", key name: " + keyName; } + +} diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/secret/Secret.java b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/Secret.java new file mode 100644 index 00000000000..fef0ba804eb --- /dev/null +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/Secret.java @@ -0,0 +1,58 @@ +package com.yahoo.container.jdisc.secret; + +import com.yahoo.security.YBase64; +import com.yahoo.text.Utf8; + +import java.util.Arrays; +import java.util.Objects; + +public class Secret { + + private final Key key; + private final byte[] secret; + private final int version; + + public Secret(Key key, byte[] secret, int version) { + this.key = key; + this.secret = secret; + this.version = version; + } + + public String keyGroup() { + return key.keyGroup(); + } + + public String keyName() { + return key.keyName(); + } + + public byte[] secret() { + return secret; + } + + public String secretAsString() { return Utf8.toString(secret); } + + /** @return secret value for keys that are auto-rotated by CKMS */ + public byte[] secretAsYbase64Decoded() { return YBase64.decode(secret); } + + public int version() { + return version; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Secret that = (Secret) o; + if ( ! (that.key.equals(key))) return false; + if ( ! (Arrays.equals(that.secret, secret))) return false; + if (that.version != (version)) return false; + return true; + } + + @Override + public int hashCode() { + return Objects.hash(key, version, Arrays.hashCode(secret)); + } + +} diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/secret/TypedSecretStore.java b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/TypedSecretStore.java new file mode 100644 index 00000000000..5bb00e836f5 --- /dev/null +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/TypedSecretStore.java @@ -0,0 +1,18 @@ +package com.yahoo.container.jdisc.secret; + +import com.yahoo.container.jdisc.secretstore.SecretStore; + +import java.util.List; + +public interface TypedSecretStore extends SecretStore { + + Secret getSecret(Key key); + + Secret getSecret(Key key, int version); + + /** Lists the existing versions of this secret (nonnegative integers) */ + default List<Secret> listSecretVersions(Key key) { + throw new UnsupportedOperationException("Secret store does not support listing versions"); + } + +} diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/secret/package-info.java b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/package-info.java new file mode 100644 index 00000000000..c80c6e66066 --- /dev/null +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/secret/package-info.java @@ -0,0 +1,6 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +@ExportPackage +package com.yahoo.container.jdisc.secret; + +import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java index f481d58d334..1fe0835306e 100644 --- a/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java +++ b/container-search/src/main/java/com/yahoo/prelude/cluster/ClusterSearcher.java @@ -29,9 +29,11 @@ import com.yahoo.yolean.Exceptions; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -177,7 +179,7 @@ public class ClusterSearcher extends Searcher { public Result search(Query query, Execution execution) { validateQueryTimeout(query); validateQueryCache(query); - Searcher searcher = server; + var searcher = server; if (searcher == null) { return new Result(query, ErrorMessage.createNoBackendsInService("Could not search")); } @@ -185,17 +187,17 @@ public class ClusterSearcher extends Searcher { return new Result(query, ErrorMessage.createTimeout("No time left for searching")); } - return doSearch(searcher, query, execution); + return doSearch(searcher, query); } @Override public void fill(com.yahoo.search.Result result, String summaryClass, Execution execution) { Query query = result.getQuery(); - Searcher searcher = server; + VespaBackEndSearcher searcher = server; if (searcher != null) { if (query.getTimeLeft() > 0) { - searcher.fill(result, summaryClass, execution); + searcher.fill(result, summaryClass); } else { if (result.hits().getErrorHit() == null) { result.hits().addError(ErrorMessage.createTimeout("No time left to get summaries, query timeout was " + @@ -230,22 +232,21 @@ public class ClusterSearcher extends Searcher { query.getRanking().setQueryCache(false); } - private Result doSearch(Searcher searcher, Query query, Execution execution) { + private Result doSearch(VespaBackEndSearcher searcher, Query query) { if (schemas.size() > 1) { - return searchMultipleDocumentTypes(searcher, query, execution); + return searchMultipleDocumentTypes(searcher, query); } else { - String docType = schemas.iterator().next(); - query.getModel().setRestrict(docType); - return perSchemaSearch(searcher, query, execution); + String schema = schemas.iterator().next(); + query.getModel().setRestrict(schema); + return perSchemaSearch(searcher, schema, query); } } - private Result perSchemaSearch(Searcher searcher, Query query, Execution execution) { + private Result perSchemaSearch(VespaBackEndSearcher searcher, String schema, Query query) { Set<String> restrict = query.getModel().getRestrict(); if (restrict.size() != 1) { throw new IllegalStateException("perSchemaSearch must always be called with 1 schema, got: " + restrict.size()); } - String schema = restrict.iterator().next(); int rerankCount = globalPhaseRanker != null ? globalPhaseRanker.getRerankCount(query, schema) : 0; boolean useGlobalPhase = rerankCount > 0; final int wantOffset = query.getOffset(); @@ -257,7 +258,7 @@ public class ClusterSearcher extends Searcher { query.setOffset(0); query.setHits(useHits); } - Result result = searcher.search(query, execution); + Result result = searcher.search(schema, query); if (useGlobalPhase) { globalPhaseRanker.rerankHits(query, result, schema); result.hits().trim(wantOffset, wantHits); @@ -284,16 +285,17 @@ public class ClusterSearcher extends Searcher { } } - private Result searchMultipleDocumentTypes(Searcher searcher, Query query, Execution execution) { + private Result searchMultipleDocumentTypes(VespaBackEndSearcher searcher, Query query) { Set<String> schemas = resolveSchemas(query); - List<Query> queries = createQueries(query, schemas); - if (queries.size() == 1) { - return perSchemaSearch(searcher, queries.get(0), execution); + Map<String, Query> schemaQueries = createQueries(query, schemas); + if (schemaQueries.size() == 1) { + var entry = schemaQueries.entrySet().iterator().next(); + return perSchemaSearch(searcher, entry.getKey(), entry.getValue()); } else { Result mergedResult = new Result(query); - List<FutureTask<Result>> pending = new ArrayList<>(queries.size()); - for (Query q : queries) { - FutureTask<Result> task = new FutureTask<>(() -> perSchemaSearch(searcher, q, execution)); + List<FutureTask<Result>> pending = new ArrayList<>(schemaQueries.size()); + for (var entry : schemaQueries.entrySet()) { + FutureTask<Result> task = new FutureTask<>(() -> perSchemaSearch(searcher, entry.getKey(), entry.getValue())); try { executor.execute(task); pending.add(task); @@ -309,7 +311,7 @@ public class ClusterSearcher extends Searcher { if (query.getOffset() > 0 || query.getHits() < mergedResult.hits().size()) { if (mergedResult.getHitOrderer() != null) { // Make sure we have the necessary data for sorting - searcher.fill(mergedResult, VespaBackEndSearcher.SORTABLE_ATTRIBUTES_SUMMARY_CLASS, execution); + searcher.fill(mergedResult, VespaBackEndSearcher.SORTABLE_ATTRIBUTES_SUMMARY_CLASS); } mergedResult.hits().trim(query.getOffset(), query.getHits()); query.setOffset(0); // Needed when doing a trim @@ -351,22 +353,24 @@ public class ClusterSearcher extends Searcher { return retval; } - private List<Query> createQueries(Query query, Set<String> docTypes) { + private Map<String, Query> createQueries(Query query, Set<String> schemas) { query.getModel().getQueryTree(); // performance: parse query before cloning such that it is only done once - List<Query> retval = new ArrayList<>(docTypes.size()); - if (docTypes.size() == 1) { - query.getModel().setRestrict(docTypes.iterator().next()); - retval.add(query); - } else if ( ! docTypes.isEmpty() ) { - for (String docType : docTypes) { + if (schemas.size() == 1) { + String schema = schemas.iterator().next(); + query.getModel().setRestrict(schema); + return Map.of(schema, query); + } else if ( ! schemas.isEmpty() ) { + var schemaQueries = new HashMap<String, Query>(); + for (String schema : schemas) { Query q = query.clone(); q.setOffset(0); q.setHits(query.getOffset() + query.getHits()); - q.getModel().setRestrict(docType); - retval.add(q); + q.getModel().setRestrict(schema); + schemaQueries.put(schema, q); } + return schemaQueries; } - return retval; + return Map.of(); } @Override diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java index ddb36e007d3..85b7770a8b2 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/FastSearcher.java @@ -1,8 +1,6 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.fastsearch; -import com.yahoo.prelude.Ping; -import com.yahoo.prelude.Pong; import com.yahoo.prelude.querytransform.QueryRewrite; import com.yahoo.search.Query; import com.yahoo.search.Result; @@ -16,7 +14,6 @@ import com.yahoo.search.result.ErrorMessage; import com.yahoo.search.result.Hit; import com.yahoo.search.result.HitGroup; import com.yahoo.search.schema.SchemaInfo; -import com.yahoo.search.searchchain.Execution; import java.io.IOException; import java.util.Optional; @@ -61,14 +58,6 @@ public class FastSearcher extends VespaBackEndSearcher { this.dispatcher = dispatcher; } - /** - * Pings the backend. Does not propagate to other searchers. - */ - @Override - public Pong ping(Ping ping, Execution execution) { - throw new IllegalStateException("This ping should not have been called."); - } - @Override protected void transformQuery(Query query) { QueryRewrite.rewriteSddocname(query); @@ -83,11 +72,11 @@ public class FastSearcher extends VespaBackEndSearcher { } @Override - public Result doSearch2(Query query, Execution execution) { + public Result doSearch2(String schema, Query query) { if (dispatcher.allGroupsHaveSize1()) forceSinglePassGrouping(query); try (SearchInvoker invoker = getSearchInvoker(query)) { - Result result = invoker.search(query, execution); + Result result = invoker.search(query); injectSource(result.hits()); if (query.properties().getBoolean(Ranking.RANKFEATURES, false)) { @@ -97,7 +86,7 @@ public class FastSearcher extends VespaBackEndSearcher { // contain the data we need. If we fetch the default // one we end up fetching docsums twice unless the // user also requested the default one. - fill(result, query.getPresentation().getSummary(), execution); // ARGH + fill(result, query.getPresentation().getSummary()); // ARGH } return result; } catch (TimeoutException e) { diff --git a/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java b/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java index 2e635d21f01..340262ed186 100644 --- a/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java +++ b/container-search/src/main/java/com/yahoo/prelude/fastsearch/VespaBackEndSearcher.java @@ -12,13 +12,11 @@ import com.yahoo.prelude.querytransform.QueryRewrite; import com.yahoo.protect.Validator; import com.yahoo.search.Query; import com.yahoo.search.Result; -import com.yahoo.search.cluster.PingableSearcher; import com.yahoo.search.schema.RankProfile; import com.yahoo.search.grouping.vespa.GroupingExecutor; import com.yahoo.search.result.ErrorMessage; import com.yahoo.search.result.Hit; import com.yahoo.search.schema.SchemaInfo; -import com.yahoo.search.searchchain.Execution; import com.yahoo.searchlib.aggregation.Grouping; import java.util.ArrayList; @@ -27,14 +25,13 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.logging.Logger; /** * Superclass for backend searchers. * * @author baldersheim */ -public abstract class VespaBackEndSearcher extends PingableSearcher { +public abstract class VespaBackEndSearcher { /** for vespa-internal use only; consider renaming the summary class */ public static final String SORTABLE_ATTRIBUTES_SUMMARY_CLASS = "attributeprefetch"; @@ -62,16 +59,13 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { /** Sets default document summary class. Default is null */ private void setDefaultDocsumClass(String docsumClass) { defaultDocsumClass = docsumClass; } - public final Logger getLogger() { return super.getLogger(); } - /** * Searches a search cluster * This is an endpoint - searchers will never propagate the search to any nested searcher. * * @param query the query to search - * @param execution the query execution context */ - protected abstract Result doSearch2(Query query, Execution execution); + protected abstract Result doSearch2(String schema, Query query); protected abstract void doPartialFill(Result result, String summaryClass); @@ -154,8 +148,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { protected void transformQuery(Query query) { } - @Override - public Result search(Query query, Execution execution) { + public Result search(String schema, Query query) { // query root should not be null here Item root = query.getModel().getQueryTree().getRoot(); if (root == null || root instanceof NullItem) { @@ -183,7 +176,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { if (root == null || root instanceof NullItem) // root can become null after resolving and transformation? return new Result(query); - Result result = doSearch2(query, execution); + Result result = doSearch2(schema, query); if (query.getTrace().getLevel() >= 1) query.trace(getName() + " dispatch response: " + result, false, 1); @@ -217,8 +210,7 @@ public abstract class VespaBackEndSearcher extends PingableSearcher { return parts; } - @Override - public void fill(Result result, String summaryClass, Execution execution) { + public void fill(Result result, String summaryClass) { if (result.isFilled(summaryClass)) return; // TODO: Checked in the superclass - remove List<Result> parts = partitionHits(result, summaryClass); diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java b/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java index be8524bedd2..a246589ec7e 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/InterleavedSearchInvoker.java @@ -111,9 +111,9 @@ public class InterleavedSearchInvoker extends SearchInvoker implements ResponseM } @Override - protected InvokerResult getSearchResult(Execution execution) throws IOException { + protected InvokerResult getSearchResult() throws IOException { InvokerResult result = new InvokerResult(query, query.getHits()); - List<LeanHit> merged = Collections.emptyList(); + List<LeanHit> merged = List.of(); long nextTimeout = query.getTimeLeft(); var groupingResultAggregator = new GroupingResultAggregator(); try { @@ -124,7 +124,7 @@ public class InterleavedSearchInvoker extends SearchInvoker implements ResponseM coverageAggregator.getAnsweredNodes() + " responses received"); break; } else { - InvokerResult toMerge = invoker.getSearchResult(execution); + InvokerResult toMerge = invoker.getSearchResult(); merged = mergeResult(result.getResult(), toMerge, merged, groupingResultAggregator); ejectInvoker(invoker); } diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/SearchErrorInvoker.java b/container-search/src/main/java/com/yahoo/search/dispatch/SearchErrorInvoker.java index b494b5b3819..74da2388155 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/SearchErrorInvoker.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/SearchErrorInvoker.java @@ -35,7 +35,7 @@ public class SearchErrorInvoker extends SearchInvoker { } @Override - protected Object sendSearchRequest(Query query, Object context) throws IOException { + protected Object sendSearchRequest(Query query, Object context) { this.query = query; if (monitor != null) { monitor.responseAvailable(this); @@ -44,7 +44,7 @@ public class SearchErrorInvoker extends SearchInvoker { } @Override - protected InvokerResult getSearchResult(Execution execution) throws IOException { + protected InvokerResult getSearchResult() { Result res = new Result(query, message); if (coverage != null) { res.setCoverage(coverage); diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/SearchInvoker.java b/container-search/src/main/java/com/yahoo/search/dispatch/SearchInvoker.java index ad332494179..4ad89674b7b 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/SearchInvoker.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/SearchInvoker.java @@ -31,9 +31,9 @@ public abstract class SearchInvoker extends CloseableInvoker { * nodes, the provided {@link Execution} may be used to retrieve document summaries required * for correct result windowing. */ - public Result search(Query query, Execution execution) throws IOException { + public Result search(Query query) throws IOException { sendSearchRequest(query, null); - InvokerResult result = getSearchResult(execution); + InvokerResult result = getSearchResult(); setFinalStatus(result.getResult().hits().getError() == null); result.complete(); return result.getResult(); @@ -48,7 +48,7 @@ public abstract class SearchInvoker extends CloseableInvoker { */ protected abstract Object sendSearchRequest(Query query, Object context) throws IOException; - protected abstract InvokerResult getSearchResult(Execution execution) throws IOException; + protected abstract InvokerResult getSearchResult() throws IOException; protected void setMonitor(ResponseMonitor<SearchInvoker> monitor) { this.monitor = monitor; diff --git a/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcSearchInvoker.java b/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcSearchInvoker.java index e34e5c97bc4..93e09a04180 100644 --- a/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcSearchInvoker.java +++ b/container-search/src/main/java/com/yahoo/search/dispatch/rpc/RpcSearchInvoker.java @@ -86,7 +86,7 @@ public class RpcSearchInvoker extends SearchInvoker implements Client.ResponseRe } @Override - protected InvokerResult getSearchResult(Execution execution) throws IOException { + protected InvokerResult getSearchResult() throws IOException { long timeLeftMs = query.getTimeLeft(); if (timeLeftMs <= 0) { return errorResult(query, ErrorMessage.createTimeout("Timeout while waiting for " + getName())); diff --git a/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingSearcher.java b/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingSearcher.java index 180fdc389d8..2f3b48b5683 100644 --- a/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingSearcher.java +++ b/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingSearcher.java @@ -126,7 +126,7 @@ public class StreamingSearcher extends VespaBackEndSearcher { } @Override - public Result doSearch2(Query query, Execution execution) { + public Result doSearch2(String schema, Query query) { if (query.getTimeLeft() <= 0) return new Result(query, ErrorMessage.createTimeout(String.format("No time left for searching (timeout=%d)", query.getTimeout()))); @@ -135,8 +135,6 @@ public class StreamingSearcher extends VespaBackEndSearcher { return new Result(query, ErrorMessage.createIllegalQuery("Streaming search requires either " + "streaming.groupname or streaming.selection")); } - // Cluster searcher guarantees that there will be one, and only one schema here - String schema = query.getModel().getRestrict().iterator().next(); if (query.getTrace().isTraceable(4)) query.trace("Routing to search cluster " + getSearchClusterName() + " and document type " + schema, 4); @@ -264,7 +262,7 @@ public class StreamingSearcher extends VespaBackEndSearcher { lazyTrace(query, 8, "Returning result ", result); if (skippedHits > 0) { - getLogger().info("skipping " + skippedHits + " hits for query: " + result.getQuery()); + log.info("skipping " + skippedHits + " hits for query: " + result.getQuery()); result.hits().addError(ErrorMessage.createTimeout("Missing hit summary data for " + skippedHits + " hits")); } @@ -366,8 +364,8 @@ public class StreamingSearcher extends VespaBackEndSearcher { } @Override - public Visitor createVisitor(Query query, String searchCluster, Route route, String documentType, int traceLevelOverride) { - return new StreamingVisitor(query, searchCluster, route, documentType, this, traceLevelOverride); + public Visitor createVisitor(Query query, String searchCluster, Route route, String schema, int traceLevelOverride) { + return new StreamingVisitor(query, searchCluster, route, schema, this, traceLevelOverride); } } diff --git a/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingVisitor.java b/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingVisitor.java index 658eea0b526..e638e0cf12a 100644 --- a/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingVisitor.java +++ b/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/StreamingVisitor.java @@ -28,6 +28,7 @@ import com.yahoo.vdslib.VisitorStatistics; import com.yahoo.vespa.objects.BufferSerializer; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -76,13 +77,13 @@ class StreamingVisitor extends VisitorDataHandler implements Visitor { } public StreamingVisitor(Query query, String searchCluster, Route route, - String documentType, VisitorSessionFactory visitorSessionFactory, + String schema, VisitorSessionFactory visitorSessionFactory, int traceLevelOverride) { this.query = query; this.visitorSessionFactory = visitorSessionFactory; this.traceLevelOverride = traceLevelOverride; - setVisitorParameters(searchCluster, route, documentType); + setVisitorParameters(searchCluster, route, schema); } private int inferSessionTraceLevel(Query query) { @@ -112,8 +113,8 @@ class StreamingVisitor extends VisitorDataHandler implements Visitor { return query.properties().getString(streamingSelection); } - private void setVisitorParameters(String searchCluster, Route route, String documentType) { - params.setDocumentSelection(createSelectionString(documentType, createQuerySelectionString())); + private void setVisitorParameters(String searchCluster, Route route, String schema) { + params.setDocumentSelection(createSelectionString(schema, createQuerySelectionString())); params.setTimeoutMs(query.getTimeout()); // Per bucket visitor timeout params.setSessionTimeoutMs(query.getTimeout()); params.setVisitorLibrary("searchvisitor"); @@ -146,7 +147,8 @@ class StreamingVisitor extends VisitorDataHandler implements Visitor { encodeQueryData(query, 0, ed); params.setLibraryParameter("query", ed.getEncodedData()); params.setLibraryParameter("querystackcount", String.valueOf(ed.getReturned())); - params.setLibraryParameter("searchcluster", searchCluster.getBytes()); + params.setLibraryParameter("searchcluster", searchCluster.getBytes(StandardCharsets.UTF_8)); + params.setLibraryParameter("schema", schema.getBytes(StandardCharsets.UTF_8)); if (query.getPresentation().getSummary() != null) { params.setLibraryParameter("summaryclass", query.getPresentation().getSummary()); } else { diff --git a/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/VisitorFactory.java b/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/VisitorFactory.java index 10387065128..e33bbd206be 100644 --- a/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/VisitorFactory.java +++ b/container-search/src/main/java/com/yahoo/vespa/streamingvisitors/VisitorFactory.java @@ -11,6 +11,6 @@ import com.yahoo.search.Query; */ interface VisitorFactory { - Visitor createVisitor(Query query, String searchCluster, Route route, String documentType, int traceLevelOverride); + Visitor createVisitor(Query query, String searchCluster, Route route, String schema, int traceLevelOverride); } diff --git a/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java index 8d4e3364ce4..affa6161440 100644 --- a/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java +++ b/container-search/src/test/java/com/yahoo/prelude/cluster/ClusterSearcherTestCase.java @@ -206,12 +206,12 @@ public class ClusterSearcherTestCase { } @Override - protected com.yahoo.search.Result doSearch2(Query query, Execution execution) { + protected com.yahoo.search.Result doSearch2(String schema, Query query) { return null; // search() is overriden, this should never be called } @Override - public com.yahoo.search.Result search(Query query, Execution execution) { + public com.yahoo.search.Result search(String schema, Query query) { com.yahoo.search.Result result = new com.yahoo.search.Result(query); List<Hit> hits = getHits(query); if (hits != null) { diff --git a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java index 20d2a304c3c..8270700a66b 100644 --- a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java +++ b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/FastSearcherTestCase.java @@ -1,7 +1,6 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.fastsearch.test; -import com.yahoo.component.chain.Chain; import com.yahoo.container.QrSearchersConfig; import com.yahoo.container.handler.VipStatus; import com.yahoo.container.protect.Error; @@ -9,9 +8,9 @@ import com.yahoo.prelude.fastsearch.ClusterParams; import com.yahoo.prelude.fastsearch.DocumentdbInfoConfig; import com.yahoo.prelude.fastsearch.FastSearcher; import com.yahoo.prelude.fastsearch.SummaryParameters; +import com.yahoo.prelude.fastsearch.VespaBackEndSearcher; import com.yahoo.search.Query; import com.yahoo.search.Result; -import com.yahoo.search.Searcher; import com.yahoo.search.dispatch.MockDispatcher; import com.yahoo.search.dispatch.rpc.RpcResourcePool; import com.yahoo.search.dispatch.searchcluster.Node; @@ -24,10 +23,8 @@ import com.yahoo.search.schema.DocumentSummary; import com.yahoo.search.schema.RankProfile; import com.yahoo.search.schema.Schema; import com.yahoo.search.schema.SchemaInfo; -import com.yahoo.search.searchchain.Execution; import org.junit.jupiter.api.Test; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Level; @@ -42,16 +39,18 @@ import static org.junit.jupiter.api.Assertions.*; * @author bratseth */ public class FastSearcherTestCase { + private static final String SCHEMA = "test"; + private static final String CLUSTER = "test"; @Test void testNullQuery() { Logger.getLogger(FastSearcher.class.getName()).setLevel(Level.ALL); FastSearcher fastSearcher = new FastSearcher("container.0", - MockDispatcher.create(Collections.emptyList()), + MockDispatcher.create(List.of()), new SummaryParameters(null), new ClusterParams("testhittype"), - documentdbInfoConfig("test"), - schemaInfo("test")); + documentdbInfoConfig(SCHEMA), + schemaInfo(SCHEMA)); String query = "?junkparam=ignored"; Result result = doSearch(fastSearcher, new Query(query), 0, 10); @@ -63,30 +62,20 @@ public class FastSearcherTestCase { assertEquals(Error.NULL_QUERY.code, message.getCode()); } - private Chain<Searcher> chainedAsSearchChain(Searcher topOfChain) { - List<Searcher> searchers = new ArrayList<>(); - searchers.add(topOfChain); - return new Chain<>(searchers); - } - - private Result doSearch(Searcher searcher, Query query, int offset, int hits) { + private Result doSearch(VespaBackEndSearcher searcher, Query query, int offset, int hits) { query.setOffset(offset); query.setHits(hits); - return createExecution(searcher).search(query); - } - - private Execution createExecution(Searcher searcher) { - return new Execution(chainedAsSearchChain(searcher), Execution.Context.createContextStub()); + return searcher.search(SCHEMA, query); } @Test void testSinglePassGroupingIsForcedWithSingleNodeGroups() { FastSearcher fastSearcher = new FastSearcher("container.0", - MockDispatcher.create(List.of(new Node("test", 0, "host0", 0))), + MockDispatcher.create(List.of(new Node(CLUSTER, 0, "host0", 0))), new SummaryParameters(null), new ClusterParams("testhittype"), - documentdbInfoConfig("test"), - schemaInfo("test")); + documentdbInfoConfig(SCHEMA), + schemaInfo(SCHEMA)); Query q = new Query("?query=foo"); GroupingRequest request1 = GroupingRequest.newInstance(q); request1.setRootOperation(new AllOperation()); @@ -98,18 +87,18 @@ public class FastSearcherTestCase { request2.setRootOperation(all); assertForceSinglePassIs(false, q); - fastSearcher.search(q, new Execution(Execution.Context.createContextStub())); + fastSearcher.search(SCHEMA, q); assertForceSinglePassIs(true, q); } @Test void testRankProfileValidation() { FastSearcher fastSearcher = new FastSearcher("container.0", - MockDispatcher.create(List.of(new Node("test", 0, "host0", 0))), + MockDispatcher.create(List.of(new Node(CLUSTER, 0, "host0", 0))), new SummaryParameters(null), new ClusterParams("testhittype"), - documentdbInfoConfig("test"), - schemaInfo("test")); + documentdbInfoConfig(SCHEMA), + schemaInfo(SCHEMA)); assertFalse(searchError("?query=q", fastSearcher).contains("does not contain requested rank profile")); assertFalse(searchError("?query=q&ranking.profile=default", fastSearcher).contains("does not contain requested rank profile")); assertTrue(searchError("?query=q&ranking.profile=nosuch", fastSearcher).contains("does not contain requested rank profile")); @@ -117,14 +106,14 @@ public class FastSearcherTestCase { @Test void testSummaryNeedsQuery() { - var documentDb = new DocumentdbInfoConfig(new DocumentdbInfoConfig.Builder().documentdb(new DocumentdbInfoConfig.Documentdb.Builder().name("test"))); - var schema = new Schema.Builder("test") + var documentDb = new DocumentdbInfoConfig(new DocumentdbInfoConfig.Builder().documentdb(new DocumentdbInfoConfig.Documentdb.Builder().name(SCHEMA))); + var schema = new Schema.Builder(SCHEMA) .add(new DocumentSummary.Builder("default").build()) .add(new RankProfile.Builder("default").setHasRankFeatures(false) .setHasSummaryFeatures(false) .build()); FastSearcher backend = new FastSearcher("container.0", - MockDispatcher.create(Collections.singletonList(new Node("test", 0, "host0", 0))), + MockDispatcher.create(Collections.singletonList(new Node(CLUSTER, 0, "host0", 0))), new SummaryParameters(null), new ClusterParams("testhittype"), documentDb, @@ -141,14 +130,14 @@ public class FastSearcherTestCase { @Test void testSinglePassGroupingIsNotForcedWithSingleNodeGroups() { - MockDispatcher dispatcher = MockDispatcher.create(List.of(new Node("test", 0, "host0", 0), new Node("test", 2, "host1", 0))); + MockDispatcher dispatcher = MockDispatcher.create(List.of(new Node(CLUSTER, 0, "host0", 0), new Node(CLUSTER, 2, "host1", 0))); FastSearcher fastSearcher = new FastSearcher("container.0", dispatcher, new SummaryParameters(null), new ClusterParams("testhittype"), - documentdbInfoConfig("test"), - schemaInfo("test")); + documentdbInfoConfig(SCHEMA), + schemaInfo(SCHEMA)); Query q = new Query("?query=foo"); GroupingRequest request1 = GroupingRequest.newInstance(q); request1.setRootOperation(new AllOperation()); @@ -160,7 +149,7 @@ public class FastSearcherTestCase { request2.setRootOperation(all); assertForceSinglePassIs(false, q); - fastSearcher.search(q, new Execution(Execution.Context.createContextStub())); + fastSearcher.search(SCHEMA, q); assertForceSinglePassIs(false, q); } @@ -183,7 +172,7 @@ public class FastSearcherTestCase { searchClusterB.name(clusterName); b.searchcluster(searchClusterB); VipStatus vipStatus = new VipStatus(b.build()); - List<Node> nodes_1 = List.of(new Node("test", 0, "host0", 0)); + List<Node> nodes_1 = List.of(new Node(CLUSTER, 0, "host0", 0)); RpcResourcePool rpcPool_1 = new RpcResourcePool(MockDispatcher.toDispatchConfig(), MockDispatcher.toNodesConfig(nodes_1)); MockDispatcher dispatch_1 = MockDispatcher.create(nodes_1, rpcPool_1, vipStatus); dispatch_1.clusterMonitor.shutdown(); @@ -193,12 +182,12 @@ public class FastSearcherTestCase { assertTrue(vipStatus.isInRotation()); //Verify that deconstruct does not touch vipstatus } - private String searchError(String query, Searcher searcher) { + private String searchError(String query, VespaBackEndSearcher searcher) { return search(query, searcher).hits().getError().getDetailedMessage(); } - private Result search(String query, Searcher searcher) { - return searcher.search(new Query(query), new Execution(Execution.Context.createContextStub())); + private Result search(String query, VespaBackEndSearcher searcher) { + return searcher.search(SCHEMA, new Query(query)); } private DocumentdbInfoConfig documentdbInfoConfig(String schemaName) { diff --git a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/PartialFillTestCase.java b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/PartialFillTestCase.java index 27a27e993a8..a033ccdace6 100644 --- a/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/PartialFillTestCase.java +++ b/container-search/src/test/java/com/yahoo/prelude/fastsearch/test/PartialFillTestCase.java @@ -2,16 +2,13 @@ package com.yahoo.prelude.fastsearch.test; import com.yahoo.component.chain.Chain; -import com.yahoo.language.simple.SimpleLinguistics; import com.yahoo.prelude.fastsearch.FastHit; import com.yahoo.prelude.fastsearch.VespaBackEndSearcher; import com.yahoo.search.Query; import com.yahoo.search.Result; import com.yahoo.search.Searcher; -import com.yahoo.search.rendering.RendererRegistry; import com.yahoo.search.result.ErrorHit; import com.yahoo.search.result.ErrorMessage; -import com.yahoo.search.searchchain.Execution; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -27,7 +24,7 @@ public class PartialFillTestCase { public static class FS4 extends VespaBackEndSearcher { public List<Result> history = new ArrayList<>(); - protected Result doSearch2(Query query, Execution execution) { + protected Result doSearch2(String schema, Query query) { return new Result(query); } protected void doPartialFill(Result result, String summaryClass) { @@ -36,7 +33,7 @@ public class PartialFillTestCase { } public static class BadFS4 extends VespaBackEndSearcher { - protected Result doSearch2(Query query, Execution execution) { + protected Result doSearch2(String schema, Query query) { return new Result(query); } protected void doPartialFill(Result result, String summaryClass) { @@ -130,24 +127,18 @@ public class PartialFillTestCase { com.yahoo.search.result.ErrorMessage error = i.next(); switch (n) { case 0: - assertEquals(exp_sub, error); - break; case 1: assertEquals(exp_sub, error); break; default: - assertTrue(false); + fail(); } n++; } } - private Execution createExecution(Searcher searcher) { - return new Execution(chainedAsSearchChain(searcher), Execution.Context.createContextStub()); - } - - private void doFill(Searcher searcher, Result result, String summaryClass) { - createExecution(searcher).fill(result, summaryClass); + private void doFill(VespaBackEndSearcher searcher, Result result, String summaryClass) { + searcher.fill(result, summaryClass); } private Chain<Searcher> chainedAsSearchChain(Searcher topOfChain) { diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java index 8dc74110291..23846db3f0b 100644 --- a/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java +++ b/container-search/src/test/java/com/yahoo/search/dispatch/DispatcherTest.java @@ -18,7 +18,6 @@ import com.yahoo.search.dispatch.searchcluster.Pinger; import com.yahoo.search.dispatch.searchcluster.PongHandler; import com.yahoo.search.dispatch.searchcluster.SearchCluster; import com.yahoo.search.dispatch.searchcluster.SearchGroups; -import com.yahoo.search.searchchain.Execution; import com.yahoo.vespa.config.search.DispatchConfig; import com.yahoo.vespa.config.search.DispatchNodesConfig; import com.yahoo.yolean.UncheckedInterruptedException; @@ -243,7 +242,7 @@ public class DispatcherTest { rpcPool.getConnection(node.key()).request(null, null, 0, null, null, 0); return null; }; - @Override protected InvokerResult getSearchResult(Execution execution) { + @Override protected InvokerResult getSearchResult() { return new InvokerResult(new Result(new Query())); } @Override protected void release() { } @@ -288,11 +287,11 @@ public class DispatcherTest { // Start some searches, one against each group, since we have a round-robin policy. SearchInvoker search0 = dispatcher.getSearchInvoker(new Query(), null); - search0.search(new Query(), null); + search0.search(new Query()); // Unknown whether the first or second search hits node0, so we must track that. int offset = nodeIdOfSearcher0.get(); SearchInvoker search1 = dispatcher.getSearchInvoker(new Query(), null); - search1.search(new Query(), null); + search1.search(new Query()); // Wait for the current cluster monitor to be mid-ping-round. doPing.set(true); @@ -330,7 +329,7 @@ public class DispatcherTest { // Next search should hit group0 again, this time on node2. SearchInvoker search2 = dispatcher.getSearchInvoker(new Query(), null); - search2.search(new Query(), null); + search2.search(new Query()); // Searches against nodes 1 and 2 complete. (offset == 0 ? search0 : search1).close(); diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java index fac75b1dd68..8ced7d3895e 100644 --- a/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java +++ b/container-search/src/test/java/com/yahoo/search/dispatch/InterleavedSearchInvokerTest.java @@ -61,7 +61,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(4900, 100, 1)); expectedEvents.add(new Event(4800, 100, 2)); - invoker.search(query, null); + invoker.search(query); assertTrue(expectedEvents.isEmpty(), "All test scenario events processed"); } @@ -75,7 +75,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(4700, 300, 1)); expectedEvents.add(null); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertTrue(expectedEvents.isEmpty(), "All test scenario events processed"); assertNull(result.hits().getErrorHit(), "Result is not marked as an error"); @@ -94,7 +94,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(2400, 100, 2)); expectedEvents.add(new Event(0, 0, null)); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertTrue(expectedEvents.isEmpty(), "All test scenario events processed"); assertNull(result.hits().getErrorHit(), "Result is not marked as an error"); @@ -113,7 +113,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(null, 100, 0)); expectedEvents.add(new Event(null, 200, 1)); - Result result = invoker.search(query, null); + Result result = invoker.search(query); Coverage cov = result.getCoverage(true); assertEquals(100000L, cov.getDocs()); @@ -134,7 +134,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(null, 100, 0)); expectedEvents.add(new Event(null, 200, 1)); - Result result = invoker.search(query, null); + Result result = invoker.search(query); Coverage cov = result.getCoverage(true); assertEquals(23420L, cov.getDocs()); @@ -156,7 +156,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(null, 100, 0)); expectedEvents.add(new Event(null, 200, 1)); - Result result = invoker.search(query, null); + Result result = invoker.search(query); Coverage cov = result.getCoverage(true); assertEquals(9900L, cov.getDocs()); @@ -178,7 +178,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(null, 100, 0)); expectedEvents.add(null); - Result result = invoker.search(query, null); + Result result = invoker.search(query); Coverage cov = result.getCoverage(true); assertEquals(50155L, cov.getDocs()); @@ -213,7 +213,7 @@ public class InterleavedSearchInvokerTest { query.setHits(8); query.properties().set(Dispatcher.topKProbability, topKProbability); SearchInvoker[] invokers = invoker.invokers().toArray(new SearchInvoker[0]); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(2, invokers.length); assertEquals(expectedK, ((MockInvoker) invokers[0]).hitsRequested); assertEquals(8, result.hits().size()); @@ -264,7 +264,7 @@ public class InterleavedSearchInvokerTest { void requireThatMergeOfConcreteHitsObeySorting() throws IOException { try (InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5, B5, new Group(0, List.of()))) { query.setHits(12); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(10, result.hits().size()); assertEquals(11.0, result.hits().get(0).getRelevance().getScore(), DELTA); assertEquals(1.0, result.hits().get(9).getRelevance().getScore(), DELTA); @@ -273,7 +273,7 @@ public class InterleavedSearchInvokerTest { } try ( InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(B5, A5, new Group(0, List.of()))) { - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(10, result.hits().size()); assertEquals(11.0, result.hits().get(0).getRelevance().getScore(), DELTA); assertEquals(1.0, result.hits().get(9).getRelevance().getScore(), DELTA); @@ -287,7 +287,7 @@ public class InterleavedSearchInvokerTest { try (InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5, B5, new Group(0, List.of()))) { query.setHits(3); query.setOffset(5); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(3, result.hits().size()); assertEquals(7.0, result.hits().get(0).getRelevance().getScore(), DELTA); assertEquals(3.0, result.hits().get(2).getRelevance().getScore(), DELTA); @@ -297,7 +297,7 @@ public class InterleavedSearchInvokerTest { try (InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(B5, A5, new Group(0, List.of()))) { query.setOffset(5); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(3, result.hits().size()); assertEquals(7.0, result.hits().get(0).getRelevance().getScore(), DELTA); assertEquals(3.0, result.hits().get(2).getRelevance().getScore(), DELTA); @@ -311,7 +311,7 @@ public class InterleavedSearchInvokerTest { try (InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(A5Aux, B5Aux, new Group(0, List.of()))) { query.setHits(3); query.setOffset(5); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(7, result.hits().size()); assertEquals(7.0, result.hits().get(0).getRelevance().getScore(), DELTA); assertEquals(3.0, result.hits().get(2).getRelevance().getScore(), DELTA); @@ -322,7 +322,7 @@ public class InterleavedSearchInvokerTest { try (InterleavedSearchInvoker invoker = createInterLeavedTestInvoker(B5Aux, A5Aux, new Group(0, List.of()))) { query.setOffset(5); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(7, result.hits().size()); assertEquals(7.0, result.hits().get(0).getRelevance().getScore(), DELTA); assertEquals(3.0, result.hits().get(2).getRelevance().getScore(), DELTA); @@ -359,7 +359,7 @@ public class InterleavedSearchInvokerTest { try (InterleavedSearchInvoker invoker = new InterleavedSearchInvoker(Timer.monotonic, invokers, hitEstimator, dispatchConfig, new Group(0, List.of()), Collections.emptySet())) { invoker.responseAvailable(invokers.get(0)); invoker.responseAvailable(invokers.get(1)); - Result result = invoker.search(query, null); + Result result = invoker.search(query); assertEquals(1, ((GroupingListHit) result.hits().get(0)).getGroupingList().size()); } for (SearchInvoker invoker : invokers) { @@ -404,7 +404,7 @@ public class InterleavedSearchInvokerTest { expectedEvents.add(new Event(null, 1, 1)); expectedEvents.add(new Event(null, 100, 0)); - Result result = invoker.search(query, null); + Result result = invoker.search(query); Coverage cov = result.getCoverage(true); assertEquals(50155L, cov.getDocs()); diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java b/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java index a1521a88fb7..e43f3b0bd9a 100644 --- a/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java +++ b/container-search/src/test/java/com/yahoo/search/dispatch/MockInvoker.java @@ -40,7 +40,7 @@ class MockInvoker extends SearchInvoker { } @Override - protected InvokerResult getSearchResult(Execution execution) { + protected InvokerResult getSearchResult() { InvokerResult ret = new InvokerResult(query, 10); if (coverage != null) { ret.getResult().setCoverage(coverage); diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java index 3f527f34f31..2600d8612f8 100644 --- a/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java +++ b/container-search/src/test/java/com/yahoo/search/dispatch/rpc/RpcSearchInvokerTest.java @@ -9,7 +9,6 @@ import com.yahoo.prelude.fastsearch.VespaBackEndSearcher; import com.yahoo.search.Query; import com.yahoo.search.Result; import com.yahoo.search.dispatch.searchcluster.Node; -import com.yahoo.search.searchchain.Execution; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -45,7 +44,7 @@ public class RpcSearchInvokerTest { assertEquals(10, request.getHits()); assertEquals(3, request.getOffset()); - assertTrue(request.getQueryTreeBlob().size() > 0); + assertFalse(request.getQueryTreeBlob().isEmpty()); var invoker2 = new RpcSearchInvoker(mockSearcher(), compressor, new Node("test", 8, "eight", 1), mockPool, 1000); RpcSearchInvoker.RpcContext context2 = (RpcSearchInvoker.RpcContext) invoker2.sendSearchRequest(q, context); @@ -121,7 +120,7 @@ public class RpcSearchInvokerTest { private VespaBackEndSearcher mockSearcher() { return new VespaBackEndSearcher() { @Override - protected Result doSearch2(Query query, Execution execution) { + protected Result doSearch2(String schema, Query query) { fail("Unexpected call"); return null; } diff --git a/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingSearcherTestCase.java b/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingSearcherTestCase.java index 3d9a958c757..c7e95f802ab 100644 --- a/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingSearcherTestCase.java +++ b/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingSearcherTestCase.java @@ -16,7 +16,6 @@ import com.yahoo.search.Result; import com.yahoo.search.result.Hit; import com.yahoo.search.schema.Schema; import com.yahoo.search.schema.SchemaInfo; -import com.yahoo.search.searchchain.Execution; import com.yahoo.searchlib.aggregation.Grouping; import com.yahoo.vdslib.DocumentSummary; import com.yahoo.vdslib.SearchResult; @@ -161,9 +160,7 @@ public class StreamingSearcherTestCase { } private static Result executeQuery(StreamingSearcher searcher, Query query) { - Execution execution = new Execution(Execution.Context.createContextStub()); - query.getModel().setRestrict("test"); - return searcher.doSearch2(query, execution); + return searcher.doSearch2("test", query); } private static Query[] generateTestQueries(String queryString) { diff --git a/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingVisitorTest.java b/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingVisitorTest.java index 8be60b7c3b0..30fb33ee8c8 100644 --- a/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingVisitorTest.java +++ b/container-search/src/test/java/com/yahoo/vespa/streamingvisitors/StreamingVisitorTest.java @@ -23,6 +23,7 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static org.junit.jupiter.api.Assertions.*; @@ -76,7 +77,7 @@ public class StreamingVisitorTest { }; } - private class QueryArguments { + private static class QueryArguments { // General query parameters String query = "test"; double timeout = 0.5; @@ -188,25 +189,21 @@ public class StreamingVisitorTest { return query; } - private void verifyVisitorParameters(VisitorParameters params, QueryArguments qa, String searchCluster, String docType, Route route) { + private void verifyVisitorParameters(VisitorParameters params, QueryArguments qa, String searchCluster, String schema, Route route) { //System.out.println("params="+params); // Verify parameters based on properties if (qa.userId != null) { - assertEquals(docType + " and ( id.user=="+qa.userId + " )", params.getDocumentSelection()); + assertEquals(schema + " and ( id.user=="+qa.userId + " )", params.getDocumentSelection()); } else if (qa.groupName != null) { - assertEquals(docType + " and ( id.group==\""+qa.groupName+"\" )", params.getDocumentSelection()); + assertEquals(schema + " and ( id.group==\""+qa.groupName+"\" )", params.getDocumentSelection()); } else if ((qa.selection == null) || qa.selection.isEmpty()) { - assertEquals(docType, params.getDocumentSelection()); + assertEquals(schema, params.getDocumentSelection()); } else { - assertEquals(docType + " and ( " + qa.selection + " )", params.getDocumentSelection()); + assertEquals(schema + " and ( " + qa.selection + " )", params.getDocumentSelection()); } assertEquals(qa.from, params.getFromTimestamp()); assertEquals(qa.to, params.getToTimestamp()); - if (qa.priority != null) { - assertEquals(qa.priority, params.getPriority()); - } else { - assertEquals(DocumentProtocol.Priority.VERY_HIGH, params.getPriority()); - } + assertEquals(Objects.requireNonNullElse(qa.priority, DocumentProtocol.Priority.VERY_HIGH), params.getPriority()); if (qa.maxBucketsPerVisitor != 0) { assertEquals(qa.maxBucketsPerVisitor, params.getMaxBucketsPerVisitor()); } else { @@ -227,17 +224,10 @@ public class StreamingVisitorTest { //System.err.println("query="+new String(params.getLibraryParameters().get("querystackcount"))); assertNotNull(params.getLibraryParameters().get("querystackcount")); // TODO: Check contents assertEquals(searchCluster, new String(params.getLibraryParameters().get("searchcluster"))); - if (qa.summary != null) { - assertEquals(qa.summary, new String(params.getLibraryParameters().get("summaryclass"))); - } else { - assertEquals("default", new String(params.getLibraryParameters().get("summaryclass"))); - } + assertEquals(schema, new String(params.getLibraryParameters().get("schema"))); + assertEquals(Objects.requireNonNullElse(qa.summary, "default"), new String(params.getLibraryParameters().get("summaryclass"))); assertEquals(Integer.toString(qa.offset+qa.hits), new String(params.getLibraryParameters().get("summarycount"))); - if (qa.profile != null) { - assertEquals(qa.profile, new String(params.getLibraryParameters().get("rankprofile"))); - } else { - assertEquals("default", new String(params.getLibraryParameters().get("rankprofile"))); - } + assertEquals(Objects.requireNonNullElse(qa.profile, "default"), new String(params.getLibraryParameters().get("rankprofile"))); //System.err.println("queryflags="+new String(params.getLibraryParameters().get("queryflags"))); assertNotNull(params.getLibraryParameters().get("queryflags")); // TODO: Check contents if (qa.location != null) { diff --git a/dependency-versions/pom.xml b/dependency-versions/pom.xml index f6f6646eb76..a9e17bbb45c 100644 --- a/dependency-versions/pom.xml +++ b/dependency-versions/pom.xml @@ -65,7 +65,7 @@ <assertj.vespa.version>3.25.3</assertj.vespa.version> <!-- Athenz dependencies. Make sure these dependencies match those in Vespa's internal repositories --> - <aws-sdk.vespa.version>1.12.674</aws-sdk.vespa.version> + <aws-sdk.vespa.version>1.12.675</aws-sdk.vespa.version> <athenz.vespa.version>1.11.53</athenz.vespa.version> <!-- Athenz END --> @@ -122,7 +122,7 @@ <mockito.vespa.version>5.11.0</mockito.vespa.version> <mojo-executor.vespa.version>2.4.0</mojo-executor.vespa.version> <netty.vespa.version>4.1.107.Final</netty.vespa.version> - <netty-tcnative.vespa.version>2.0.63.Final</netty-tcnative.vespa.version> + <netty-tcnative.vespa.version>2.0.65.Final</netty-tcnative.vespa.version> <onnxruntime.vespa.version>1.17.1</onnxruntime.vespa.version> <opennlp.vespa.version>2.3.2</opennlp.vespa.version> <opentest4j.vespa.version>1.3.0</opentest4j.vespa.version> diff --git a/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/MbusRequestContext.java b/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/MbusRequestContext.java index 180173789ae..1836f25f8d2 100644 --- a/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/MbusRequestContext.java +++ b/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/MbusRequestContext.java @@ -40,6 +40,7 @@ public class MbusRequestContext implements RequestContext, ResponseHandler { private final static Logger log = Logger.getLogger(MbusRequestContext.class.getName()); private final static CopyOnWriteHashMap<String, URI> uriCache = new CopyOnWriteHashMap<>(); + private final AtomicBoolean deserialized = new AtomicBoolean(false); private final AtomicBoolean responded = new AtomicBoolean(false); private final ProcessingFactory processingFactory; diff --git a/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/ProcessingFactory.java b/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/ProcessingFactory.java index 030f95e380b..41d7f7920ca 100644 --- a/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/ProcessingFactory.java +++ b/docproc/src/main/java/com/yahoo/docproc/jdisc/messagebus/ProcessingFactory.java @@ -81,7 +81,12 @@ class ProcessingFactory { log.fine(() -> "Unable to get document factory component '" + componentId + "' from document factory registry."); return document; } - return cdf.getDocumentCopy(document.getDataType().getName(), document, document.getId()); + try { + return cdf.getDocumentCopy(document.getDataType().getName(), document, document.getId()); + } + catch (RuntimeException e) { + throw new IllegalArgumentException("error in document with id '" + document.getId() + "'", e); + } } private ContainerDocumentConfig.Doctype getDocumentConfig(String name) { diff --git a/document/src/main/java/com/yahoo/document/datatypes/StringFieldValue.java b/document/src/main/java/com/yahoo/document/datatypes/StringFieldValue.java index 8b4b94f6bbf..d09967f973f 100644 --- a/document/src/main/java/com/yahoo/document/datatypes/StringFieldValue.java +++ b/document/src/main/java/com/yahoo/document/datatypes/StringFieldValue.java @@ -29,6 +29,9 @@ import java.util.Objects; */ public class StringFieldValue extends FieldValue { + // TODO: remove this, it's a temporary workaround for invalid data stored before unicode validation was fixed + private static final boolean replaceInvalidUnicode = System.getProperty("vespa.replace_invalid_unicode", "false").equals("true"); + private static class Factory extends PrimitiveDataType.Factory { @Override public FieldValue create() { return new StringFieldValue(); } @Override public FieldValue create(String value) { return new StringFieldValue(value); } @@ -56,16 +59,17 @@ public class StringFieldValue extends FieldValue { setValue(value); } - private static void validateTextString(String value) { + private static String validateTextString(String value) { if ( ! Text.isValidTextString(value)) { - throw new IllegalArgumentException("The string field value contains illegal code point 0x" + - Integer.toHexString(Text.validateTextString(value).getAsInt()).toUpperCase()); + if (replaceInvalidUnicode) return Text.stripInvalidCharacters(value); + else throw new IllegalArgumentException("The string field value contains illegal code point 0x" + + Integer.toHexString(Text.validateTextString(value).getAsInt()).toUpperCase()); } + return value; } private void setValue(String value) { - validateTextString(value); - this.value = value; + this.value = validateTextString(value); } /** diff --git a/searchlib/CMakeLists.txt b/searchlib/CMakeLists.txt index ffc6cf75ab0..a5453ac5273 100644 --- a/searchlib/CMakeLists.txt +++ b/searchlib/CMakeLists.txt @@ -131,6 +131,7 @@ vespa_define_module( src/tests/engine/proto_rpc_adapter src/tests/expression/attributenode src/tests/expression/current_index_setup + src/tests/expression/interpolated_document_field_lookup_node src/tests/features src/tests/features/beta src/tests/features/bm25 diff --git a/searchlib/src/tests/expression/interpolated_document_field_lookup_node/CMakeLists.txt b/searchlib/src/tests/expression/interpolated_document_field_lookup_node/CMakeLists.txt new file mode 100644 index 00000000000..267848d9468 --- /dev/null +++ b/searchlib/src/tests/expression/interpolated_document_field_lookup_node/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchlib_interpolated_document_field_lookup_node_test_app + SOURCES + interpolated_document_field_lookup_node_test.cpp + DEPENDS + searchlib_test +) +vespa_add_test(NAME searchlib_interpolated_document_field_lookup_node_test_app COMMAND searchlib_interpolated_document_field_lookup_node_test_app) diff --git a/searchlib/src/tests/expression/interpolated_document_field_lookup_node/interpolated_document_field_lookup_node_test.cpp b/searchlib/src/tests/expression/interpolated_document_field_lookup_node/interpolated_document_field_lookup_node_test.cpp new file mode 100644 index 00000000000..c131efcacb2 --- /dev/null +++ b/searchlib/src/tests/expression/interpolated_document_field_lookup_node/interpolated_document_field_lookup_node_test.cpp @@ -0,0 +1,98 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/document/fieldvalue/arrayfieldvalue.h> +#include <vespa/document/fieldvalue/document.h> +#include <vespa/document/fieldvalue/doublefieldvalue.h> +#include <vespa/document/repo/configbuilder.h> +#include <vespa/searchlib/expression/constantnode.h> +#include <vespa/searchlib/expression/floatresultnode.h> +#include <vespa/searchlib/expression/interpolated_document_field_lookup_node.h> +#include <vespa/searchlib/test/doc_builder.h> +#include <vespa/vespalib/gtest/gtest.h> + +using document::DataType; +using document::Document; +using document::DoubleFieldValue; +using search::expression::ConstantNode; +using search::expression::DocumentAccessorNode; +using search::expression::FloatResultNode; +using search::expression::InterpolatedDocumentFieldLookupNode; +using search::test::DocBuilder; + +const vespalib::string field_name("f"); + +struct Fixture { + DocBuilder _builder; + std::unique_ptr<Document> _doc; + std::unique_ptr<DocumentAccessorNode> _node; + + Fixture(); + ~Fixture(); + + Fixture& setup_doc(std::vector<double> field_value); + Fixture& setup_node(double lookup_value); + double evaluate(); +}; + +Fixture::Fixture() + : _builder([](auto& header) + { header.addField(field_name, document::config_builder::Array(DataType::T_DOUBLE)); }), + _doc(_builder.make_document("id:ns:searchdocument::0")), + _node() +{ +} + +Fixture::~Fixture() = default; + + +Fixture& +Fixture::setup_doc(std::vector<double> field_value) +{ + auto array = _builder.make_array(field_name); + for (auto& v : field_value) { + array.add(DoubleFieldValue(v)); + } + _doc->setValue(field_name, array); + return *this; +} + +Fixture& +Fixture::setup_node(double lookup_value) +{ + _node = std::make_unique<InterpolatedDocumentFieldLookupNode>(field_name, std::make_unique<ConstantNode>(std::make_unique<FloatResultNode>(lookup_value))); + _node->prepare(true); + _node->setDocType(_doc->getType()); + _node->setDoc(*_doc); + return *this; +} + +double +Fixture::evaluate() +{ + EXPECT_TRUE(_node->execute()); + return _node->getResult()->getFloat(); +} + + +class InterpolatedDocumentFieldLookupNodeTest : public Fixture, + public ::testing::Test +{ +protected: + InterpolatedDocumentFieldLookupNodeTest(); + ~InterpolatedDocumentFieldLookupNodeTest() override; +}; + +InterpolatedDocumentFieldLookupNodeTest::InterpolatedDocumentFieldLookupNodeTest() = default; +InterpolatedDocumentFieldLookupNodeTest::~InterpolatedDocumentFieldLookupNodeTest() = default; + +TEST_F(InterpolatedDocumentFieldLookupNodeTest, test_interpolated_lookup_in_document_field) +{ + EXPECT_EQ(0.0, setup_doc({ 2, 10 }).setup_node(1.0).evaluate()); + EXPECT_EQ(0.0, setup_node(2.0).evaluate()); + EXPECT_EQ(0.3125, setup_node(4.5).evaluate()); + EXPECT_EQ(1.0, setup_node(10).evaluate()); + EXPECT_EQ(1.0, setup_node(11).evaluate()); + EXPECT_EQ(2.5, setup_doc({1.5, 5.25, 8.0, 14.0 }).evaluate()); +} + +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/searchlib/src/vespa/searchlib/queryeval/flow_tuning.h b/searchlib/src/vespa/searchlib/queryeval/flow_tuning.h index ce5a24d9c2f..53f2be88c1f 100644 --- a/searchlib/src/vespa/searchlib/queryeval/flow_tuning.h +++ b/searchlib/src/vespa/searchlib/queryeval/flow_tuning.h @@ -22,6 +22,8 @@ inline double array_cost(double my_est, size_t num_children) { * The following tests were executed on a machine with an Intel Xeon 2.5 GHz CPU with 48 cores and 256 Gb of memory: * ./searchlib_iterator_benchmark_test_app --gtest_filter='*analyze_term_search*' * + * TODO: Add details on OR benchmarking. + * * The benchmark summary shows the 'average ms per cost' of the different benchmark cases. * The following constants and formulas were derived to balance 'average ms per cost' to be similar * across the different benchmark cases. @@ -29,7 +31,7 @@ inline double array_cost(double my_est, size_t num_children) { // Non-strict cost of lookup based matching in an attribute (not fast-search). inline double lookup_cost(size_t num_indirections) { - return 1.0 + (num_indirections * 4.0); + return 1.0 + (num_indirections * 1.0); } // Strict cost of lookup based matching in an attribute (not fast-search). @@ -39,7 +41,7 @@ inline double lookup_strict_cost(size_t num_indirections) { // Non-strict cost of matching in a btree posting list (e.g. fast-search attribute or memory index field). inline double btree_cost() { - return 7.0; + return 1.0; } // Strict cost of matching in a btree posting list (e.g. fast-search attribute or memory index field). @@ -49,7 +51,7 @@ inline double btree_strict_cost(double my_est) { // Non-strict cost of matching in a disk index posting list. inline double disk_index_cost() { - return 12.0; + return 1.5; } // Strict cost of matching in a disk index posting list. diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp index 52dd1c52fc2..dc58b607848 100644 --- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp +++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp @@ -55,15 +55,24 @@ using vespalib::string; namespace { -std::optional<vespalib::string> +vespalib::stringref extract_search_cluster(const vdslib::Parameters& params) { - Parameters::ValueRef searchClusterBlob; - if (params.lookup("searchcluster", searchClusterBlob)) { - LOG(spam, "Received searchcluster blob of %zd bytes", searchClusterBlob.size()); - return {{searchClusterBlob.data(), searchClusterBlob.size()}}; + Parameters::ValueRef searchCluster; + if (params.lookup("searchcluster", searchCluster)) { + LOG(spam, "Received searchcluster blob of %zd bytes", searchCluster.size()); } - return std::nullopt; + return searchCluster; +} + +vespalib::stringref +extract_schema(const vdslib::Parameters& params) +{ + Parameters::ValueRef schema; + if (params.lookup("schema", schema)) { + LOG(spam, "Received searchcluster blob of %zd bytes", schema.size()); + } + return schema; } std::shared_ptr<const SearchEnvironmentSnapshot> @@ -71,8 +80,11 @@ get_search_environment_snapshot(VisitorEnvironment& v_env, const Parameters& par { auto& env = dynamic_cast<SearchEnvironment&>(v_env); auto search_cluster = extract_search_cluster(params); - if (search_cluster.has_value()) { - return env.get_snapshot(search_cluster.value()); + if ( !search_cluster.empty()) { + auto schema = extract_schema(params); + return schema.empty() + ? env.get_snapshot(search_cluster) + : env.get_snapshot(search_cluster + "/" + schema); } return {}; } diff --git a/vespalib/src/tests/btree/CMakeLists.txt b/vespalib/src/tests/btree/CMakeLists.txt index bf4edc9e5e9..3b6f012a888 100644 --- a/vespalib/src/tests/btree/CMakeLists.txt +++ b/vespalib/src/tests/btree/CMakeLists.txt @@ -20,6 +20,7 @@ vespa_add_executable(vespalib_btreeaggregation_test_app TEST btreeaggregation_test.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_btreeaggregation_test_app COMMAND vespalib_btreeaggregation_test_app COST 30) vespa_add_executable(vespalib_iteratespeed_app diff --git a/vespalib/src/tests/btree/btreeaggregation_test.cpp b/vespalib/src/tests/btree/btreeaggregation_test.cpp index b33242b918e..34c1ca76772 100644 --- a/vespalib/src/tests/btree/btreeaggregation_test.cpp +++ b/vespalib/src/tests/btree/btreeaggregation_test.cpp @@ -16,8 +16,8 @@ #include <vespa/vespalib/btree/btreeaggregator.hpp> #include <vespa/vespalib/datastore/buffer_type.hpp> #include <vespa/vespalib/datastore/compaction_strategy.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/test/btree/btree_printer.h> -#include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/rand48.h> #include <iostream> @@ -216,115 +216,95 @@ cleanup(GenerationHandler & g, cleanup(g, m); } -class Test : public vespalib::TestApp { -private: +class BTreeAggregationTest : public ::testing::Test { +protected: + BTreeAggregationTest(); + ~BTreeAggregationTest() override; template <typename Tree> bool assertTree(const std::string & exp, const Tree &t); template <typename Tree> bool - assertAggregated(const MockTree &m, const Tree &t); + assertAggregated(const MockTree &m, const Tree &t, const vespalib::string& label); template <typename TreeStore> bool - assertAggregated(const MockTree &m, const TreeStore &s, EntryRef ref); + assertAggregated(const MockTree &m, const TreeStore &s, EntryRef ref, const vespalib::string& label); void buildSubTree(const std::vector<LeafPair> &sub, size_t numEntries); - - void requireThatNodeInsertWorks(); - void keys_are_aggregated_correctly_on_node_insertions(); - void requireThatNodeSplitInsertWorks(); - void keys_are_aggregated_correctly_when_node_split_on_insert(); - void requireThatTreeInsertWorks(); - void requireThatNodeStealWorks(); - void requireThatNodeRemoveWorks(); - void keys_are_aggregated_correctly_on_node_removal(); - void requireThatWeCanInsertAndRemoveFromTree(); - void requireThatSortedTreeInsertWorks(); - void requireThatCornerCaseTreeFindWorks(); - void requireThatBasicTreeIteratorWorks(); - void requireThatTreeIteratorAssignWorks(); - void requireThatUpdateOfKeyWorks(); - void requireThatUpdateOfDataWorks(); - void requireThatFrozenViewProvidesAggregatedValues(); - - void - requireThatSmallNodesWorks(); -public: - int Main() override; }; +BTreeAggregationTest::BTreeAggregationTest() = default; +BTreeAggregationTest::~BTreeAggregationTest() = default; template<typename Tree> bool -Test::assertTree(const std::string &exp, const Tree &t) +BTreeAggregationTest::assertTree(const std::string &exp, const Tree &t) { std::stringstream ss; test::BTreePrinter<std::stringstream, typename Tree::NodeAllocatorType> printer(ss, t.getAllocator()); printer.print(t.getRoot()); - if (!EXPECT_EQUAL(exp, ss.str())) return false; - return true; + bool failed = false; + EXPECT_EQ(exp, ss.str()) << (failed = true, ""); + return !failed; } template <typename Tree> bool -Test::assertAggregated(const MockTree &m, const Tree &t) +BTreeAggregationTest::assertAggregated(const MockTree &m, const Tree &t, const vespalib::string& label) { + SCOPED_TRACE(label); const MinMaxAggregated &ta(t.getAggregated()); + bool failed = false; if (t.getRoot().valid()) { - return - EXPECT_FALSE(m._rtree.empty()) && - EXPECT_EQUAL(m._rtree.rbegin()->first, - ta.getMax()) && - EXPECT_EQUAL(m._rtree.begin()->first, - ta.getMin()); + EXPECT_FALSE(m._rtree.empty()) << (failed = true, ""); + if (failed) { + return false; + } + EXPECT_EQ(m._rtree.rbegin()->first, ta.getMax()) << (failed = true, ""); + EXPECT_EQ(m._rtree.begin()->first, ta.getMin()) << (failed = true, ""); } else { - return EXPECT_TRUE(m._rtree.empty()) && - EXPECT_EQUAL(std::numeric_limits<int32_t>::min(), - ta.getMax()) && - EXPECT_EQUAL(std::numeric_limits<int32_t>::max(), - ta.getMin()); + EXPECT_TRUE(m._rtree.empty()) << (failed = true, ""); + EXPECT_EQ(std::numeric_limits<int32_t>::min(), ta.getMax()) << (failed = true, ""); + EXPECT_EQ(std::numeric_limits<int32_t>::max(), ta.getMin()) << (failed = true, ""); } + return !failed; } template <typename TreeStore> bool -Test::assertAggregated(const MockTree &m, const TreeStore &s, EntryRef ref) +BTreeAggregationTest::assertAggregated(const MockTree &m, const TreeStore &s, EntryRef ref, const vespalib::string& label) { + SCOPED_TRACE(label); typename TreeStore::Iterator i(s.begin(ref)); MinMaxAggregated sa(s.getAggregated(ref)); const MinMaxAggregated &ia(i.getAggregated()); + bool failed = false; if (ref.valid()) { - return - EXPECT_FALSE(m._rtree.empty()) && - EXPECT_EQUAL(m._rtree.rbegin()->first, - ia.getMax()) && - EXPECT_EQUAL(m._rtree.begin()->first, - ia.getMin()) && - EXPECT_EQUAL(m._rtree.rbegin()->first, - sa.getMax()) && - EXPECT_EQUAL(m._rtree.begin()->first, - sa.getMin()); + EXPECT_FALSE(m._rtree.empty()) << (failed = true, ""); + if (failed) { + return false; + } + EXPECT_EQ(m._rtree.rbegin()->first, ia.getMax()) << (failed = true, ""); + EXPECT_EQ(m._rtree.begin()->first, ia.getMin()) << (failed = true, ""); + EXPECT_EQ(m._rtree.rbegin()->first, sa.getMax()) << (failed = true, ""); + EXPECT_EQ(m._rtree.begin()->first, sa.getMin()) << (failed = true, ""); } else { - return EXPECT_TRUE(m._rtree.empty()) && - EXPECT_EQUAL(std::numeric_limits<int32_t>::min(), - ia.getMax()) && - EXPECT_EQUAL(std::numeric_limits<int32_t>::max(), - ia.getMin()) && - EXPECT_EQUAL(std::numeric_limits<int32_t>::min(), - sa.getMax()) && - EXPECT_EQUAL(std::numeric_limits<int32_t>::max(), - sa.getMin()); + EXPECT_TRUE(m._rtree.empty()) << (failed = true, ""); + EXPECT_EQ(std::numeric_limits<int32_t>::min(), ia.getMax()) << (failed = true, ""); + EXPECT_EQ(std::numeric_limits<int32_t>::max(), ia.getMin()) << (failed = true, ""); + EXPECT_EQ(std::numeric_limits<int32_t>::min(), sa.getMax()) << (failed =true, ""); + EXPECT_EQ(std::numeric_limits<int32_t>::max(), sa.getMin()) << (failed =true, ""); } + return !failed; } -void -Test::requireThatNodeInsertWorks() +TEST_F(BTreeAggregationTest, require_that_node_insert_works) { MyTree t; t.insert(20, 102); @@ -336,7 +316,8 @@ Test::requireThatNodeInsertWorks() EXPECT_TRUE(assertTree("{{10:101,20:102,30:103,40:104[min=101,max=104]}}", t)); } -void Test::keys_are_aggregated_correctly_on_node_insertions() { +TEST_F(BTreeAggregationTest, keys_are_aggregated_correctly_on_node_insertions) +{ MyKeyAggrTree t; t.insert(20, 102); EXPECT_TRUE(assertTree("{{20:102[min=20,max=20]}}", t)); @@ -367,8 +348,7 @@ populateLeafNode(Tree &t) populateTree(t, 4, 2); } -void -Test::requireThatNodeSplitInsertWorks() +TEST_F(BTreeAggregationTest, require_that_node_split_insert_works) { { // new entry in current node MyTree t; @@ -396,7 +376,8 @@ Test::requireThatNodeSplitInsertWorks() } } -void Test::keys_are_aggregated_correctly_when_node_split_on_insert() { +TEST_F(BTreeAggregationTest, keys_are_aggregated_correctly_when_node_split_on_insert) +{ { // new entry in current node MyKeyAggrTree t; populateLeafNode(t); @@ -423,8 +404,7 @@ void Test::keys_are_aggregated_correctly_when_node_split_on_insert() { } } -void -Test::requireThatTreeInsertWorks() +TEST_F(BTreeAggregationTest, require_that_tree_insert_works) { { // multi level node split MyTree t; @@ -523,8 +503,7 @@ struct BTreeStealTraits } -void -Test::requireThatNodeStealWorks() +TEST_F(BTreeAggregationTest, require_that_node_steal_works) { typedef BTree<MyKey, int32_t, btree::MinMaxAggregated, @@ -602,8 +581,7 @@ Test::requireThatNodeStealWorks() } } -void -Test::requireThatNodeRemoveWorks() +TEST_F(BTreeAggregationTest, require_that_node_remove_works) { MyTree t; populateLeafNode(t); @@ -615,7 +593,8 @@ Test::requireThatNodeRemoveWorks() EXPECT_TRUE(assertTree("{{5:105[min=105,max=105]}}", t)); } -void Test::keys_are_aggregated_correctly_on_node_removal() { +TEST_F(BTreeAggregationTest, keys_are_aggregated_correctly_on_node_removal) +{ MyKeyAggrTree t; populateLeafNode(t); t.remove(3); @@ -640,7 +619,7 @@ generateData(std::vector<LeafPair> & data, size_t numEntries) } void -Test::buildSubTree(const std::vector<LeafPair> &sub, +BTreeAggregationTest::buildSubTree(const std::vector<LeafPair> &sub, size_t numEntries) { GenerationHandler g; @@ -660,31 +639,31 @@ Test::buildSubTree(const std::vector<LeafPair> &sub, assert(numEntries == tree.size()); assert(tree.isValid()); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); - EXPECT_EQUAL(numEntries, tree.size()); + EXPECT_TRUE(assertAggregated(mock, tree, "build_sub_tree")); + EXPECT_EQ(numEntries, tree.size()); EXPECT_TRUE(tree.isValid()); MyTree::Iterator itr = tree.begin(); MyTree::Iterator ritr = itr; if (numEntries > 0) { EXPECT_TRUE(ritr.valid()); - EXPECT_EQUAL(0u, ritr.position()); + EXPECT_EQ(0u, ritr.position()); --ritr; EXPECT_TRUE(!ritr.valid()); - EXPECT_EQUAL(numEntries, ritr.position()); + EXPECT_EQ(numEntries, ritr.position()); --ritr; EXPECT_TRUE(ritr.valid()); - EXPECT_EQUAL(numEntries - 1, ritr.position()); + EXPECT_EQ(numEntries - 1, ritr.position()); } else { EXPECT_TRUE(!ritr.valid()); - EXPECT_EQUAL(0u, ritr.position()); + EXPECT_EQ(0u, ritr.position()); --ritr; EXPECT_TRUE(!ritr.valid()); - EXPECT_EQUAL(0u, ritr.position()); + EXPECT_EQ(0u, ritr.position()); } for (size_t i = 0; i < numEntries; ++i) { EXPECT_TRUE(itr.valid()); - EXPECT_EQUAL(sorted[i].first, itr.getKey()); - EXPECT_EQUAL(sorted[i].second, itr.getData()); + EXPECT_EQ(sorted[i].first, itr.getKey()); + EXPECT_EQ(sorted[i].second, itr.getData()); ++itr; } EXPECT_TRUE(!itr.valid()); @@ -693,22 +672,21 @@ Test::buildSubTree(const std::vector<LeafPair> &sub, --ritr; for (size_t i = 0; i < numEntries; ++i) { EXPECT_TRUE(ritr.valid()); - EXPECT_EQUAL(sorted[numEntries - 1 - i].first, ritr.getKey()); - EXPECT_EQUAL(sorted[numEntries - 1 - i].second, ritr.getData()); + EXPECT_EQ(sorted[numEntries - 1 - i].first, ritr.getKey()); + EXPECT_EQ(sorted[numEntries - 1 - i].second, ritr.getData()); --ritr; } EXPECT_TRUE(!ritr.valid()); } -void -Test::requireThatWeCanInsertAndRemoveFromTree() +TEST_F(BTreeAggregationTest, require_that_we_can_insert_and_remove_from_tree) { GenerationHandler g; MyTree tree; MockTree mock; std::vector<LeafPair> exp; std::vector<LeafPair> sorted; - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); + EXPECT_TRUE(assertAggregated(mock, tree, "insert_and_remove_1")); size_t numEntries = 1000; generateData(exp, numEntries); sorted = exp; @@ -722,15 +700,15 @@ Test::requireThatWeCanInsertAndRemoveFromTree() EXPECT_TRUE(tree.insert(num, val)); EXPECT_TRUE(!tree.insert(num, val)); mock.insert(num, val); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); + EXPECT_TRUE(assertAggregated(mock, tree, "insert_and_remove_2")); for (size_t j = 0; j <= i; ++j) { //LOG(info, "find[%zu](%d)", j, exp[j].first._val); MyTree::Iterator itr = tree.find(exp[j].first); EXPECT_TRUE(itr.valid()); - EXPECT_EQUAL(exp[j].first, itr.getKey()); - EXPECT_EQUAL(exp[j].second, itr.getData()); + EXPECT_EQ(exp[j].first, itr.getKey()); + EXPECT_EQ(exp[j].second, itr.getData()); } - EXPECT_EQUAL(i + 1u, tree.size()); + EXPECT_EQ(i + 1u, tree.size()); EXPECT_TRUE(tree.isValid()); buildSubTree(exp, i + 1); } @@ -745,36 +723,36 @@ Test::requireThatWeCanInsertAndRemoveFromTree() ++itre; if (numEntries > 0) { EXPECT_TRUE(ritr.valid()); - EXPECT_EQUAL(0u, ritr.position()); + EXPECT_EQ(0u, ritr.position()); --ritr; EXPECT_TRUE(!ritr.valid()); - EXPECT_EQUAL(numEntries, ritr.position()); + EXPECT_EQ(numEntries, ritr.position()); --ritr; EXPECT_TRUE(ritr.valid()); - EXPECT_EQUAL(numEntries - 1, ritr.position()); + EXPECT_EQ(numEntries - 1, ritr.position()); } else { EXPECT_TRUE(!ritr.valid()); - EXPECT_EQUAL(0u, ritr.position()); + EXPECT_EQ(0u, ritr.position()); --ritr; EXPECT_TRUE(!ritr.valid()); - EXPECT_EQUAL(0u, ritr.position()); + EXPECT_EQ(0u, ritr.position()); } MyTree::Iterator pitr = itr; for (size_t i = 0; i < numEntries; ++i) { ssize_t si = i; ssize_t sileft = numEntries - i; EXPECT_TRUE(itr.valid()); - EXPECT_EQUAL(i, itr.position()); - EXPECT_EQUAL(sileft, itre - itr); - EXPECT_EQUAL(-sileft, itr - itre); - EXPECT_EQUAL(sileft, itre2 - itr); - EXPECT_EQUAL(-sileft, itr - itre2); - EXPECT_EQUAL(si, itr - tree.begin()); - EXPECT_EQUAL(-si, tree.begin() - itr); - EXPECT_EQUAL(i != 0, itr - pitr); - EXPECT_EQUAL(-(i != 0), pitr - itr); - EXPECT_EQUAL(sorted[i].first, itr.getKey()); - EXPECT_EQUAL(sorted[i].second, itr.getData()); + EXPECT_EQ(i, itr.position()); + EXPECT_EQ(sileft, itre - itr); + EXPECT_EQ(-sileft, itr - itre); + EXPECT_EQ(sileft, itre2 - itr); + EXPECT_EQ(-sileft, itr - itre2); + EXPECT_EQ(si, itr - tree.begin()); + EXPECT_EQ(-si, tree.begin() - itr); + EXPECT_EQ(i != 0, itr - pitr); + EXPECT_EQ(-(i != 0), pitr - itr); + EXPECT_EQ(sorted[i].first, itr.getKey()); + EXPECT_EQ(sorted[i].second, itr.getData()); pitr = itr; ++itr; ritr = itr; @@ -783,12 +761,12 @@ Test::requireThatWeCanInsertAndRemoveFromTree() EXPECT_TRUE(ritr == pitr); } EXPECT_TRUE(!itr.valid()); - EXPECT_EQUAL(numEntries, itr.position()); + EXPECT_EQ(numEntries, itr.position()); ssize_t sNumEntries = numEntries; - EXPECT_EQUAL(sNumEntries, itr - tree.begin()); - EXPECT_EQUAL(-sNumEntries, tree.begin() - itr); - EXPECT_EQUAL(1, itr - pitr); - EXPECT_EQUAL(-1, pitr - itr); + EXPECT_EQ(sNumEntries, itr - tree.begin()); + EXPECT_EQ(-sNumEntries, tree.begin() - itr); + EXPECT_EQ(1, itr - pitr); + EXPECT_EQ(-1, pitr - itr); } // compact full tree by calling incremental compaction methods in a loop { @@ -818,52 +796,50 @@ Test::requireThatWeCanInsertAndRemoveFromTree() EXPECT_TRUE(!tree.remove(num)); EXPECT_TRUE(tree.isValid()); mock.erase(num); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); + EXPECT_TRUE(assertAggregated(mock, tree, "insert_and_remove3")); for (size_t j = i + 1; j < numEntries; ++j) { MyTree::Iterator itr = tree.find(exp[j].first); EXPECT_TRUE(itr.valid()); - EXPECT_EQUAL(exp[j].first, itr.getKey()); - EXPECT_EQUAL(exp[j].second, itr.getData()); + EXPECT_EQ(exp[j].first, itr.getKey()); + EXPECT_EQ(exp[j].second, itr.getData()); } - EXPECT_EQUAL(numEntries - 1 - i, tree.size()); + EXPECT_EQ(numEntries - 1 - i, tree.size()); } } -void -Test::requireThatSortedTreeInsertWorks() +TEST_F(BTreeAggregationTest, require_that_sorted_tree_insert_works) { { MyTree tree; MockTree mock; - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); + EXPECT_TRUE(assertAggregated(mock, tree, "sorted_tree_insert1")); for (int i = 0; i < 1000; ++i) { EXPECT_TRUE(tree.insert(i, toVal(i))); mock.insert(i, toVal(i)); MyTree::Iterator itr = tree.find(i); EXPECT_TRUE(itr.valid()); - EXPECT_EQUAL(toVal(i), itr.getData()); + EXPECT_EQ(toVal(i), itr.getData()); EXPECT_TRUE(tree.isValid()); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); + EXPECT_TRUE(assertAggregated(mock, tree, "sorted_tree_insert2")); } } { MyTree tree; MockTree mock; - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); + EXPECT_TRUE(assertAggregated(mock, tree, "sorted_tree_insert3")); for (int i = 1000; i > 0; --i) { EXPECT_TRUE(tree.insert(i, toVal(i))); mock.insert(i, toVal(i)); MyTree::Iterator itr = tree.find(i); EXPECT_TRUE(itr.valid()); - EXPECT_EQUAL(toVal(i), itr.getData()); + EXPECT_EQ(toVal(i), itr.getData()); EXPECT_TRUE(tree.isValid()); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, tree))); + EXPECT_TRUE(assertAggregated(mock, tree, "sorted_tree_insert4")); } } } -void -Test::requireThatCornerCaseTreeFindWorks() +TEST_F(BTreeAggregationTest, require_that_corner_case_tree_find_works) { GenerationHandler g; MyTree tree; @@ -874,8 +850,7 @@ Test::requireThatCornerCaseTreeFindWorks() EXPECT_TRUE(!tree.find(1000).valid()); // higher than highest } -void -Test::requireThatBasicTreeIteratorWorks() +TEST_F(BTreeAggregationTest, require_that_basic_tree_iterator_works) { GenerationHandler g; MyTree tree; @@ -890,27 +865,24 @@ Test::requireThatBasicTreeIteratorWorks() size_t ei = 0; MyTree::Iterator itr = tree.begin(); MyTree::Iterator ritr; - EXPECT_EQUAL(1000u, itr.size()); + EXPECT_EQ(1000u, itr.size()); for (; itr.valid(); ++itr) { //LOG(info, "itr(%d, %s)", itr.getKey(), itr.getData().c_str()); - EXPECT_EQUAL(UNWRAP(exp[ei].first), UNWRAP(itr.getKey())); - EXPECT_EQUAL(exp[ei].second, itr.getData()); + EXPECT_EQ(UNWRAP(exp[ei].first), UNWRAP(itr.getKey())); + EXPECT_EQ(exp[ei].second, itr.getData()); ei++; ritr = itr; } - EXPECT_EQUAL(numEntries, ei); + EXPECT_EQ(numEntries, ei); for (; ritr.valid(); --ritr) { --ei; //LOG(info, "itr(%d, %s)", itr.getKey(), itr.getData().c_str()); - EXPECT_EQUAL(UNWRAP(exp[ei].first), UNWRAP(ritr.getKey())); - EXPECT_EQUAL(exp[ei].second, ritr.getData()); + EXPECT_EQ(UNWRAP(exp[ei].first), UNWRAP(ritr.getKey())); + EXPECT_EQ(exp[ei].second, ritr.getData()); } } - - -void -Test::requireThatTreeIteratorAssignWorks() +TEST_F(BTreeAggregationTest, require_that_tree_iterator_assign_works) { GenerationHandler g; MyTree tree; @@ -923,9 +895,9 @@ Test::requireThatTreeIteratorAssignWorks() EXPECT_TRUE(itr == itr2); int expNum = i; for (; itr2.valid(); ++itr2) { - EXPECT_EQUAL(expNum++, UNWRAP(itr2.getKey())); + EXPECT_EQ(expNum++, UNWRAP(itr2.getKey())); } - EXPECT_EQUAL(1000, expNum); + EXPECT_EQ(1000, expNum); } } @@ -940,8 +912,7 @@ struct UpdKeyComp { } }; -void -Test::requireThatUpdateOfKeyWorks() +TEST_F(BTreeAggregationTest, require_that_update_of_key_works) { using UpdKeyTree = BTree<int, BTreeNoLeafData, btree::NoAggregated, UpdKeyComp &>; using UpdKeyTreeIterator = UpdKeyTree::Iterator; @@ -951,7 +922,7 @@ Test::requireThatUpdateOfKeyWorks() for (int i = 0; i < 1000; i+=2) { EXPECT_TRUE(t.insert(i, BTreeNoLeafData(), cmp1)); } - EXPECT_EQUAL(0u, cmp1._numErrors); + EXPECT_EQ(0u, cmp1._numErrors); for (int i = 0; i < 1000; i+=2) { UpdKeyTreeIterator itr = t.find(i, cmp1); itr.writeKey(i + 1); @@ -961,23 +932,22 @@ Test::requireThatUpdateOfKeyWorks() UpdKeyTreeIterator itr = t.find(i, cmp2); EXPECT_TRUE(itr.valid()); } - EXPECT_EQUAL(0u, cmp2._numErrors); + EXPECT_EQ(0u, cmp2._numErrors); } -void -Test::requireThatUpdateOfDataWorks() +TEST_F(BTreeAggregationTest, require_that_update_of_data_works) { GenerationHandler g; MyTree t; MockTree mock; MyAggrCalc ac; MyTree::NodeAllocatorType &manager = t.getAllocator(); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, t))); + EXPECT_TRUE(assertAggregated(mock, t, "update_data1")); for (int i = 0; i < 1000; i+=2) { EXPECT_TRUE(t.insert(i, toVal(i))); mock.insert(i, toVal(i)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, t))); + EXPECT_TRUE(assertAggregated(mock, t, "udate_data2")); } freezeTree(g, manager); for (int i = 0; i < 1000; i+=2) { @@ -985,31 +955,31 @@ Test::requireThatUpdateOfDataWorks() MyTree::Iterator itr2 = itr; t.thaw(itr); itr.updateData(toHighVal(i), ac); - EXPECT_EQUAL(toHighVal(i), itr.getData()); - EXPECT_EQUAL(toVal(i), itr2.getData()); + EXPECT_EQ(toHighVal(i), itr.getData()); + EXPECT_EQ(toVal(i), itr2.getData()); mock.erase(i); mock.insert(i, toHighVal(i)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, t))); + EXPECT_TRUE(assertAggregated(mock, t, "update_data3")); freezeTree(g, manager); itr = t.find(i); itr2 = itr; t.thaw(itr); itr.updateData(toLowVal(i), ac); - EXPECT_EQUAL(toLowVal(i), itr.getData()); - EXPECT_EQUAL(toHighVal(i), itr2.getData()); + EXPECT_EQ(toLowVal(i), itr.getData()); + EXPECT_EQ(toHighVal(i), itr2.getData()); mock.erase(i); mock.insert(i, toLowVal(i)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, t))); + EXPECT_TRUE(assertAggregated(mock, t, "update_data4")); freezeTree(g, manager); itr = t.find(i); itr2 = itr; t.thaw(itr); itr.updateData(toVal(i), ac); - EXPECT_EQUAL(toVal(i), itr.getData()); - EXPECT_EQUAL(toLowVal(i), itr2.getData()); + EXPECT_EQ(toVal(i), itr.getData()); + EXPECT_EQ(toLowVal(i), itr2.getData()); mock.erase(i); mock.insert(i, toVal(i)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, t))); + EXPECT_TRUE(assertAggregated(mock, t, "update_data5")); freezeTree(g, manager); } } @@ -1030,68 +1000,67 @@ remove(MyTreeStore& s, EntryRef& root, MyTreeStore::KeyType removal) } -void -Test::requireThatSmallNodesWorks() +TEST_F(BTreeAggregationTest, require_that_small_nodes_works) { GenerationHandler g; MyTreeStore s; MockTree mock; EntryRef root; - EXPECT_EQUAL(0u, s.size(root)); + EXPECT_EQ(0u, s.size(root)); EXPECT_TRUE(s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small1")); insert(s, root, {40, toVal(40)}); mock.insert(40, toVal(40)); - EXPECT_EQUAL(1u, s.size(root)); + EXPECT_EQ(1u, s.size(root)); EXPECT_TRUE(s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small2")); insert(s, root, {20, toVal(20)}); mock.insert(20, toVal(20)); - EXPECT_EQUAL(2u, s.size(root)); + EXPECT_EQ(2u, s.size(root)); EXPECT_TRUE(s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small3")); insert(s, root, {60, toVal(60)}); mock.insert(60, toVal(60)); - EXPECT_EQUAL(3u, s.size(root)); + EXPECT_EQ(3u, s.size(root)); EXPECT_TRUE(s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small4")); insert(s, root, {50, toVal(50)}); mock.insert(50, toVal(50)); - EXPECT_EQUAL(4u, s.size(root)); + EXPECT_EQ(4u, s.size(root)); EXPECT_TRUE(s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small5")); for (uint32_t i = 0; i < 100; ++i) { insert(s, root, {int(1000 + i), 42}); mock.insert(1000 + i, 42); - EXPECT_EQUAL(5u + i, s.size(root)); - EXPECT_EQUAL(5u + i <= MyTreeStore::clusterLimit, s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_EQ(5u + i, s.size(root)); + EXPECT_EQ(5u + i <= MyTreeStore::clusterLimit, s.isSmallArray(root)); + EXPECT_TRUE(assertAggregated(mock, s, root, "small6")); } remove(s, root, 40); mock.erase(40); - EXPECT_EQUAL(103u, s.size(root)); + EXPECT_EQ(103u, s.size(root)); EXPECT_TRUE(!s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small7")); remove(s, root, 20); mock.erase(20); - EXPECT_EQUAL(102u, s.size(root)); + EXPECT_EQ(102u, s.size(root)); EXPECT_TRUE(!s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small8")); remove(s, root, 50); mock.erase(50); - EXPECT_EQUAL(101u, s.size(root)); + EXPECT_EQ(101u, s.size(root)); EXPECT_TRUE(!s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_TRUE(assertAggregated(mock, s, root, "small9")); for (uint32_t i = 0; i < 100; ++i) { remove(s, root, 1000 + i); mock.erase(1000 + i); - EXPECT_EQUAL(100 - i, s.size(root)); - EXPECT_EQUAL(100 - i <= MyTreeStore::clusterLimit, s.isSmallArray(root)); - TEST_DO(EXPECT_TRUE(assertAggregated(mock, s, root))); + EXPECT_EQ(100 - i, s.size(root)); + EXPECT_EQ(100 - i <= MyTreeStore::clusterLimit, s.isSmallArray(root)); + EXPECT_TRUE(assertAggregated(mock, s, root, "small10")); } - EXPECT_EQUAL(1u, s.size(root)); + EXPECT_EQ(1u, s.size(root)); EXPECT_TRUE(s.isSmallArray(root)); s.clear(root); @@ -1102,8 +1071,7 @@ Test::requireThatSmallNodesWorks() s.reclaim_memory(g.get_oldest_used_generation()); } -void -Test::requireThatFrozenViewProvidesAggregatedValues() +TEST_F(BTreeAggregationTest, require_that_frozen_view_provides_aggregated_values) { MyTree t; t.insert(20, 102); @@ -1114,39 +1082,13 @@ Test::requireThatFrozenViewProvidesAggregatedValues() t.getAllocator().freeze(); auto new_view = t.getFrozenView(); auto new_aggregated = new_view.getAggregated(); - EXPECT_EQUAL(new_aggregated.getMin(), 101); - EXPECT_EQUAL(new_aggregated.getMax(), 104); + EXPECT_EQ(new_aggregated.getMin(), 101); + EXPECT_EQ(new_aggregated.getMax(), 104); auto old_aggregated = old_view.getAggregated(); - EXPECT_EQUAL(old_aggregated.getMin(), std::numeric_limits<int32_t>::max()); - EXPECT_EQUAL(old_aggregated.getMax(), std::numeric_limits<int32_t>::min()); -} - -int -Test::Main() -{ - TEST_INIT("btreeaggregation_test"); - - requireThatNodeInsertWorks(); - keys_are_aggregated_correctly_on_node_insertions(); - requireThatNodeSplitInsertWorks(); - keys_are_aggregated_correctly_when_node_split_on_insert(); - requireThatTreeInsertWorks(); - requireThatNodeStealWorks(); - requireThatNodeRemoveWorks(); - keys_are_aggregated_correctly_on_node_removal(); - requireThatWeCanInsertAndRemoveFromTree(); - requireThatSortedTreeInsertWorks(); - requireThatCornerCaseTreeFindWorks(); - requireThatBasicTreeIteratorWorks(); - requireThatTreeIteratorAssignWorks(); - requireThatUpdateOfKeyWorks(); - requireThatUpdateOfDataWorks(); - TEST_DO(requireThatSmallNodesWorks()); - TEST_DO(requireThatFrozenViewProvidesAggregatedValues()); - - TEST_DONE(); + EXPECT_EQ(old_aggregated.getMin(), std::numeric_limits<int32_t>::max()); + EXPECT_EQ(old_aggregated.getMax(), std::numeric_limits<int32_t>::min()); } } -TEST_APPHOOK(vespalib::btree::Test); +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/fileheader/CMakeLists.txt b/vespalib/src/tests/fileheader/CMakeLists.txt index 1b3f527ebd7..be8e91ef414 100644 --- a/vespalib/src/tests/fileheader/CMakeLists.txt +++ b/vespalib/src/tests/fileheader/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_fileheader_test_app TEST fileheader_test.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_fileheader_test_app COMMAND vespalib_fileheader_test_app) diff --git a/vespalib/src/tests/fileheader/fileheader_test.cpp b/vespalib/src/tests/fileheader/fileheader_test.cpp index 0dfa28cb24c..db2c7f7c65d 100644 --- a/vespalib/src/tests/fileheader/fileheader_test.cpp +++ b/vespalib/src/tests/fileheader/fileheader_test.cpp @@ -1,8 +1,9 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/data/fileheader.h> #include <vespa/vespalib/data/databuffer.h> +#include <vespa/vespalib/gtest/gtest.h> +#include <vespa/vespalib/testkit/test_path.h> #include <vespa/fastos/file.h> #include <filesystem> @@ -14,63 +15,20 @@ vespalib::string fileheader_tmp("fileheader.tmp"); } -class Test : public vespalib::TestApp { -private: - void testTag(); - void testTagErrors(); - void testTagIteration(); - void testGenericHeader(); - void testBufferReader(); - void testBufferWriter(); - void testBufferAccess(); - void testFileReader(); - void testFileWriter(); - void testFileHeader(); - void testFileAlign(); - void testFileSize(); - void testReadErrors(); +class FileHeaderTest : public ::testing::Test { +protected: + FileHeaderTest(); + ~FileHeaderTest() override; bool testReadError(DataBuffer &buf, const std::string &expected); - void testWriteErrors(); - void testRewriteErrors(); - void testLayout(); - void testReadSize(bool mapped); void testReadSizeErrors(bool mapped); bool testReadSizeError(DataBuffer &buf, const std::string &expected, bool mapped); - -public: - int Main() override { - TEST_INIT("fileheader_test"); - - testTag(); TEST_FLUSH(); - testTagErrors(); TEST_FLUSH(); - testTagIteration(); TEST_FLUSH(); - testGenericHeader(); TEST_FLUSH(); - testBufferReader(); TEST_FLUSH(); - testBufferWriter(); TEST_FLUSH(); - testBufferAccess(); TEST_FLUSH(); - testFileReader(); TEST_FLUSH(); - testFileWriter(); TEST_FLUSH(); - testFileHeader(); TEST_FLUSH(); - testFileAlign(); TEST_FLUSH(); - testFileSize(); TEST_FLUSH(); - testReadErrors(); TEST_FLUSH(); - testWriteErrors(); TEST_FLUSH(); - testRewriteErrors(); TEST_FLUSH(); - testLayout(); TEST_FLUSH(); - testReadSize(false); TEST_FLUSH(); - testReadSizeErrors(false); TEST_FLUSH(); - testReadSize(true); TEST_FLUSH(); - testReadSizeErrors(true); TEST_FLUSH(); - - TEST_DONE(); - } }; -TEST_APPHOOK(Test); +FileHeaderTest::FileHeaderTest() = default; +FileHeaderTest::~FileHeaderTest() = default; -void -Test::testTag() +TEST_F(FileHeaderTest, test_tag) { { std::vector<GenericHeader::Tag> tags; @@ -81,18 +39,18 @@ Test::testTag() { GenericHeader::Tag tag = *it; for (uint32_t i = 0; i < 2; ++i) { - EXPECT_EQUAL(GenericHeader::Tag::TYPE_FLOAT, tag.getType()); - EXPECT_EQUAL("foo", tag.getName()); + EXPECT_EQ(GenericHeader::Tag::TYPE_FLOAT, tag.getType()); + EXPECT_EQ("foo", tag.getName()); EXPECT_TRUE(tag.asString().empty()); - EXPECT_APPROX(6.9, tag.asFloat(), 1E-6); - EXPECT_EQUAL(0, tag.asInteger()); + EXPECT_NEAR(6.9, tag.asFloat(), 1E-6); + EXPECT_EQ(0, tag.asInteger()); uint32_t len = tag.getSize(); DataBuffer buf(len); - EXPECT_EQUAL(len, tag.write(buf)); + EXPECT_EQ(len, tag.write(buf)); GenericHeader::Tag tmp; - EXPECT_EQUAL(len, tmp.read(buf)); + EXPECT_EQ(len, tmp.read(buf)); tag = tmp; } } @@ -111,18 +69,18 @@ Test::testTag() { GenericHeader::Tag tag = *it; for (uint32_t i = 0; i < 2; ++i) { - EXPECT_EQUAL(GenericHeader::Tag::TYPE_INTEGER, tag.getType()); - EXPECT_EQUAL("foo", tag.getName()); + EXPECT_EQ(GenericHeader::Tag::TYPE_INTEGER, tag.getType()); + EXPECT_EQ("foo", tag.getName()); EXPECT_TRUE(tag.asString().empty()); - EXPECT_EQUAL(0.0, tag.asFloat()); - EXPECT_EQUAL(69l, tag.asInteger()); + EXPECT_EQ(0.0, tag.asFloat()); + EXPECT_EQ(69l, tag.asInteger()); uint32_t len = tag.getSize(); DataBuffer buf(len); - EXPECT_EQUAL(len, tag.write(buf)); + EXPECT_EQ(len, tag.write(buf)); GenericHeader::Tag tmp; - EXPECT_EQUAL(len, tmp.read(buf)); + EXPECT_EQ(len, tmp.read(buf)); tag = tmp; } } @@ -130,35 +88,34 @@ Test::testTag() { GenericHeader::Tag tag("foo", "bar"); for (uint32_t i = 0; i < 2; ++i) { - EXPECT_EQUAL(GenericHeader::Tag::TYPE_STRING, tag.getType()); - EXPECT_EQUAL("foo", tag.getName()); - EXPECT_EQUAL("bar", tag.asString()); - EXPECT_EQUAL(0.0, tag.asFloat()); - EXPECT_EQUAL(0, tag.asInteger()); + EXPECT_EQ(GenericHeader::Tag::TYPE_STRING, tag.getType()); + EXPECT_EQ("foo", tag.getName()); + EXPECT_EQ("bar", tag.asString()); + EXPECT_EQ(0.0, tag.asFloat()); + EXPECT_EQ(0, tag.asInteger()); uint32_t len = tag.getSize(); DataBuffer buf(len); - EXPECT_EQUAL(len, tag.write(buf)); + EXPECT_EQ(len, tag.write(buf)); GenericHeader::Tag tmp; - EXPECT_EQUAL(len, tmp.read(buf)); + EXPECT_EQ(len, tmp.read(buf)); tag = tmp; } } { GenericHeader::Tag trueTag("foo", true); GenericHeader::Tag falseTag("foo", false); - EXPECT_EQUAL(GenericHeader::Tag::TYPE_INTEGER, trueTag.getType()); - EXPECT_EQUAL(GenericHeader::Tag::TYPE_INTEGER, falseTag.getType()); - EXPECT_EQUAL(1, trueTag.asInteger()); - EXPECT_EQUAL(0, falseTag.asInteger()); + EXPECT_EQ(GenericHeader::Tag::TYPE_INTEGER, trueTag.getType()); + EXPECT_EQ(GenericHeader::Tag::TYPE_INTEGER, falseTag.getType()); + EXPECT_EQ(1, trueTag.asInteger()); + EXPECT_EQ(0, falseTag.asInteger()); EXPECT_TRUE(trueTag.asBool()); EXPECT_FALSE(falseTag.asBool()); } } -void -Test::testTagErrors() +TEST_F(FileHeaderTest, test_tag_errors) { DataBuffer buf(1024); buf.writeBytes("foo", 3); @@ -170,33 +127,31 @@ Test::testTagErrors() tag.read(buf); EXPECT_TRUE(false); } catch (IllegalHeaderException &e) { - EXPECT_EQUAL("Can not deserialize empty tag.", e.getMessage()); + EXPECT_EQ("Can not deserialize empty tag.", e.getMessage()); } - EXPECT_EQUAL("bar", tag.getName()); - EXPECT_EQUAL(GenericHeader::Tag::TYPE_FLOAT, tag.getType()); - EXPECT_EQUAL(6.9, tag.asFloat()); + EXPECT_EQ("bar", tag.getName()); + EXPECT_EQ(GenericHeader::Tag::TYPE_FLOAT, tag.getType()); + EXPECT_EQ(6.9, tag.asFloat()); } -void -Test::testTagIteration() +TEST_F(FileHeaderTest, test_tag_iteration) { GenericHeader header; header.putTag(GenericHeader::Tag("foo", 6.9)); header.putTag(GenericHeader::Tag("bar", 6699)); header.putTag(GenericHeader::Tag("baz", "666999")); - EXPECT_EQUAL(3u, header.getNumTags()); - EXPECT_EQUAL("bar", header.getTag(0).getName()); - EXPECT_EQUAL("baz", header.getTag(1).getName()); - EXPECT_EQUAL("foo", header.getTag(2).getName()); + EXPECT_EQ(3u, header.getNumTags()); + EXPECT_EQ("bar", header.getTag(0).getName()); + EXPECT_EQ("baz", header.getTag(1).getName()); + EXPECT_EQ("foo", header.getTag(2).getName()); } -void -Test::testGenericHeader() +TEST_F(FileHeaderTest, test_generic_header) { GenericHeader header; EXPECT_TRUE(header.isEmpty()); - EXPECT_EQUAL(0u, header.getNumTags()); + EXPECT_EQ(0u, header.getNumTags()); EXPECT_TRUE(!header.hasTag("foo")); EXPECT_TRUE(header.getTag("foo").isEmpty()); EXPECT_TRUE(!header.hasTag("bar")); @@ -206,9 +161,9 @@ Test::testGenericHeader() header.putTag(GenericHeader::Tag("foo", 6.9)); EXPECT_TRUE(!header.isEmpty()); - EXPECT_EQUAL(1u, header.getNumTags()); + EXPECT_EQ(1u, header.getNumTags()); EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(6.9, header.getTag("foo").asFloat()); + EXPECT_EQ(6.9, header.getTag("foo").asFloat()); EXPECT_TRUE(!header.hasTag("bar")); EXPECT_TRUE(header.getTag("bar").isEmpty()); EXPECT_TRUE(!header.hasTag("baz")); @@ -216,29 +171,29 @@ Test::testGenericHeader() header.putTag(GenericHeader::Tag("bar", 6699)); EXPECT_TRUE(!header.isEmpty()); - EXPECT_EQUAL(2u, header.getNumTags()); + EXPECT_EQ(2u, header.getNumTags()); EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(6.9, header.getTag("foo").asFloat()); + EXPECT_EQ(6.9, header.getTag("foo").asFloat()); EXPECT_TRUE(header.hasTag("bar")); - EXPECT_EQUAL(6699, header.getTag("bar").asInteger()); + EXPECT_EQ(6699, header.getTag("bar").asInteger()); EXPECT_TRUE(!header.hasTag("baz")); EXPECT_TRUE(header.getTag("baz").isEmpty()); header.putTag(GenericHeader::Tag("baz", "666999")); EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(6.9, header.getTag("foo").asFloat()); + EXPECT_EQ(6.9, header.getTag("foo").asFloat()); EXPECT_TRUE(header.hasTag("bar")); - EXPECT_EQUAL(6699, header.getTag("bar").asInteger()); + EXPECT_EQ(6699, header.getTag("bar").asInteger()); EXPECT_TRUE(header.hasTag("baz")); - EXPECT_EQUAL("666999", header.getTag("baz").asString()); + EXPECT_EQ("666999", header.getTag("baz").asString()); header.removeTag("bar"); EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(6.9, header.getTag("foo").asFloat()); + EXPECT_EQ(6.9, header.getTag("foo").asFloat()); EXPECT_TRUE(!header.hasTag("bar")); EXPECT_TRUE(header.getTag("bar").isEmpty()); EXPECT_TRUE(header.hasTag("baz")); - EXPECT_EQUAL("666999", header.getTag("baz").asString()); + EXPECT_EQ("666999", header.getTag("baz").asString()); header.removeTag("foo"); EXPECT_TRUE(!header.hasTag("foo")); @@ -246,7 +201,7 @@ Test::testGenericHeader() EXPECT_TRUE(!header.hasTag("bar")); EXPECT_TRUE(header.getTag("bar").isEmpty()); EXPECT_TRUE(header.hasTag("baz")); - EXPECT_EQUAL("666999", header.getTag("baz").asString()); + EXPECT_EQ("666999", header.getTag("baz").asString()); header.removeTag("baz"); EXPECT_TRUE(!header.hasTag("foo")); @@ -257,8 +212,7 @@ Test::testGenericHeader() EXPECT_TRUE(header.getTag("baz").isEmpty()); } -void -Test::testBufferReader() +TEST_F(FileHeaderTest, test_buffer_reader) { DataBuffer src(256); for (uint32_t i = 0; i < 256; ++i) { @@ -272,15 +226,14 @@ Test::testBufferReader() while (sum < 256) { uint32_t len = (uint32_t)reader.getData(dst, 7); for (uint32_t i = 0; i < len; ++i) { - EXPECT_EQUAL(sum + i, (uint8_t)dst[i]); + EXPECT_EQ(sum + i, (uint8_t)dst[i]); } sum += len; } - EXPECT_EQUAL(256u, sum); + EXPECT_EQ(256u, sum); } -void -Test::testBufferWriter() +TEST_F(FileHeaderTest, test_buffer_writer) { DataBuffer dst(256); GenericHeader::BufferWriter writer(dst); @@ -292,20 +245,19 @@ Test::testBufferWriter() src[i] = (uint8_t)(sum + i); } uint32_t len = std::min(7u, 256 - sum); - EXPECT_EQUAL(len, (uint32_t)writer.putData(src, len)); + EXPECT_EQ(len, (uint32_t)writer.putData(src, len)); sum += len; } - EXPECT_EQUAL(256u, sum); + EXPECT_EQ(256u, sum); // flip dst for (uint32_t i = 0; i < 256; ++i) { uint8_t b = dst.readInt8(); - EXPECT_EQUAL(i, (uint32_t)b); + EXPECT_EQ(i, (uint32_t)b); } } -void -Test::testBufferAccess() +TEST_F(FileHeaderTest, test_buffer_access) { DataBuffer buf; uint32_t len; @@ -321,26 +273,25 @@ Test::testBufferAccess() len = header.getSize(); buf.ensureFree(len); GenericHeader::BufferWriter writer(buf); - EXPECT_EQUAL(len, header.write(writer)); + EXPECT_EQ(len, header.write(writer)); } { GenericHeader header; GenericHeader::BufferReader reader(buf); - EXPECT_EQUAL(len, header.read(reader)); + EXPECT_EQ(len, header.read(reader)); EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(6.9, header.getTag("foo").asFloat()); + EXPECT_EQ(6.9, header.getTag("foo").asFloat()); EXPECT_TRUE(header.hasTag("bar")); - EXPECT_EQUAL(6699, header.getTag("bar").asInteger()); + EXPECT_EQ(6699, header.getTag("bar").asInteger()); EXPECT_TRUE(header.hasTag("baz")); - EXPECT_EQUAL("666999", header.getTag("baz").asString()); + EXPECT_EQ("666999", header.getTag("baz").asString()); EXPECT_TRUE(header.hasTag("big")); - EXPECT_EQUAL(0x1234567890abcdefLL, header.getTag("big").asInteger()); + EXPECT_EQ(0x1234567890abcdefLL, header.getTag("big").asInteger()); } } -void -Test::testFileReader() +TEST_F(FileHeaderTest, test_file_reader) { { FastOS_File file; @@ -350,7 +301,7 @@ Test::testFileReader() for (uint32_t i = 0; i < 256; ++i) { buf[i] = (uint8_t)i; } - EXPECT_EQUAL(256, file.Write2(buf, 256)); + EXPECT_EQ(256, file.Write2(buf, 256)); } { FastOS_File file; @@ -362,19 +313,18 @@ Test::testFileReader() while(sum < 256) { uint32_t len = (uint32_t)reader.getData(buf, 7); for (uint32_t i = 0; i < len; ++i) { - EXPECT_EQUAL(sum + i, (uint8_t)buf[i]); + EXPECT_EQ(sum + i, (uint8_t)buf[i]); } sum += len; } - EXPECT_EQUAL(256u, sum); + EXPECT_EQ(256u, sum); ASSERT_TRUE(file.Close()); std::filesystem::remove(std::filesystem::path(fileheader_tmp)); } } -void -Test::testFileWriter() +TEST_F(FileHeaderTest, test_file_writer) { { FastOS_File file; @@ -388,19 +338,19 @@ Test::testFileWriter() src[i] = (uint8_t)(sum + i); } uint32_t len = std::min(7u, 256 - sum); - EXPECT_EQUAL(len, (uint32_t)writer.putData(src, len)); + EXPECT_EQ(len, (uint32_t)writer.putData(src, len)); sum += len; } - EXPECT_EQUAL(256u, sum); + EXPECT_EQ(256u, sum); } { FastOS_File file; ASSERT_TRUE(file.OpenReadOnly(fileheader_tmp.c_str())); uint8_t buf[256]; - EXPECT_EQUAL(256, file.Read(buf, 256)); + EXPECT_EQ(256, file.Read(buf, 256)); for (uint32_t i = 0; i < 256; ++i) { - EXPECT_EQUAL(i, (uint32_t)buf[i]); + EXPECT_EQ(i, (uint32_t)buf[i]); } ASSERT_TRUE(file.Close()); @@ -408,8 +358,7 @@ Test::testFileWriter() } } -void -Test::testFileHeader() +TEST_F(FileHeaderTest, test_file_header) { uint32_t len = 0; { @@ -421,60 +370,58 @@ Test::testFileHeader() FastOS_File file; ASSERT_TRUE(file.OpenWriteOnlyTruncate(fileheader_tmp.c_str())); len = header.writeFile(file); - EXPECT_EQUAL(len, header.getSize()); + EXPECT_EQ(len, header.getSize()); } { FastOS_File file; ASSERT_TRUE(file.OpenReadWrite(fileheader_tmp.c_str())); FileHeader header; - EXPECT_EQUAL(len, header.readFile(file)); - EXPECT_EQUAL(len, header.getSize()); + EXPECT_EQ(len, header.readFile(file)); + EXPECT_EQ(len, header.getSize()); EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(6.9, header.getTag("foo").asFloat()); + EXPECT_EQ(6.9, header.getTag("foo").asFloat()); EXPECT_TRUE(header.hasTag("bar")); - EXPECT_EQUAL(6699, header.getTag("bar").asInteger()); + EXPECT_EQ(6699, header.getTag("bar").asInteger()); EXPECT_TRUE(header.hasTag("baz")); - EXPECT_EQUAL("666999", header.getTag("baz").asString()); + EXPECT_EQ("666999", header.getTag("baz").asString()); header.putTag(FileHeader::Tag("foo", 9.6)); header.putTag(FileHeader::Tag("bar", 9966)); header.putTag(FileHeader::Tag("baz", "999666")); - EXPECT_EQUAL(len, header.getSize()); - EXPECT_EQUAL(len, header.rewriteFile(file)); + EXPECT_EQ(len, header.getSize()); + EXPECT_EQ(len, header.rewriteFile(file)); } { FileHeader header; FastOS_File file; ASSERT_TRUE(file.OpenReadOnly(fileheader_tmp.c_str())); - EXPECT_EQUAL(len, header.readFile(file)); - EXPECT_EQUAL(len, header.getSize()); + EXPECT_EQ(len, header.readFile(file)); + EXPECT_EQ(len, header.getSize()); ASSERT_TRUE(file.Close()); std::filesystem::remove(std::filesystem::path(fileheader_tmp)); EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(9.6, header.getTag("foo").asFloat()); + EXPECT_EQ(9.6, header.getTag("foo").asFloat()); EXPECT_TRUE(header.hasTag("bar")); - EXPECT_EQUAL(9966, header.getTag("bar").asInteger()); + EXPECT_EQ(9966, header.getTag("bar").asInteger()); EXPECT_TRUE(header.hasTag("baz")); - EXPECT_EQUAL("999666", header.getTag("baz").asString()); + EXPECT_EQ("999666", header.getTag("baz").asString()); } } -void -Test::testFileAlign() +TEST_F(FileHeaderTest, test_file_align) { for (uint32_t alignTo = 1; alignTo < 16; ++alignTo) { FileHeader header(alignTo); header.putTag(FileHeader::Tag("foo", "bar")); - EXPECT_EQUAL(0u, header.getSize() % alignTo); + EXPECT_EQ(0u, header.getSize() % alignTo); } } -void -Test::testFileSize() +TEST_F(FileHeaderTest, test_file_size) { for (uint32_t minSize = 0; minSize < 512; ++minSize) { FileHeader header(1u, minSize); @@ -483,8 +430,7 @@ Test::testFileSize() } } -void -Test::testReadErrors() +TEST_F(FileHeaderTest, test_read_errors) { { DataBuffer buf; @@ -524,7 +470,7 @@ Test::testReadErrors() } bool -Test::testReadError(DataBuffer &buf, const std::string &expected) +FileHeaderTest::testReadError(DataBuffer &buf, const std::string &expected) { GenericHeader header; header.putTag(GenericHeader::Tag("foo", "bar")); @@ -534,21 +480,22 @@ Test::testReadError(DataBuffer &buf, const std::string &expected) EXPECT_TRUE(false); return false; } catch (IllegalHeaderException &e) { - if (!EXPECT_EQUAL(expected, e.getMessage())) { + bool failed = false; + EXPECT_EQ(expected, e.getMessage()) << (failed = true, ""); + if (failed) { return false; } } - if (!EXPECT_EQUAL(1u, header.getNumTags())) { + bool failed = false; + EXPECT_EQ(1u, header.getNumTags()) << (failed = true, ""); + if (failed) { return false; } - if (!EXPECT_EQUAL("bar", header.getTag("foo").asString())) { - return false; - } - return true; + EXPECT_EQ("bar", header.getTag("foo").asString()) << (failed = true, ""); + return !failed; } -void -Test::testWriteErrors() +TEST_F(FileHeaderTest, test_write_errors) { GenericHeader header; header.putTag(GenericHeader::Tag("foo", 69)); @@ -562,15 +509,14 @@ Test::testWriteErrors() header.write(writer); EXPECT_TRUE(false); } catch (IllegalHeaderException &e) { - EXPECT_EQUAL("Failed to write header.", e.getMessage()); + EXPECT_EQ("Failed to write header.", e.getMessage()); } EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(69, header.getTag("foo").asInteger()); + EXPECT_EQ(69, header.getTag("foo").asInteger()); } -void -Test::testRewriteErrors() +TEST_F(FileHeaderTest, test_rewrite_errors) { FileHeader header; header.putTag(FileHeader::Tag("foo", "bar")); @@ -579,7 +525,7 @@ Test::testRewriteErrors() { FastOS_File file; ASSERT_TRUE(file.OpenWriteOnlyTruncate(fileheader_tmp.c_str())); - EXPECT_EQUAL(len, header.writeFile(file)); + EXPECT_EQ(len, header.writeFile(file)); } { FastOS_File file; @@ -590,13 +536,12 @@ Test::testRewriteErrors() header.rewriteFile(file); EXPECT_TRUE(false); } catch (IllegalHeaderException &e) { - EXPECT_EQUAL("Failed to rewrite resized header.", e.getMessage()); + EXPECT_EQ("Failed to rewrite resized header.", e.getMessage()); } } } -void -Test::testLayout() +TEST_F(FileHeaderTest, test_layout) { FileHeader header; { @@ -604,20 +549,20 @@ Test::testLayout() const std::string fileName = TEST_PATH("fileheader.dat"); ASSERT_TRUE(file.OpenReadOnly(fileName.c_str())); uint32_t len = header.readFile(file); - EXPECT_EQUAL(len, header.getSize()); + EXPECT_EQ(len, header.getSize()); } EXPECT_TRUE(header.hasTag("foo")); - EXPECT_EQUAL(6.9, header.getTag("foo").asFloat()); + EXPECT_EQ(6.9, header.getTag("foo").asFloat()); EXPECT_TRUE(header.hasTag("bar")); - EXPECT_EQUAL(6699, header.getTag("bar").asInteger()); + EXPECT_EQ(6699, header.getTag("bar").asInteger()); EXPECT_TRUE(header.hasTag("baz")); - EXPECT_EQUAL("666999", header.getTag("baz").asString()); + EXPECT_EQ("666999", header.getTag("baz").asString()); } void -Test::testReadSize(bool mapped) +FileHeaderTest::testReadSize(bool mapped) { DataBuffer buf; buf.writeInt32(GenericHeader::MAGIC); @@ -632,12 +577,21 @@ Test::testReadSize(bool mapped) GenericHeader::BufferReader reader(buf); headerLen = FileHeader::readSize(reader); } - EXPECT_EQUAL(21u, headerLen); + EXPECT_EQ(21u, headerLen); +} + +TEST_F(FileHeaderTest, test_read_size_unmapped) +{ + testReadSize(false); } +TEST_F(FileHeaderTest, test_read_size_mapped) +{ + testReadSize(true); +} void -Test::testReadSizeErrors(bool mapped) +FileHeaderTest::testReadSizeErrors(bool mapped) { { DataBuffer buf; @@ -674,9 +628,18 @@ Test::testReadSizeErrors(bool mapped) } } +TEST_F(FileHeaderTest, test_read_size_errors_unmapped) +{ + testReadSizeErrors(false); +} + +TEST_F(FileHeaderTest, test_read_size_errors_mapped) +{ + testReadSizeErrors(true); +} bool -Test::testReadSizeError(DataBuffer &buf, const std::string &expected, +FileHeaderTest::testReadSizeError(DataBuffer &buf, const std::string &expected, bool mapped) { uint32_t headerLen = 0u; @@ -691,11 +654,14 @@ Test::testReadSizeError(DataBuffer &buf, const std::string &expected, EXPECT_TRUE(false); return false; } catch (IllegalHeaderException &e) { - if (!EXPECT_EQUAL(expected, e.getMessage())) { + bool failed = false; + EXPECT_EQ(expected, e.getMessage()) << (failed = true, ""); + if (failed) { return false; } } - EXPECT_EQUAL(headerLen, 0u); + EXPECT_EQ(headerLen, 0u); return true; } +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/floatingpointtype/CMakeLists.txt b/vespalib/src/tests/floatingpointtype/CMakeLists.txt index ed003fe7b83..9bcd2236eea 100644 --- a/vespalib/src/tests/floatingpointtype/CMakeLists.txt +++ b/vespalib/src/tests/floatingpointtype/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_floatingpointtype_test_app TEST floatingpointtypetest.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_floatingpointtype_test_app COMMAND vespalib_floatingpointtype_test_app) diff --git a/vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp b/vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp index 8e09d297a84..4b9718f1199 100644 --- a/vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp +++ b/vespalib/src/tests/floatingpointtype/floatingpointtypetest.cpp @@ -1,17 +1,9 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/objects/floatingpointtype.h> -class Test : public vespalib::TestApp -{ -public: - void testFloatingPoint(); - int Main() override; -}; - -void -Test::testFloatingPoint() +TEST(FloatingPointTypeTest, test_floating_point) { vespalib::Double d1(1.0); vespalib::Double d2(1.000000000000001); @@ -20,11 +12,11 @@ Test::testFloatingPoint() EXPECT_TRUE(d1.getValue() != d2.getValue()); - EXPECT_EQUAL(d1, d2); - EXPECT_EQUAL(d2, d1); + EXPECT_EQ(d1, d2); + EXPECT_EQ(d2, d1); - EXPECT_NOT_EQUAL(d1, d3); - EXPECT_NOT_EQUAL(d1, d4); + EXPECT_NE(d1, d3); + EXPECT_NE(d1, d4); EXPECT_TRUE(d1 - d2 == 0); EXPECT_TRUE(d2 - d1 == 0); @@ -40,34 +32,26 @@ Test::testFloatingPoint() EXPECT_TRUE(!(d1 < 1)); EXPECT_TRUE(!(d1 > 1)); - EXPECT_EQUAL(d2 * 4, d4); + EXPECT_EQ(d2 * 4, d4); - EXPECT_EQUAL(++d4, 5.0); - EXPECT_EQUAL(d4++, 5.0); - EXPECT_EQUAL(d4, 6.0); + EXPECT_EQ(++d4, 5.0); + EXPECT_EQ(d4++, 5.0); + EXPECT_EQ(d4, 6.0); d4 /= 3; - EXPECT_EQUAL(d4, 2.00000000001); + EXPECT_EQ(d4, 2.00000000001); d4 *= 2; - EXPECT_EQUAL(d4, 4.000000000001); + EXPECT_EQ(d4, 4.000000000001); - EXPECT_EQUAL(--d4, 3.0); - EXPECT_EQUAL(d4--, 3.0); - EXPECT_EQUAL(d4, 2.0); + EXPECT_EQ(--d4, 3.0); + EXPECT_EQ(d4--, 3.0); + EXPECT_EQ(d4, 2.0); d4 /= 0.50000000001; - EXPECT_EQUAL(d4, 4.0); + EXPECT_EQ(d4, 4.0); EXPECT_TRUE(!(d3 + 1 > 0)); EXPECT_TRUE(!(d3 + 1 < 0)); } -int -Test::Main() -{ - TEST_INIT("floatingpointtype_test"); - testFloatingPoint(); - TEST_DONE(); -} - -TEST_APPHOOK(Test) +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/growablebytebuffer/CMakeLists.txt b/vespalib/src/tests/growablebytebuffer/CMakeLists.txt index be3ba82594d..0448eedd488 100644 --- a/vespalib/src/tests/growablebytebuffer/CMakeLists.txt +++ b/vespalib/src/tests/growablebytebuffer/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_growablebytebuffer_test_app TEST growablebytebuffer_test.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_growablebytebuffer_test_app COMMAND vespalib_growablebytebuffer_test_app) diff --git a/vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp b/vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp index a94a150c4e1..00cc77d19cb 100644 --- a/vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp +++ b/vespalib/src/tests/growablebytebuffer/growablebytebuffer_test.cpp @@ -1,19 +1,11 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/util/growablebytebuffer.h> using namespace vespalib; -class Test : public TestApp -{ -public: - void testGrowing(); - int Main() override; -}; - -void -Test::testGrowing() +TEST(GrowableByteBufferTest, test_growing) { GrowableByteBuffer buf(10); @@ -23,15 +15,7 @@ Test::testGrowing() buf.putDouble(1234); buf.putString("hei der"); - EXPECT_EQUAL(35u, buf.position()); -} - -int -Test::Main() -{ - TEST_INIT("guard_test"); - testGrowing(); - TEST_DONE(); + EXPECT_EQ(35u, buf.position()); } -TEST_APPHOOK(Test) +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/json/CMakeLists.txt b/vespalib/src/tests/json/CMakeLists.txt index 720f8e3a040..89471e18d74 100644 --- a/vespalib/src/tests/json/CMakeLists.txt +++ b/vespalib/src/tests/json/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_json_test_app TEST json.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_json_test_app COMMAND vespalib_json_test_app boost) diff --git a/vespalib/src/tests/json/json.cpp b/vespalib/src/tests/json/json.cpp index 2638c6638c3..024d9045cc1 100644 --- a/vespalib/src/tests/json/json.cpp +++ b/vespalib/src/tests/json/json.cpp @@ -1,124 +1,108 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/util/jsonstream.h> #include <vespa/vespalib/util/jsonexception.h> #include <vespa/vespalib/stllike/asciistream.h> using namespace vespalib; -class JSONTest : public vespalib::TestApp -{ -private: - void testJSONWriterValues(); - void testJSONWriterObject(); - void testJSONWriterArray(); - void testJSONWriterComplex(); - void testJsonStream(); - void testJsonStreamErrors(); - void testJsonStreamStateReporting(); - -public: - int Main() override; -}; -void -JSONTest::testJSONWriterValues() +TEST(JSONTest, test_json_writer_values) { JSONStringer js; { // bool js.appendBool(true); - EXPECT_EQUAL(js.toString(), "true"); + EXPECT_EQ(js.toString(), "true"); js.clear().appendBool(false); - EXPECT_EQUAL(js.toString(), "false"); + EXPECT_EQ(js.toString(), "false"); } { // double js.clear().appendDouble(1234.5678); - EXPECT_EQUAL(js.toString(), "1234.5678"); + EXPECT_EQ(js.toString(), "1234.5678"); js.clear().appendDouble(-1234.5678); - EXPECT_EQUAL(js.toString(), "-1234.5678"); + EXPECT_EQ(js.toString(), "-1234.5678"); js.clear().appendDouble(0.0); - EXPECT_EQUAL(js.toString(), "0.0"); + EXPECT_EQ(js.toString(), "0.0"); js.clear().appendDouble(0.00000000012345678912356789123456789); - EXPECT_EQUAL(js.toString(), "1.234567891235679e-10"); + EXPECT_EQ(js.toString(), "1.234567891235679e-10"); js.clear().appendDouble(std::numeric_limits<double>::max()); - EXPECT_EQUAL(js.toString(), "1.797693134862316e+308"); + EXPECT_EQ(js.toString(), "1.797693134862316e+308"); js.clear().appendDouble(std::numeric_limits<double>::min()); - EXPECT_EQUAL(js.toString(), "2.225073858507201e-308"); + EXPECT_EQ(js.toString(), "2.225073858507201e-308"); js.clear().appendDouble(1.0 * (uint64_t(1) << 53)); - EXPECT_EQUAL(js.toString(), "9007199254740992.0"); + EXPECT_EQ(js.toString(), "9007199254740992.0"); js.clear().appendDouble(1000); - EXPECT_EQUAL(js.toString(), "1000.0"); + EXPECT_EQ(js.toString(), "1000.0"); } { // float js.clear().appendFloat(1234.5678f); - EXPECT_EQUAL(js.toString(), "1234.5677"); + EXPECT_EQ(js.toString(), "1234.5677"); js.clear().appendFloat(-1234.5678f); - EXPECT_EQUAL(js.toString(), "-1234.5677"); + EXPECT_EQ(js.toString(), "-1234.5677"); js.clear().appendFloat(0.0f); - EXPECT_EQUAL(js.toString(), "0.0"); + EXPECT_EQ(js.toString(), "0.0"); js.clear().appendFloat(0.00000000012345678912356789123456789f); - EXPECT_EQUAL(js.toString(), "1.2345679e-10"); + EXPECT_EQ(js.toString(), "1.2345679e-10"); js.clear().appendFloat(std::numeric_limits<float>::max()); - EXPECT_EQUAL(js.toString(), "3.4028235e+38"); + EXPECT_EQ(js.toString(), "3.4028235e+38"); js.clear().appendFloat(std::numeric_limits<float>::min()); - EXPECT_EQUAL(js.toString(), "1.1754944e-38"); + EXPECT_EQ(js.toString(), "1.1754944e-38"); js.clear().appendFloat(1.0 * (uint64_t(1) << 24)); - EXPECT_EQUAL(js.toString(), "16777216.0"); + EXPECT_EQ(js.toString(), "16777216.0"); js.clear().appendFloat(1000); - EXPECT_EQUAL(js.toString(), "1000.0"); + EXPECT_EQ(js.toString(), "1000.0"); } { // long js.clear().appendInt64(4294967296ll); - EXPECT_EQUAL(js.toString(), "4294967296"); + EXPECT_EQ(js.toString(), "4294967296"); js.clear().appendInt64(-4294967296ll); - EXPECT_EQUAL(js.toString(), "-4294967296"); + EXPECT_EQ(js.toString(), "-4294967296"); } { // string js.clear().appendString("string"); - EXPECT_EQUAL(js.toString(), "\"string\""); + EXPECT_EQ(js.toString(), "\"string\""); } { // NULL js.clear().appendNull(); - EXPECT_EQUAL(js.toString(), "null"); + EXPECT_EQ(js.toString(), "null"); } { // quote js.clear().appendString("x\"y"); - EXPECT_EQUAL(js.toString(), "\"x\\\"y\""); + EXPECT_EQ(js.toString(), "\"x\\\"y\""); js.clear().appendString("x\\y"); - EXPECT_EQUAL(js.toString(), "\"x\\\\y\""); + EXPECT_EQ(js.toString(), "\"x\\\\y\""); js.clear().appendString("x/y"); - EXPECT_EQUAL(js.toString(), "\"x/y\""); + EXPECT_EQ(js.toString(), "\"x/y\""); js.clear().appendString("x\by"); - EXPECT_EQUAL(js.toString(), "\"x\\by\""); + EXPECT_EQ(js.toString(), "\"x\\by\""); js.clear().appendString("x\fy"); - EXPECT_EQUAL(js.toString(), "\"x\\fy\""); + EXPECT_EQ(js.toString(), "\"x\\fy\""); js.clear().appendString("x\ny"); - EXPECT_EQUAL(js.toString(), "\"x\\ny\""); + EXPECT_EQ(js.toString(), "\"x\\ny\""); js.clear().appendString("x\ry"); - EXPECT_EQUAL(js.toString(), "\"x\\ry\""); + EXPECT_EQ(js.toString(), "\"x\\ry\""); js.clear().appendString("x\ty"); - EXPECT_EQUAL(js.toString(), "\"x\\ty\""); + EXPECT_EQ(js.toString(), "\"x\\ty\""); } } -void -JSONTest::testJSONWriterObject() +TEST(JSONTest, test_json_writer_object) { JSONStringer js; { // single pair js.beginObject().appendKey("k1").appendInt64(1l).endObject(); - EXPECT_EQUAL(js.toString(), "{\"k1\":1}"); + EXPECT_EQ(js.toString(), "{\"k1\":1}"); } { // multiple pairs js.clear().beginObject().appendKey("k1").appendInt64(1l).appendKey("k2").appendInt64(2l).endObject(); - EXPECT_EQUAL(js.toString(), "{\"k1\":1,\"k2\":2}"); + EXPECT_EQ(js.toString(), "{\"k1\":1,\"k2\":2}"); } { // object in object js.clear().beginObject().appendKey("k1").beginObject().appendKey("k1.1").appendInt64(11l).endObject().endObject(); - EXPECT_EQUAL(js.toString(), "{\"k1\":{\"k1.1\":11}}"); + EXPECT_EQ(js.toString(), "{\"k1\":{\"k1.1\":11}}"); } { // object in object (multiple pairs) js.clear().beginObject(). @@ -133,65 +117,61 @@ JSONTest::testJSONWriterObject() appendKey("k2.2").appendInt64(22l). endObject(). endObject(); - EXPECT_EQUAL(js.toString(), "{\"k1\":{\"k1.1\":11,\"k1.2\":12},\"k2\":{\"k2.1\":21,\"k2.2\":22}}"); + EXPECT_EQ(js.toString(), "{\"k1\":{\"k1.1\":11,\"k1.2\":12},\"k2\":{\"k2.1\":21,\"k2.2\":22}}"); } { // array in object js.clear().beginObject().appendKey("k1"). beginArray().appendInt64(1l).appendInt64(2l).endArray().endObject(); - EXPECT_EQUAL(js.toString(), "{\"k1\":[1,2]}"); + EXPECT_EQ(js.toString(), "{\"k1\":[1,2]}"); } { // array in object (multiple pairs) js.clear().beginObject(). appendKey("k1").beginArray().appendInt64(1l).appendInt64(2l).endArray(). appendKey("k2").beginArray().appendInt64(3l).appendInt64(4l).endArray(). endObject(); - EXPECT_EQUAL(js.toString(), "{\"k1\":[1,2],\"k2\":[3,4]}"); + EXPECT_EQ(js.toString(), "{\"k1\":[1,2],\"k2\":[3,4]}"); } } - -void -JSONTest::testJSONWriterArray() +TEST(JSONTest, test_json_writer_array) { JSONStringer js; { // single element js.beginArray().appendInt64(1l).endArray(); - EXPECT_EQUAL(js.toString(), "[1]"); + EXPECT_EQ(js.toString(), "[1]"); } { // multiple elements js.clear().beginArray().appendInt64(1l).appendInt64(2l).endArray(); - EXPECT_EQUAL(js.toString(), "[1,2]"); + EXPECT_EQ(js.toString(), "[1,2]"); } { // array in array js.clear().beginArray().beginArray().appendInt64(1l).endArray().endArray(); - EXPECT_EQUAL(js.toString(), "[[1]]"); + EXPECT_EQ(js.toString(), "[[1]]"); } { // array in array (multiple elements) js.clear().beginArray(). beginArray().appendInt64(1l).appendInt64(2l).endArray(). beginArray().appendInt64(3l).appendInt64(4l).endArray(). endArray(); - EXPECT_EQUAL(js.toString(), "[[1,2],[3,4]]"); + EXPECT_EQ(js.toString(), "[[1,2],[3,4]]"); } { // object in array js.clear().beginArray(). beginObject().appendKey("k1").appendInt64(1l).endObject(). endArray(); - EXPECT_EQUAL(js.toString(), "[{\"k1\":1}]"); + EXPECT_EQ(js.toString(), "[{\"k1\":1}]"); } { // object in array (multiple elements) js.clear().beginArray(). beginObject().appendKey("k1").appendInt64(1l).appendKey("k2").appendInt64(2l).endObject(). beginObject().appendKey("k3").appendInt64(3l).appendKey("k4").appendInt64(4l).endObject(). endArray(); - EXPECT_EQUAL(js.toString(), "[{\"k1\":1,\"k2\":2},{\"k3\":3,\"k4\":4}]"); + EXPECT_EQ(js.toString(), "[{\"k1\":1,\"k2\":2},{\"k3\":3,\"k4\":4}]"); } } - -void -JSONTest::testJSONWriterComplex() +TEST(JSONTest, test_json_writer_complex) { JSONStringer js; @@ -269,7 +249,7 @@ JSONTest::testJSONWriterComplex() js.endArray(); } js.endObject(); - EXPECT_EQUAL(js.toString(), "{\"k1\":{\"k1.1\":1,\"k1.2\":[2,3]},\"k2\":{\"k2.1\":{\"k2.1.1\":4,\"k2.1.2\":[5,6]}},\"k3\":[{\"k3.1\":7,\"k3.2\":[8,9]},{\"k3.1\":10,\"k3.2\":[11,12]}]}"); + EXPECT_EQ(js.toString(), "{\"k1\":{\"k1.1\":1,\"k1.2\":[2,3]},\"k2\":{\"k2.1\":{\"k2.1.1\":4,\"k2.1.2\":[5,6]}},\"k3\":[{\"k3.1\":7,\"k3.2\":[8,9]},{\"k3.1\":10,\"k3.2\":[11,12]}]}"); } namespace { @@ -304,19 +284,17 @@ namespace { }; } -void -JSONTest::testJsonStream() +TEST(JSONTest, test_json_stream) { vespalib::asciistream as; vespalib::JsonStream stream(as); Builder b; b.build(stream); stream.finalize(); - EXPECT_EQUAL(as.str(), "{\"k1\":{\"k1.1\":1,\"k1.2\":[2,3]},\"k2\":{\"k2.1\":{\"k2.1.1\":4,\"k2.1.2\":[5,6]}},\"k3\":[{\"k3.1\":-7,\"k3.2\":[-8,-9]},{\"k3.1\":10,\"k3.2\":[11,12]}]}"); + EXPECT_EQ(as.str(), "{\"k1\":{\"k1.1\":1,\"k1.2\":[2,3]},\"k2\":{\"k2.1\":{\"k2.1.1\":4,\"k2.1.2\":[5,6]}},\"k3\":[{\"k3.1\":-7,\"k3.2\":[-8,-9]},{\"k3.1\":10,\"k3.2\":[11,12]}]}"); } -void -JSONTest::testJsonStreamErrors() +TEST(JSONTest, test_json_stream_errors) { using namespace vespalib::jsonstream; // Unsupported object keys @@ -325,42 +303,42 @@ JSONTest::testJsonStreamErrors() vespalib::JsonStream stream(as); stream << Object() << Object(); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: An object value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); + EXPECT_EQ("Invalid state on call: An object value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << true; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: A bool value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); + EXPECT_EQ("Invalid state on call: A bool value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << 13; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: An int64_t value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); + EXPECT_EQ("Invalid state on call: An int64_t value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << uint64_t(13); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: A uint64_t value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); + EXPECT_EQ("Invalid state on call: A uint64_t value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << 0.5; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: A double value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); + EXPECT_EQ("Invalid state on call: A double value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << jsonstream::Array(); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: An array value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); + EXPECT_EQ("Invalid state on call: An array value cannot be an object key ({}(ObjectExpectingKey))", e.getReason()); } // Invalid points to add End() try{ @@ -368,14 +346,14 @@ JSONTest::testJsonStreamErrors() vespalib::JsonStream stream(as); stream << Object() << "foo" << End(); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Object got key but not value. Cannot end it now ({foo}(ObjectExpectingValue))", e.getReason()); + EXPECT_EQ("Invalid state on call: Object got key but not value. Cannot end it now ({foo}(ObjectExpectingValue))", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << End(); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: No tag to end. At root ((RootExpectingArrayOrObjectStart))", e.getReason()); + EXPECT_EQ("Invalid state on call: No tag to end. At root ((RootExpectingArrayOrObjectStart))", e.getReason()); } // Adding to finalized stream try{ @@ -383,61 +361,60 @@ JSONTest::testJsonStreamErrors() vespalib::JsonStream stream(as); stream << Object() << End() << "foo"; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a string value. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't add a string value. (Finalized)", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << End() << false; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a bool value. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't add a bool value. (Finalized)", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << End() << 13; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a long long value. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't add a long long value. (Finalized)", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << End() << 13u; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add an unsigned long long value. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't add an unsigned long long value. (Finalized)", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << End() << 0.2; } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't add a double value. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't add a double value. (Finalized)", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << End() << Object(); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't start a new object. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't start a new object. (Finalized)", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << End() << jsonstream::Array(); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't start a new array. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't start a new array. (Finalized)", e.getReason()); } try{ vespalib::asciistream as; vespalib::JsonStream stream(as); stream << Object() << End() << End(); } catch (vespalib::JsonStreamException& e) { - EXPECT_EQUAL("Invalid state on call: Stream already finalized. Can't end it. (Finalized)", e.getReason()); + EXPECT_EQ("Invalid state on call: Stream already finalized. Can't end it. (Finalized)", e.getReason()); } } -void -JSONTest::testJsonStreamStateReporting() +TEST(JSONTest, test_json_stream_state_reporting) { using namespace vespalib::jsonstream; vespalib::asciistream as; @@ -447,24 +424,8 @@ JSONTest::testJsonStreamStateReporting() << Object() << "key" << "value" << End() << false << End(); - EXPECT_EQUAL("Current: Finalized", stream.getJsonStreamState()); -} - -int -JSONTest::Main() -{ - TEST_INIT("json_test"); - - testJSONWriterValues(); - testJSONWriterObject(); - testJSONWriterArray(); - testJSONWriterComplex(); - testJsonStream(); - testJsonStreamErrors(); - testJsonStreamStateReporting(); - - TEST_DONE(); + EXPECT_EQ("Current: Finalized", stream.getJsonStreamState()); } -TEST_APPHOOK(JSONTest); +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/objects/identifiable/CMakeLists.txt b/vespalib/src/tests/objects/identifiable/CMakeLists.txt index e8227a8fa14..c3e8a932e20 100644 --- a/vespalib/src/tests/objects/identifiable/CMakeLists.txt +++ b/vespalib/src/tests/objects/identifiable/CMakeLists.txt @@ -5,5 +5,6 @@ vespa_add_executable(vespalib_identifiable_test_app TEST namedobject.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_identifiable_test_app COMMAND vespalib_identifiable_test_app) diff --git a/vespalib/src/tests/objects/identifiable/identifiable_test.cpp b/vespalib/src/tests/objects/identifiable/identifiable_test.cpp index 4b31ba6e870..6296c7c5922 100644 --- a/vespalib/src/tests/objects/identifiable/identifiable_test.cpp +++ b/vespalib/src/tests/objects/identifiable/identifiable_test.cpp @@ -1,27 +1,26 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "namedobject.h" +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/objects/identifiable.hpp> #include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/util/exceptions.h> -#include <vespa/vespalib/testkit/testapp.h> using namespace vespalib; -class IdentifiableTest : public TestApp { - void requireThatIdentifiableCastCanCastPointers(); - void requireThatIdentifiableCastCanCastReferences(); - void testNamedObject(); - void testNboStream(); +class IdentifiableTest : public ::testing::Test { +protected: + IdentifiableTest(); + ~IdentifiableTest() override; template <typename T> void testStream(const T & a); - void testNboSerializer(); template <typename T> void testSerializer(const T & a); -public: - int Main() override; }; +IdentifiableTest::IdentifiableTest() = default; +IdentifiableTest::~IdentifiableTest() = default; + #define CID_Abstract 0x700000 #define CID_A 0x700001 #define CID_B 0x700002 @@ -74,22 +73,21 @@ IMPLEMENT_IDENTIFIABLE(A, Abstract); IMPLEMENT_IDENTIFIABLE(B, A); IMPLEMENT_IDENTIFIABLE(C, Identifiable); -void -IdentifiableTest::testNamedObject() +TEST_F(IdentifiableTest, test_named_object) { NamedObject a("first"), b("second");; nbostream os; NBOSerializer nos(os); nos << a << b; - EXPECT_EQUAL(27u,os.size()); + EXPECT_EQ(27u,os.size()); Identifiable::UP o1; o1 = Identifiable::create(nos); - EXPECT_EQUAL(14u, os.size()); + EXPECT_EQ(14u, os.size()); ASSERT_TRUE(o1->inherits(NamedObject::classId)); ASSERT_TRUE(o1->getClass().id() == NamedObject::classId); EXPECT_TRUE(static_cast<const NamedObject &>(*o1).getName() == "first"); o1 = Identifiable::create(nos); - EXPECT_EQUAL(0u, os.size()); + EXPECT_EQ(0u, os.size()); ASSERT_TRUE(o1->inherits(NamedObject::classId)); ASSERT_TRUE(o1->getClass().id() == NamedObject::classId); EXPECT_TRUE(static_cast<const NamedObject &>(*o1).getName() == "second"); @@ -103,8 +101,8 @@ void IdentifiableTest::testStream(const T & a) T b; s >> b; EXPECT_TRUE(s.empty()); - EXPECT_EQUAL(a, b); - EXPECT_EQUAL(nbostream::ok, s.state()); + EXPECT_EQ(a, b); + EXPECT_EQ(nbostream::ok, s.state()); EXPECT_TRUE(s.good()); } @@ -117,11 +115,11 @@ void IdentifiableTest::testSerializer(const T & a) T b; s >> b; EXPECT_TRUE(s.getStream().empty()); - EXPECT_EQUAL(a, b); - EXPECT_EQUAL(nbostream::ok, s.getStream().state()); + EXPECT_EQ(a, b); + EXPECT_EQ(nbostream::ok, s.getStream().state()); } -void IdentifiableTest::testNboSerializer() +TEST_F(IdentifiableTest, test_nbo_serializer) { testSerializer(true); testSerializer(false); @@ -138,7 +136,7 @@ void IdentifiableTest::testNboSerializer() testSerializer(vespalib::string("abcdefgh")); } -void IdentifiableTest::testNboStream() +TEST_F(IdentifiableTest, test_nbo_stream) { testStream(true); testStream(false); @@ -156,94 +154,85 @@ void IdentifiableTest::testNboStream() testStream(vespalib::string("abcdefgh")); { nbostream s(4); - EXPECT_EQUAL(4u, s.capacity()); + EXPECT_EQ(4u, s.capacity()); s << "abcdef"; - EXPECT_EQUAL(nbostream::ok, s.state()); - EXPECT_EQUAL(10u, s.size()); - EXPECT_EQUAL(16u, s.capacity()); - EXPECT_EQUAL(0, strncmp(s.data() + 4, "abcdef", 6)); + EXPECT_EQ(nbostream::ok, s.state()); + EXPECT_EQ(10u, s.size()); + EXPECT_EQ(16u, s.capacity()); + EXPECT_EQ(0, strncmp(s.data() + 4, "abcdef", 6)); } { nbostream s(8); - EXPECT_EQUAL(0u, s.size()); - EXPECT_EQUAL(8u, s.capacity()); + EXPECT_EQ(0u, s.size()); + EXPECT_EQ(8u, s.capacity()); const char * prev = s.data(); s << "ABCD"; - EXPECT_EQUAL(8u, s.size()); - EXPECT_EQUAL(8u, s.capacity()); - EXPECT_EQUAL(prev, s.data()); + EXPECT_EQ(8u, s.size()); + EXPECT_EQ(8u, s.capacity()); + EXPECT_EQ(prev, s.data()); s << "A long string that will cause resizing"; - EXPECT_EQUAL(50u, s.size()); - EXPECT_EQUAL(64u, s.capacity()); - EXPECT_NOT_EQUAL(prev, s.data()); + EXPECT_EQ(50u, s.size()); + EXPECT_EQ(64u, s.capacity()); + EXPECT_NE(prev, s.data()); } { nbostream s(8); - EXPECT_EQUAL(0u, s.size()); - EXPECT_EQUAL(8u, s.capacity()); + EXPECT_EQ(0u, s.size()); + EXPECT_EQ(8u, s.capacity()); const char * prev = s.data(); s << "ABCD"; - EXPECT_EQUAL(8u, s.size()); - EXPECT_EQUAL(8u, s.capacity()); - EXPECT_EQUAL(prev, s.data()); + EXPECT_EQ(8u, s.size()); + EXPECT_EQ(8u, s.capacity()); + EXPECT_EQ(prev, s.data()); s.reserve(50); - EXPECT_NOT_EQUAL(prev, s.data()); - EXPECT_EQUAL(8u, s.size()); - EXPECT_EQUAL(64u, s.capacity()); + EXPECT_NE(prev, s.data()); + EXPECT_EQ(8u, s.size()); + EXPECT_EQ(64u, s.capacity()); prev = s.data(); s << "A long string that will cause resizing"; - EXPECT_EQUAL(50u, s.size()); - EXPECT_EQUAL(64u, s.capacity()); - EXPECT_EQUAL(prev, s.data()); + EXPECT_EQ(50u, s.size()); + EXPECT_EQ(64u, s.capacity()); + EXPECT_EQ(prev, s.data()); } { nbostream s; s << int64_t(9); - EXPECT_EQUAL(8u, s.size()); - EXPECT_EQUAL(0u, s.rp()); + EXPECT_EQ(8u, s.size()); + EXPECT_EQ(0u, s.rp()); int64_t a(7), b(1); s >> a; - EXPECT_EQUAL(0u, s.size()); - EXPECT_EQUAL(8u, s.rp()); + EXPECT_EQ(0u, s.size()); + EXPECT_EQ(8u, s.rp()); EXPECT_TRUE(s.empty()); EXPECT_TRUE(s.good()); - EXPECT_EQUAL(9, a); + EXPECT_EQ(9, a); try { s >> b; EXPECT_TRUE(false); } catch (const IllegalStateException & e) { - EXPECT_EQUAL("Stream failed bufsize(1024), readp(8), writep(8)", e.getMessage()); + EXPECT_EQ("Stream failed bufsize(1024), readp(8), writep(8)", e.getMessage()); } - EXPECT_EQUAL(0u, s.size()); - EXPECT_EQUAL(8u, s.rp()); + EXPECT_EQ(0u, s.size()); + EXPECT_EQ(8u, s.rp()); EXPECT_TRUE(s.empty()); EXPECT_FALSE(s.good()); - EXPECT_EQUAL(1, b); - EXPECT_EQUAL(nbostream::eof, s.state()); + EXPECT_EQ(1, b); + EXPECT_EQ(nbostream::eof, s.state()); } } -int -IdentifiableTest::Main() +TEST_F(IdentifiableTest, test_identifiable) { - TEST_INIT("identifiable_test"); - - TEST_DO(requireThatIdentifiableCastCanCastPointers()); - TEST_DO(requireThatIdentifiableCastCanCastReferences()); - testNamedObject(); - testNboStream(); - testNboSerializer(); - A a; B b; const Identifiable::RuntimeClass & rtcA = a.getClass(); - EXPECT_EQUAL(rtcA.id(), static_cast<unsigned int>(A::classId)); - EXPECT_EQUAL(strcmp(rtcA.name(), "A"), 0); + EXPECT_EQ(rtcA.id(), static_cast<unsigned int>(A::classId)); + EXPECT_EQ(strcmp(rtcA.name(), "A"), 0); const Identifiable::RuntimeClass & rtcB = b.getClass(); - EXPECT_EQUAL(rtcB.id(), static_cast<unsigned int>(B::classId)); - EXPECT_EQUAL(strcmp(rtcB.name(), "B"), 0); + EXPECT_EQ(rtcB.id(), static_cast<unsigned int>(B::classId)); + EXPECT_EQ(strcmp(rtcB.name(), "B"), 0); const Identifiable::RuntimeClass * rt(Identifiable::classFromId(0x1ab76245)); ASSERT_TRUE(rt == NULL); @@ -270,7 +259,7 @@ IdentifiableTest::Main() nbostream os; NBOSerializer nos(os); nos << *o; - EXPECT_EQUAL(os.size(), 4u); + EXPECT_EQ(os.size(), 4u); Identifiable::UP o2 = Identifiable::create(nos); EXPECT_TRUE(os.empty()); ASSERT_TRUE(o->inherits(B::classId)); @@ -297,18 +286,17 @@ IdentifiableTest::Main() IdentifiablePtr<C> c1(new C(10)); IdentifiablePtr<C> c2(new C(20)); - EXPECT_LESS(c0.cmp(c1), 0); - EXPECT_EQUAL(c0.cmp(c0), 0); - EXPECT_GREATER(c1.cmp(c0), 0); + EXPECT_LT(c0.cmp(c1), 0); + EXPECT_EQ(c0.cmp(c0), 0); + EXPECT_GT(c1.cmp(c0), 0); - EXPECT_LESS(c1.cmp(c2), 0); - EXPECT_EQUAL(c1.cmp(c1), 0); - EXPECT_GREATER(c2.cmp(c1), 0); - - TEST_DONE(); + EXPECT_LT(c1.cmp(c2), 0); + EXPECT_EQ(c1.cmp(c1), 0); + EXPECT_GT(c2.cmp(c1), 0); } -void IdentifiableTest::requireThatIdentifiableCastCanCastPointers() { +TEST_F(IdentifiableTest, require_that_identifiable_cast_can_cast_pointers) +{ A a; B b; EXPECT_TRUE(Identifiable::cast<A *>(&a)); @@ -319,7 +307,8 @@ void IdentifiableTest::requireThatIdentifiableCastCanCastPointers() { EXPECT_TRUE(Identifiable::cast<Abstract *>(&b)); } -void IdentifiableTest::requireThatIdentifiableCastCanCastReferences() { +TEST_F(IdentifiableTest, require_that_identifiable_cast_can_cast_references) +{ A a; B b; try { @@ -330,9 +319,9 @@ void IdentifiableTest::requireThatIdentifiableCastCanCastReferences() { Identifiable::cast<Abstract &>(a); Identifiable::cast<Abstract &>(b); } catch (std::bad_cast &e) { - TEST_FATAL(e.what()); + FAIL() << e.what(); } - EXPECT_EXCEPTION(Identifiable::cast<B &>(a), std::bad_cast, "bad_cast"); + EXPECT_THROW(Identifiable::cast<B &>(a), std::bad_cast); } -TEST_APPHOOK(IdentifiableTest) +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/optimized/CMakeLists.txt b/vespalib/src/tests/optimized/CMakeLists.txt index 0e7e85b6678..ce1c3a7cf67 100644 --- a/vespalib/src/tests/optimized/CMakeLists.txt +++ b/vespalib/src/tests/optimized/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_optimized_test_app TEST optimized_test.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_optimized_test_app COMMAND vespalib_optimized_test_app) diff --git a/vespalib/src/tests/optimized/optimized_test.cpp b/vespalib/src/tests/optimized/optimized_test.cpp index 9dffefeb012..ec14750f919 100644 --- a/vespalib/src/tests/optimized/optimized_test.cpp +++ b/vespalib/src/tests/optimized/optimized_test.cpp @@ -1,82 +1,64 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/util/optimized.h> using namespace vespalib; -class Test : public vespalib::TestApp +template <typename TestType> +class OptimizedTest : public ::testing::Test { -private: - template<typename T> - void testMsbIdx(); - template<typename T> - void testLsbIdx(); - template<typename T> - void testPopCount(); -public: - int Main() override; +protected: + OptimizedTest(); + ~OptimizedTest() override; }; -template<typename T> -void Test::testMsbIdx() +template <typename TestType> +OptimizedTest<TestType>::OptimizedTest() = default; +template <typename TestType> +OptimizedTest<TestType>::~OptimizedTest() = default; + +using OptimizedTestTypes = ::testing::Types<unsigned int, unsigned long, unsigned long long>; +TYPED_TEST_SUITE(OptimizedTest, OptimizedTestTypes); + +TYPED_TEST(OptimizedTest, test_msb_idx) { - EXPECT_EQUAL(Optimized::msbIdx(T(0)), 0); - EXPECT_EQUAL(Optimized::msbIdx(T(1)), 0); - EXPECT_EQUAL(Optimized::msbIdx(T(-1)), int(sizeof(T)*8 - 1)); + using T = TypeParam; + EXPECT_EQ(Optimized::msbIdx(T(0)), 0); + EXPECT_EQ(Optimized::msbIdx(T(1)), 0); + EXPECT_EQ(Optimized::msbIdx(T(-1)), int(sizeof(T)*8 - 1)); T v(static_cast<T>(-1)); for (size_t i(0); i < sizeof(T); i++) { for (size_t j(0); j < 8; j++) { - EXPECT_EQUAL(Optimized::msbIdx(v), int(sizeof(T)*8 - (i*8+j) - 1)); + EXPECT_EQ(Optimized::msbIdx(v), int(sizeof(T)*8 - (i*8+j) - 1)); v = v >> 1; } } } -template<typename T> -void Test::testLsbIdx() +TYPED_TEST(OptimizedTest, test_lsb_idx) { - EXPECT_EQUAL(Optimized::lsbIdx(T(0)), 0); - EXPECT_EQUAL(Optimized::lsbIdx(T(1)), 0); - EXPECT_EQUAL(Optimized::lsbIdx(T(T(1)<<(sizeof(T)*8 - 1))), int(sizeof(T)*8 - 1)); - EXPECT_EQUAL(Optimized::lsbIdx(T(-1)), 0); + using T = TypeParam; + EXPECT_EQ(Optimized::lsbIdx(T(0)), 0); + EXPECT_EQ(Optimized::lsbIdx(T(1)), 0); + EXPECT_EQ(Optimized::lsbIdx(T(T(1)<<(sizeof(T)*8 - 1))), int(sizeof(T)*8 - 1)); + EXPECT_EQ(Optimized::lsbIdx(T(-1)), 0); T v(static_cast<T>(-1)); for (size_t i(0); i < sizeof(T); i++) { for (size_t j(0); j < 8; j++) { - EXPECT_EQUAL(Optimized::lsbIdx(v), int(i*8+j)); + EXPECT_EQ(Optimized::lsbIdx(v), int(i*8+j)); v = v << 1; } } } -template<typename T> -void Test::testPopCount() +TYPED_TEST(OptimizedTest, test_pop_count) { - EXPECT_EQUAL(0, Optimized::popCount(T(0))); - EXPECT_EQUAL(1, Optimized::popCount(T(1))); - EXPECT_EQUAL(int(8 * sizeof(T)), Optimized::popCount(T(-1))); + using T = TypeParam; + EXPECT_EQ(0, Optimized::popCount(T(0))); + EXPECT_EQ(1, Optimized::popCount(T(1))); + EXPECT_EQ(int(8 * sizeof(T)), Optimized::popCount(T(-1))); } -int Test::Main() -{ - TEST_INIT("optimized_test"); - - testMsbIdx<unsigned int>(); - testMsbIdx<unsigned long>(); - testMsbIdx<unsigned long long>(); - - TEST_FLUSH(); - testLsbIdx<unsigned int>(); - testLsbIdx<unsigned long>(); - testLsbIdx<unsigned long long>(); - - TEST_FLUSH(); - testPopCount<unsigned int>(); - testPopCount<unsigned long>(); - testPopCount<unsigned long long>(); - - TEST_FLUSH(); - TEST_DONE(); -} +GTEST_MAIN_RUN_ALL_TESTS() -TEST_APPHOOK(Test) diff --git a/vespalib/src/tests/printable/CMakeLists.txt b/vespalib/src/tests/printable/CMakeLists.txt index e9332bba309..4781e9b8f54 100644 --- a/vespalib/src/tests/printable/CMakeLists.txt +++ b/vespalib/src/tests/printable/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_printabletest_app TEST printabletest.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_printabletest_app COMMAND vespalib_printabletest_app) diff --git a/vespalib/src/tests/printable/printabletest.cpp b/vespalib/src/tests/printable/printabletest.cpp index 03e3c777a25..5b6c0058bf0 100644 --- a/vespalib/src/tests/printable/printabletest.cpp +++ b/vespalib/src/tests/printable/printabletest.cpp @@ -1,8 +1,8 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/util/printable.h> #include <vespa/vespalib/stllike/asciistream.h> -#include <vespa/vespalib/testkit/testapp.h> struct Foo : public vespalib::Printable { int val; @@ -74,80 +74,61 @@ struct AsciiBar : public vespalib::AsciiPrintable { } }; -class Test : public vespalib::TestApp -{ -public: - void testSimple(); - void testAsciiVariant(); - int Main() override; -}; - -void -Test::testSimple() +TEST(PrintableTest, test_simple) { Foo foo(3, "myval"); Bar bar(7, 3, "otherval"); - EXPECT_EQUAL("Foo(val = 3, other size 5)", foo.toString()); - EXPECT_EQUAL("Foo(val = 3, other size 5)", foo.toString(false, " ")); - EXPECT_EQUAL("Foo(val = 3, other:\n" - " myval)", foo.toString(true)); - EXPECT_EQUAL("Foo(val = 3, other:\n" - " myval)", foo.toString(true, " ")); + EXPECT_EQ("Foo(val = 3, other size 5)", foo.toString()); + EXPECT_EQ("Foo(val = 3, other size 5)", foo.toString(false, " ")); + EXPECT_EQ("Foo(val = 3, other:\n" + " myval)", foo.toString(true)); + EXPECT_EQ("Foo(val = 3, other:\n" + " myval)", foo.toString(true, " ")); std::ostringstream ost; ost << foo; - EXPECT_EQUAL("Foo(val = 3, other size 5)", ost.str()); - - EXPECT_EQUAL("Bar(7)", bar.toString()); - EXPECT_EQUAL("Bar(7)", bar.toString(false, " ")); - EXPECT_EQUAL("Bar(7) : Foo(val = 3, other:\n" - " otherval)", bar.toString(true)); - EXPECT_EQUAL("Bar(7) : Foo(val = 3, other:\n" - " otherval)", bar.toString(true, " ")); + EXPECT_EQ("Foo(val = 3, other size 5)", ost.str()); + + EXPECT_EQ("Bar(7)", bar.toString()); + EXPECT_EQ("Bar(7)", bar.toString(false, " ")); + EXPECT_EQ("Bar(7) : Foo(val = 3, other:\n" + " otherval)", bar.toString(true)); + EXPECT_EQ("Bar(7) : Foo(val = 3, other:\n" + " otherval)", bar.toString(true, " ")); } -void -Test::testAsciiVariant() +TEST(PrintableTest, test_ascii_variant) { AsciiFoo foo(19); - EXPECT_EQUAL("19", foo.toString()); - EXPECT_EQUAL("AsciiFoo(19)", - foo.toString(vespalib::AsciiPrintable::VERBOSE)); + EXPECT_EQ("19", foo.toString()); + EXPECT_EQ("AsciiFoo(19)", + foo.toString(vespalib::AsciiPrintable::VERBOSE)); { vespalib::asciistream as; as << foo; - EXPECT_EQUAL("19", as.str()); + EXPECT_EQ("19", as.str()); std::ostringstream ost; ost << foo; - EXPECT_EQUAL("19", ost.str()); + EXPECT_EQ("19", ost.str()); } AsciiBar bar(3); - EXPECT_EQUAL("3", bar.toString()); - EXPECT_EQUAL("AsciiBar() {\n" - " AsciiFoo(3)\n" - "}", bar.toString(vespalib::AsciiPrintable::VERBOSE)); + EXPECT_EQ("3", bar.toString()); + EXPECT_EQ("AsciiBar() {\n" + " AsciiFoo(3)\n" + "}", bar.toString(vespalib::AsciiPrintable::VERBOSE)); { vespalib::asciistream as; as << bar; - EXPECT_EQUAL("3", as.str()); + EXPECT_EQ("3", as.str()); std::ostringstream ost; ost << bar; - EXPECT_EQUAL("3", ost.str()); + EXPECT_EQ("3", ost.str()); } } -int -Test::Main() -{ - TEST_INIT("printabletest"); - testSimple(); - testAsciiVariant(); - TEST_DONE(); -} - -TEST_APPHOOK(Test) +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/programoptions/CMakeLists.txt b/vespalib/src/tests/programoptions/CMakeLists.txt index 81066b19104..524ea8dc416 100644 --- a/vespalib/src/tests/programoptions/CMakeLists.txt +++ b/vespalib/src/tests/programoptions/CMakeLists.txt @@ -5,5 +5,6 @@ vespa_add_executable(vespalib_programoptions_test_app TEST programoptions_testutils.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_programoptions_test_app COMMAND vespalib_programoptions_test_app) diff --git a/vespalib/src/tests/programoptions/programoptions_test.cpp b/vespalib/src/tests/programoptions/programoptions_test.cpp index bbb5e2ffc20..4f5ff2fc4d1 100644 --- a/vespalib/src/tests/programoptions/programoptions_test.cpp +++ b/vespalib/src/tests/programoptions/programoptions_test.cpp @@ -2,38 +2,11 @@ #include "programoptions_testutils.h" #include <vespa/vespalib/util/programoptions.h> -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> #include <iostream> namespace vespalib { -class Test : public vespalib::TestApp -{ -public: - void testSyntaxPage(); - void testNormalUsage(); - void testFailures(); - void testVectorArgument(); - void testAllHiddenOption(); - void testOptionsAfterArguments(); - int Main() override; -}; - -int -Test::Main() -{ - TEST_INIT("programoptions_test"); - srandom(1); - testSyntaxPage(); - testNormalUsage(); - testFailures(); - testVectorArgument(); - testAllHiddenOption(); - // Currently not supported - // testOptionsAfterArguments(); - TEST_DONE(); -} - struct MyOptions : public ProgramOptions { bool boolOpt; bool boolWithDefOpt; @@ -86,7 +59,8 @@ MyOptions::MyOptions(int argc, const char* const* argv) MyOptions::~MyOptions() { } -void Test::testSyntaxPage() { +TEST(ProgramOptionsTest, test_syntax_page) +{ AppOptions opts("myapp"); MyOptions options(opts.getArgCount(), opts.getArguments()); std::ostringstream actual; @@ -116,41 +90,42 @@ void Test::testSyntaxPage() { "Advanced options:\n" " -p --properties <key> <value> : Property map (default empty)\n" ); - EXPECT_EQUAL(expected, actual.str()); + EXPECT_EQ(expected, actual.str()); } -void Test::testNormalUsage() { +TEST(ProgramOptionsTest, test_normal_usage) +{ { AppOptions opts("myapp -b --uintopt 4 -s foo tit 1 tei 6"); MyOptions options(opts.getArgCount(), opts.getArguments()); options.parse(); - EXPECT_EQUAL(true, options.boolOpt); - EXPECT_EQUAL(true, options.boolWithDefOpt); - EXPECT_EQUAL(5, options.intOpt); - EXPECT_EQUAL(4u, options.uintOpt); - EXPECT_APPROX(4, options.floatOpt, 0.00001); - EXPECT_EQUAL("foo", options.stringOpt); - EXPECT_EQUAL("tit", options.argString); - EXPECT_EQUAL(1, options.argInt); - EXPECT_EQUAL("tei", options.argOptionalString); - EXPECT_EQUAL(0u, options.properties.size()); - EXPECT_EQUAL(6, options.anotherOptionalArg); + EXPECT_EQ(true, options.boolOpt); + EXPECT_EQ(true, options.boolWithDefOpt); + EXPECT_EQ(5, options.intOpt); + EXPECT_EQ(4u, options.uintOpt); + EXPECT_NEAR(4, options.floatOpt, 0.00001); + EXPECT_EQ("foo", options.stringOpt); + EXPECT_EQ("tit", options.argString); + EXPECT_EQ(1, options.argInt); + EXPECT_EQ("tei", options.argOptionalString); + EXPECT_EQ(0u, options.properties.size()); + EXPECT_EQ(6, options.anotherOptionalArg); } { AppOptions opts("myapp --uintopt 6 tit 1"); MyOptions options(opts.getArgCount(), opts.getArguments()); options.parse(); - EXPECT_EQUAL(false, options.boolOpt); - EXPECT_EQUAL(true, options.boolWithDefOpt); - EXPECT_EQUAL(5, options.intOpt); - EXPECT_EQUAL(6u, options.uintOpt); - EXPECT_APPROX(4, options.floatOpt, 0.00001); - EXPECT_EQUAL("ballalaika", options.stringOpt); - EXPECT_EQUAL("tit", options.argString); - EXPECT_EQUAL(1, options.argInt); - EXPECT_EQUAL("foo", options.argOptionalString); - EXPECT_EQUAL(0u, options.properties.size()); - EXPECT_EQUAL(3, options.anotherOptionalArg); + EXPECT_EQ(false, options.boolOpt); + EXPECT_EQ(true, options.boolWithDefOpt); + EXPECT_EQ(5, options.intOpt); + EXPECT_EQ(6u, options.uintOpt); + EXPECT_NEAR(4, options.floatOpt, 0.00001); + EXPECT_EQ("ballalaika", options.stringOpt); + EXPECT_EQ("tit", options.argString); + EXPECT_EQ(1, options.argInt); + EXPECT_EQ("foo", options.argOptionalString); + EXPECT_EQ(0u, options.properties.size()); + EXPECT_EQ(3, options.anotherOptionalArg); } // Arguments coming after options. // (Required for nesting of short options) @@ -158,62 +133,63 @@ void Test::testNormalUsage() { AppOptions opts("myapp --uintopt --intopt 6 -8 tit 1 tei"); MyOptions options(opts.getArgCount(), opts.getArguments()); options.parse(); - EXPECT_EQUAL(false, options.boolOpt); - EXPECT_EQUAL(true, options.boolWithDefOpt); - EXPECT_EQUAL(-8, options.intOpt); - EXPECT_EQUAL(6u, options.uintOpt); - EXPECT_APPROX(4, options.floatOpt, 0.00001); - EXPECT_EQUAL("ballalaika", options.stringOpt); - EXPECT_EQUAL("tit", options.argString); - EXPECT_EQUAL(1, options.argInt); - EXPECT_EQUAL("tei", options.argOptionalString); - EXPECT_EQUAL(0u, options.properties.size()); + EXPECT_EQ(false, options.boolOpt); + EXPECT_EQ(true, options.boolWithDefOpt); + EXPECT_EQ(-8, options.intOpt); + EXPECT_EQ(6u, options.uintOpt); + EXPECT_NEAR(4, options.floatOpt, 0.00001); + EXPECT_EQ("ballalaika", options.stringOpt); + EXPECT_EQ("tit", options.argString); + EXPECT_EQ(1, options.argInt); + EXPECT_EQ("tei", options.argOptionalString); + EXPECT_EQ(0u, options.properties.size()); } { AppOptions opts( "myapp -uib 6 -8 --boolwithdef tit 1 tei"); MyOptions options(opts.getArgCount(), opts.getArguments()); options.parse(); - EXPECT_EQUAL(true, options.boolOpt); - EXPECT_EQUAL(false, options.boolWithDefOpt); - EXPECT_EQUAL(-8, options.intOpt); - EXPECT_EQUAL(6u, options.uintOpt); - EXPECT_APPROX(4, options.floatOpt, 0.00001); - EXPECT_EQUAL("ballalaika", options.stringOpt); - EXPECT_EQUAL("tit", options.argString); - EXPECT_EQUAL(1, options.argInt); - EXPECT_EQUAL("tei", options.argOptionalString); - EXPECT_EQUAL(0u, options.properties.size()); + EXPECT_EQ(true, options.boolOpt); + EXPECT_EQ(false, options.boolWithDefOpt); + EXPECT_EQ(-8, options.intOpt); + EXPECT_EQ(6u, options.uintOpt); + EXPECT_NEAR(4, options.floatOpt, 0.00001); + EXPECT_EQ("ballalaika", options.stringOpt); + EXPECT_EQ("tit", options.argString); + EXPECT_EQ(1, options.argInt); + EXPECT_EQ("tei", options.argOptionalString); + EXPECT_EQ(0u, options.properties.size()); } // Properties { AppOptions opts("myapp -u 6 -p foo bar --prop hmm brr tit 1 tei"); MyOptions options(opts.getArgCount(), opts.getArguments()); options.parse(); - EXPECT_EQUAL(false, options.boolOpt); - EXPECT_EQUAL(true, options.boolWithDefOpt); - EXPECT_EQUAL(5, options.intOpt); - EXPECT_EQUAL(6u, options.uintOpt); - EXPECT_APPROX(4, options.floatOpt, 0.00001); - EXPECT_EQUAL("ballalaika", options.stringOpt); - EXPECT_EQUAL("tit", options.argString); - EXPECT_EQUAL(1, options.argInt); - EXPECT_EQUAL("tei", options.argOptionalString); - EXPECT_EQUAL(2u, options.properties.size()); - EXPECT_EQUAL("bar", options.properties["foo"]); - EXPECT_EQUAL("brr", options.properties["hmm"]); + EXPECT_EQ(false, options.boolOpt); + EXPECT_EQ(true, options.boolWithDefOpt); + EXPECT_EQ(5, options.intOpt); + EXPECT_EQ(6u, options.uintOpt); + EXPECT_NEAR(4, options.floatOpt, 0.00001); + EXPECT_EQ("ballalaika", options.stringOpt); + EXPECT_EQ("tit", options.argString); + EXPECT_EQ(1, options.argInt); + EXPECT_EQ("tei", options.argOptionalString); + EXPECT_EQ(2u, options.properties.size()); + EXPECT_EQ("bar", options.properties["foo"]); + EXPECT_EQ("brr", options.properties["hmm"]); } } -void Test::testFailures() { +TEST(ProgramOptionsTest, test_failures) +{ // Non-existing long option { AppOptions opts("myapp -b --uintopt 4 -s foo --none"); MyOptions options(opts.getArgCount(), opts.getArguments()); try{ options.parse(); - TEST_FATAL("Expected exception"); + FAIL() << "Expected exception"; } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("Invalid option 'none'.", e.getMessage()); + EXPECT_EQ("Invalid option 'none'.", e.getMessage()); } } // Non-existing short option @@ -222,9 +198,9 @@ void Test::testFailures() { MyOptions options(opts.getArgCount(), opts.getArguments()); try{ options.parse(); - TEST_FATAL("Expected exception"); + FAIL() << "Expected exception"; } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("Invalid option 'q'.", e.getMessage()); + EXPECT_EQ("Invalid option 'q'.", e.getMessage()); } } // Lacking option argument @@ -233,9 +209,9 @@ void Test::testFailures() { MyOptions options(opts.getArgCount(), opts.getArguments()); try{ options.parse(); - TEST_FATAL("Expected exception"); + FAIL() << "Expected exception"; } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("Option 's' needs 1 arguments. Only 0 available.", + EXPECT_EQ("Option 's' needs 1 arguments. Only 0 available.", e.getMessage()); } } @@ -245,35 +221,21 @@ void Test::testFailures() { MyOptions options(opts.getArgCount(), opts.getArguments()); try{ options.parse(); - TEST_FATAL("Expected exception"); + FAIL() << "Expected exception"; } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("The argument '3000000000' can not be interpreted as a " + EXPECT_EQ("The argument '3000000000' can not be interpreted as a " "number of type int.", e.getMessage()); } } - // Negative value to unsigned var (Currently doesnt fail) -/* - { - AppOptions opts("myapp -b --uintopt -1 foo 0"); - MyOptions options(opts.getArgCount(), opts.getArguments()); - try{ - options.parse(); - TEST_FATAL("Expected exception"); - } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("The argument '-1' can not be interpreted as a " - "number of type uint.", e.getMessage()); - } - } - */ // Lacking required option { AppOptions opts("myapp -b"); MyOptions options(opts.getArgCount(), opts.getArguments()); try{ options.parse(); - TEST_FATAL("Expected exception"); + FAIL() << "Expected exception"; } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("Option 'uintopt' has no default and must be set.", + EXPECT_EQ("Option 'uintopt' has no default and must be set.", e.getMessage()); } } @@ -283,9 +245,9 @@ void Test::testFailures() { MyOptions options(opts.getArgCount(), opts.getArguments()); try{ options.parse(); - TEST_FATAL("Expected exception"); + FAIL() << "Expected exception"; } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("Insufficient data is given to set required argument " + EXPECT_EQ("Insufficient data is given to set required argument " "'argInt'.", e.getMessage()); } @@ -296,16 +258,16 @@ void Test::testFailures() { MyOptions options(opts.getArgCount(), opts.getArguments()); try{ options.parse(); - TEST_FATAL("Expected exception"); + FAIL() << "Expected exception"; } catch (InvalidCommandLineArgumentsException& e) { - EXPECT_EQUAL("The argument 'en' can not be interpreted as a number " + EXPECT_EQ("The argument 'en' can not be interpreted as a number " "of type int.", e.getMessage()); } } } -void Test::testVectorArgument() +TEST(ProgramOptionsTest, test_vector_argument) { AppOptions opts("myapp foo bar baz"); std::vector<std::string> args; @@ -318,16 +280,16 @@ void Test::testVectorArgument() "Arguments:\n" " ids (string[]) : Vector element\n" ); - EXPECT_EQUAL(expected, actual.str()); + EXPECT_EQ(expected, actual.str()); options.parse(); - EXPECT_EQUAL(3u, args.size()); - EXPECT_EQUAL("foo", args[0]); - EXPECT_EQUAL("bar", args[1]); - EXPECT_EQUAL("baz", args[2]); + EXPECT_EQ(3u, args.size()); + EXPECT_EQ("foo", args[0]); + EXPECT_EQ("bar", args[1]); + EXPECT_EQ("baz", args[2]); } -void Test::testAllHiddenOption() +TEST(ProgramOptionsTest, test_all_hidden_options) { AppOptions opts("myapp --foo bar"); std::string option; @@ -337,25 +299,12 @@ void Test::testAllHiddenOption() std::ostringstream actual; options.writeSyntaxPage(actual); std::string expected("\nUsage: myapp\n"); - EXPECT_EQUAL(expected, actual.str()); + EXPECT_EQ(expected, actual.str()); options.parse(); - EXPECT_EQUAL("bar", option); -} - -void Test::testOptionsAfterArguments() -{ - AppOptions opts("myapp bar --foo baz"); - std::string option; - std::string argument; - ProgramOptions options(opts.getArgCount(), opts.getArguments()); - options.addOption("foo", option, "Description"); - options.addArgument("arg", argument, "Description"); - options.parse(); - EXPECT_EQUAL("baz", option); - EXPECT_EQUAL("bar", argument); + EXPECT_EQ("bar", option); } } // vespalib -TEST_APPHOOK(vespalib::Test) +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/sharedptr/CMakeLists.txt b/vespalib/src/tests/sharedptr/CMakeLists.txt index 052efb19447..6e038ed31c5 100644 --- a/vespalib/src/tests/sharedptr/CMakeLists.txt +++ b/vespalib/src/tests/sharedptr/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_ptrholder_test_app TEST ptrholder.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_ptrholder_test_app COMMAND vespalib_ptrholder_test_app) diff --git a/vespalib/src/tests/sharedptr/ptrholder.cpp b/vespalib/src/tests/sharedptr/ptrholder.cpp index 8dc3bba2722..e6d1710247b 100644 --- a/vespalib/src/tests/sharedptr/ptrholder.cpp +++ b/vespalib/src/tests/sharedptr/ptrholder.cpp @@ -1,20 +1,11 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/vespalib/util/ptrholder.h> -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> using vespalib::PtrHolder; -class Test : public vespalib::TestApp -{ -public: - void testEmpty(); - void testSimple(); - int Main() override; -}; - - struct Data { int ctorCnt; @@ -39,8 +30,7 @@ using PT = std::shared_ptr<DataRef>; using HOLD = PtrHolder<DataRef>; -void -Test::testEmpty() +TEST(PtrHolderTest, test_empty) { HOLD hold; EXPECT_TRUE(hold.get().get() == NULL); @@ -56,8 +46,7 @@ Test::testEmpty() } -void -Test::testSimple() +TEST(PtrHolderTest, test_simple) { Data data; HOLD hold; @@ -86,14 +75,4 @@ Test::testSimple() EXPECT_TRUE(data.dtorCnt == 2); } - -int -Test::Main() -{ - TEST_INIT("ptrholder_test"); - testEmpty(); - testSimple(); - TEST_DONE(); -} - -TEST_APPHOOK(Test) +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/stllike/CMakeLists.txt b/vespalib/src/tests/stllike/CMakeLists.txt index 7fa8e0cbd1f..644bd4f66d2 100644 --- a/vespalib/src/tests/stllike/CMakeLists.txt +++ b/vespalib/src/tests/stllike/CMakeLists.txt @@ -25,6 +25,7 @@ vespa_add_executable(vespalib_asciistream_test_app TEST asciistream_test.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_asciistream_test_app COMMAND vespalib_asciistream_test_app) vespa_add_executable(vespalib_hashtable_test_app TEST diff --git a/vespalib/src/tests/stllike/asciistream_test.cpp b/vespalib/src/tests/stllike/asciistream_test.cpp index 05068fb102c..cd710c0adb4 100644 --- a/vespalib/src/tests/stllike/asciistream_test.cpp +++ b/vespalib/src/tests/stllike/asciistream_test.cpp @@ -1,49 +1,31 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/stllike/asciistream.h> +#include <vespa/vespalib/testkit/test_path.h> #include <vespa/vespalib/util/exceptions.h> #include <vespa/vespalib/locale/c.h> +#include <cmath> #include <iomanip> #include <float.h> using namespace vespalib; -class AsciistreamTest : public TestApp -{ -public: - int Main() override; - template <typename T> - void verify(T first, T second, const char * firstResult, const char * secondResult, char delim); - template <typename T> - void verifyBothWays(T value, const char * firstResult); - void testIntegerManip(); - void testFill(); - void testString(); - void testCreateFromFile(); - void testWriteThenRead(); - void testGetLine(); - void testCopyConstruct(); - void testMoveIsWellDefined(); - void testIllegalNumbers(); - void testDouble(); - void testFloat(); - void testStateSaver(); -}; +namespace { template <typename T> void -AsciistreamTest::verifyBothWays(T value, const char * expected) +verifyBothWays(T value, const char * expected, const vespalib::string& label) { + SCOPED_TRACE(label); asciistream os; os << value; - EXPECT_EQUAL(os.str(), string(expected)); - EXPECT_EQUAL(os.size(), strlen(expected)); + EXPECT_EQ(os.str(), string(expected)); + EXPECT_EQ(os.size(), strlen(expected)); { T v; os >> v; - EXPECT_EQUAL(value, v); + EXPECT_EQ(value, v); EXPECT_TRUE(os.empty()); } @@ -51,255 +33,253 @@ AsciistreamTest::verifyBothWays(T value, const char * expected) os << " " << expected; T v; os >> v; - EXPECT_EQUAL(value, v); + EXPECT_EQ(value, v); EXPECT_TRUE(os.empty()); - EXPECT_EQUAL(0u, os.size()); + EXPECT_EQ(0u, os.size()); } } template <typename T> void -AsciistreamTest::verify(T first, T second, const char * firstResult, const char * secondResult, char delim) +verify(T first, T second, const char * firstResult, const char * secondResult, char delim, const vespalib::string& label) { + SCOPED_TRACE(label); asciistream os; std::ostringstream ss; os << first; ss << first; - EXPECT_EQUAL(os.str(), string(firstResult)); - EXPECT_EQUAL(os.size(), strlen(firstResult)); - EXPECT_EQUAL(ss.str().size(), strlen(firstResult)); - EXPECT_EQUAL(strcmp(ss.str().c_str(), firstResult), 0); + EXPECT_EQ(os.str(), string(firstResult)); + EXPECT_EQ(os.size(), strlen(firstResult)); + EXPECT_EQ(ss.str().size(), strlen(firstResult)); + EXPECT_EQ(strcmp(ss.str().c_str(), firstResult), 0); os << delim << second; ss << delim << second; - EXPECT_EQUAL(os.size(), strlen(secondResult)); - EXPECT_EQUAL(ss.str().size(), strlen(secondResult)); - EXPECT_EQUAL(strcmp(os.c_str(), secondResult), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), secondResult), 0); + EXPECT_EQ(os.size(), strlen(secondResult)); + EXPECT_EQ(ss.str().size(), strlen(secondResult)); + EXPECT_EQ(strcmp(os.c_str(), secondResult), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), secondResult), 0); } -void -AsciistreamTest::testIllegalNumbers() +} + +TEST(AsciistreamTest, test_illegal_numbers) { { asciistream is("777777777777"); uint16_t s(0); - EXPECT_EXCEPTION(is >> s, IllegalArgumentException, "strToInt value '777777777777' is outside of range"); - EXPECT_EQUAL(12u, is.size()); + EXPECT_THROW(is >> s, IllegalArgumentException); + EXPECT_EQ(12u, is.size()); uint32_t i(0); - EXPECT_EXCEPTION(is >> i, IllegalArgumentException, "strToInt value '777777777777' is outside of range"); - EXPECT_EQUAL(12u, is.size()); + EXPECT_THROW(is >> i, IllegalArgumentException); + EXPECT_EQ(12u, is.size()); int16_t si(0); - EXPECT_EXCEPTION(is >> si, IllegalArgumentException, "strToInt value '777777777777' is outside of range"); - EXPECT_EQUAL(12u, is.size()); + EXPECT_THROW(is >> si, IllegalArgumentException); + EXPECT_EQ(12u, is.size()); int32_t ii(0); - EXPECT_EXCEPTION(is >> ii, IllegalArgumentException, "strToInt value '777777777777' is outside of range"); - EXPECT_EQUAL(12u, is.size()); + EXPECT_THROW(is >> ii, IllegalArgumentException); + EXPECT_EQ(12u, is.size()); is << "777777777777"; - EXPECT_EQUAL(24u, is.size()); + EXPECT_EQ(24u, is.size()); uint64_t l(0); - EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "value '777777777777777777777777' is outside of range"); - EXPECT_EQUAL(24u, is.size()); + EXPECT_THROW(is >> l, IllegalArgumentException); + EXPECT_EQ(24u, is.size()); int64_t li(0); - EXPECT_EXCEPTION(is >> li, IllegalArgumentException, "value '777777777777777777777777' is outside of range"); - EXPECT_EQUAL(24u, is.size()); + EXPECT_THROW(is >> li, IllegalArgumentException); + EXPECT_EQ(24u, is.size()); } { asciistream is("-77"); uint16_t s(0); - EXPECT_EXCEPTION(is >> s, IllegalArgumentException, "Illegal strToInt value '-77'"); - EXPECT_EQUAL(3u, is.size()); + EXPECT_THROW(is >> s, IllegalArgumentException); + EXPECT_EQ(3u, is.size()); uint32_t i(0); - EXPECT_EXCEPTION(is >> i, IllegalArgumentException, "Illegal strToInt value '-77'"); - EXPECT_EQUAL(3u, is.size()); + EXPECT_THROW(is >> i, IllegalArgumentException); + EXPECT_EQ(3u, is.size()); } { asciistream is("7777777777777777777777777777777777777777"); - EXPECT_EQUAL(40u, is.size()); + EXPECT_EQ(40u, is.size()); float f(0); - EXPECT_EXCEPTION(is >> f, IllegalArgumentException, "float value '7777777777777777777777777777777777777777' is outside of range"); - EXPECT_EQUAL(40u, is.size()); + EXPECT_THROW(is >> f, IllegalArgumentException); + EXPECT_EQ(40u, is.size()); vespalib::string tmp = is.str(); is << "e" << tmp; - EXPECT_EQUAL(81u, is.size()); + EXPECT_EQ(81u, is.size()); double d(0); - EXPECT_EXCEPTION(is >> d, IllegalArgumentException, "double value '7777777777777777777777777777777777777777e7777777777777777777777777777777777777777' is outside of range"); - EXPECT_EQUAL(81u, is.size()); + EXPECT_THROW(is >> d, IllegalArgumentException); + EXPECT_EQ(81u, is.size()); } { asciistream is("a"); char c(' '); - EXPECT_EQUAL(1u, is.size()); + EXPECT_EQ(1u, is.size()); is >> c; - EXPECT_EQUAL('a', c); + EXPECT_EQ('a', c); EXPECT_TRUE(is.empty()); - EXPECT_EXCEPTION(is >> c, IllegalArgumentException, "buffer underflow at pos 1."); + EXPECT_THROW(is >> c, IllegalArgumentException); EXPECT_TRUE(is.empty()); unsigned char u(' '); - EXPECT_EXCEPTION(is >> u, IllegalArgumentException, "buffer underflow at pos 1."); + EXPECT_THROW(is >> u, IllegalArgumentException); EXPECT_TRUE(is.empty()); bool b(false); - EXPECT_EXCEPTION(is >> b, IllegalArgumentException, "buffer underflow at pos 1."); + EXPECT_THROW(is >> b, IllegalArgumentException); EXPECT_TRUE(is.empty()); { uint32_t l(0); - EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "buffer underflow at pos 0."); + EXPECT_THROW(is >> l, IllegalArgumentException); EXPECT_TRUE(is.empty()); } { int32_t l(0); - EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "buffer underflow at pos 0"); + EXPECT_THROW(is >> l, IllegalArgumentException); EXPECT_TRUE(is.empty()); } { float l(0); - EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "Failed decoding a float from ''."); + EXPECT_THROW(is >> l, IllegalArgumentException); EXPECT_TRUE(is.empty()); } { double l(0); - EXPECT_EXCEPTION(is >> l, IllegalArgumentException, "Failed decoding a double from ''."); + EXPECT_THROW(is >> l, IllegalArgumentException); EXPECT_TRUE(is.empty()); } } } -void -AsciistreamTest::testCopyConstruct() +TEST(AsciistreamTest, test_copy_construct) { asciistream os; os << "test1"; asciistream os2(os); - EXPECT_EQUAL(os.str(), os2.str()); + EXPECT_EQ(os.str(), os2.str()); os2 << " test2"; EXPECT_FALSE(os.str() == os2.str()); asciistream os3(os); os3 = os2; - EXPECT_EQUAL(os2.str(), os3.str()); + EXPECT_EQ(os2.str(), os3.str()); os.swap(os2); - EXPECT_EQUAL(os.str(), os3.str()); + EXPECT_EQ(os.str(), os3.str()); EXPECT_FALSE(os3.str() == os2.str()); os.swap(os2); EXPECT_TRUE(os3.str() == os2.str()); } -void -AsciistreamTest::testMoveIsWellDefined() +TEST(AsciistreamTest, test_move_is_well_defined) { asciistream read_only("hello world"); asciistream dest(std::move(read_only)); - EXPECT_EQUAL("hello world", dest.str()); + EXPECT_EQ("hello world", dest.str()); read_only = asciistream("a string long enough to not be short string optimized"); dest = std::move(read_only); - EXPECT_EQUAL("a string long enough to not be short string optimized", dest.str()); + EXPECT_EQ("a string long enough to not be short string optimized", dest.str()); asciistream written_src; written_src << "a foo walks into a bar"; dest = std::move(written_src); - EXPECT_EQUAL("a foo walks into a bar", dest.str()); + EXPECT_EQ("a foo walks into a bar", dest.str()); } -void -AsciistreamTest::testIntegerManip() +TEST(AsciistreamTest, test_integer_manip) { asciistream os; std::ostringstream ss; os << 10; ss << 10; - EXPECT_EQUAL(os.size(), 2u); - EXPECT_EQUAL(ss.str().size(), 2u); - EXPECT_EQUAL(strcmp(os.c_str(), "10"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "10"), 0); + EXPECT_EQ(os.size(), 2u); + EXPECT_EQ(ss.str().size(), 2u); + EXPECT_EQ(strcmp(os.c_str(), "10"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "10"), 0); os << ' ' << dec << 10; ss << ' ' << std::dec << 10; - EXPECT_EQUAL(os.size(), 5u); - EXPECT_EQUAL(ss.str().size(), 5u); - EXPECT_EQUAL(strcmp(os.c_str(), "10 10"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "10 10"), 0); + EXPECT_EQ(os.size(), 5u); + EXPECT_EQ(ss.str().size(), 5u); + EXPECT_EQ(strcmp(os.c_str(), "10 10"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "10 10"), 0); os << ' ' << hex << 10 << ' ' << 11; ss << ' ' << std::hex << 10 << ' ' << 11; - EXPECT_EQUAL(os.size(), 9u); - EXPECT_EQUAL(ss.str().size(), 9u); - EXPECT_EQUAL(strcmp(os.c_str(), "10 10 a b"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "10 10 a b"), 0); + EXPECT_EQ(os.size(), 9u); + EXPECT_EQ(ss.str().size(), 9u); + EXPECT_EQ(strcmp(os.c_str(), "10 10 a b"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "10 10 a b"), 0); os << ' ' << oct << 10; ss << ' ' << std::oct << 10; - EXPECT_EQUAL(os.size(), 12u); - EXPECT_EQUAL(ss.str().size(), 12u); - EXPECT_EQUAL(strcmp(os.c_str(), "10 10 a b 12"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "10 10 a b 12"), 0); + EXPECT_EQ(os.size(), 12u); + EXPECT_EQ(ss.str().size(), 12u); + EXPECT_EQ(strcmp(os.c_str(), "10 10 a b 12"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "10 10 a b 12"), 0); // std::bin not supported by std::streams. os << ' ' << bin << 10; - EXPECT_EQUAL(os.size(), 19u); - EXPECT_EQUAL(strcmp(os.c_str(), "10 10 a b 12 0b1010"), 0); + EXPECT_EQ(os.size(), 19u); + EXPECT_EQ(strcmp(os.c_str(), "10 10 a b 12 0b1010"), 0); void *fooptr = reinterpret_cast<void*>(0x1badbadc0ffeeull); // Also test that number base is restored OK after ptr print os << dec << ' ' << fooptr << ' ' << 1234; ss << std::dec << ' ' << fooptr << ' ' << 1234; - EXPECT_EQUAL(std::string("10 10 a b 12 0b1010 0x1badbadc0ffee 1234"), os.str()); - EXPECT_EQUAL(std::string("10 10 a b 12 0x1badbadc0ffee 1234"), ss.str()); + EXPECT_EQ(std::string("10 10 a b 12 0b1010 0x1badbadc0ffee 1234"), os.str()); + EXPECT_EQ(std::string("10 10 a b 12 0x1badbadc0ffee 1234"), ss.str()); int i = 0; const char *digits = "12345"; std::string ffs(digits, 4); std::istringstream std_istr(ffs); std_istr >> i; - EXPECT_EQUAL(1234, i); + EXPECT_EQ(1234, i); stringref firstfour(digits, 4); asciistream istr(firstfour); istr >> i; - EXPECT_EQUAL(1234, i); + EXPECT_EQ(1234, i); } -void -AsciistreamTest::testFill() +TEST(AsciistreamTest, test_fill) { { asciistream os; std::ostringstream ss; os << 10 << ' ' << setfill('h') << 11; ss << 10 << ' ' << std::setfill('h') << 11; - EXPECT_EQUAL(os.size(), 5u); - EXPECT_EQUAL(ss.str().size(), 5u); - EXPECT_EQUAL(strcmp(os.c_str(), "10 11"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "10 11"), 0); + EXPECT_EQ(os.size(), 5u); + EXPECT_EQ(ss.str().size(), 5u); + EXPECT_EQ(strcmp(os.c_str(), "10 11"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "10 11"), 0); os << setw(4) << 10 << ' ' << 11; ss << std::setw(4) << 10 << ' ' << 11; - EXPECT_EQUAL(os.size(), 12u); - EXPECT_EQUAL(ss.str().size(), 12u); - EXPECT_EQUAL(strcmp(os.c_str(), "10 11hh10 11"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "10 11hh10 11"), 0); + EXPECT_EQ(os.size(), 12u); + EXPECT_EQ(ss.str().size(), 12u); + EXPECT_EQ(strcmp(os.c_str(), "10 11hh10 11"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "10 11hh10 11"), 0); os << setw(4) << 10 << ' ' << 11; ss << std::setw(4) << 10 << ' ' << 11; - EXPECT_EQUAL(os.size(), 19u); - EXPECT_EQUAL(ss.str().size(), 19u); - EXPECT_EQUAL(strcmp(os.c_str(), "10 11hh10 11hh10 11"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "10 11hh10 11hh10 11"), 0); + EXPECT_EQ(os.size(), 19u); + EXPECT_EQ(ss.str().size(), 19u); + EXPECT_EQ(strcmp(os.c_str(), "10 11hh10 11hh10 11"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "10 11hh10 11hh10 11"), 0); } { asciistream os; std::ostringstream ss; os << setfill('X') << setw(19) << 'a'; ss << std::setfill('X') << std::setw(19) << 'a'; - EXPECT_EQUAL(os.size(), 19u); - EXPECT_EQUAL(ss.str().size(), 19u); - EXPECT_EQUAL(strcmp(os.c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); + EXPECT_EQ(os.size(), 19u); + EXPECT_EQ(ss.str().size(), 19u); + EXPECT_EQ(strcmp(os.c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); } { asciistream os; std::ostringstream ss; os << setfill('X') << setw(19) << "a"; ss << std::setfill('X') << std::setw(19) << "a"; - EXPECT_EQUAL(os.size(), 19u); - EXPECT_EQUAL(ss.str().size(), 19u); - EXPECT_EQUAL(strcmp(os.c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); + EXPECT_EQ(os.size(), 19u); + EXPECT_EQ(ss.str().size(), 19u); + EXPECT_EQ(strcmp(os.c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXXXXa"), 0); } { float f(8.9); @@ -307,10 +287,10 @@ AsciistreamTest::testFill() std::ostringstream ss; os << setfill('X') << setw(19) << f; ss << std::setfill('X') << std::setw(19) << f; - EXPECT_EQUAL(os.size(), 19u); - EXPECT_EQUAL(ss.str().size(), 19u); - EXPECT_EQUAL(strcmp(os.c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); + EXPECT_EQ(os.size(), 19u); + EXPECT_EQ(ss.str().size(), 19u); + EXPECT_EQ(strcmp(os.c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); } { double f(8.9); @@ -318,16 +298,15 @@ AsciistreamTest::testFill() std::ostringstream ss; os << setfill('X') << setw(19) << f; ss << std::setfill('X') << std::setw(19) << f; - EXPECT_EQUAL(os.size(), 19u); - EXPECT_EQUAL(ss.str().size(), 19u); - EXPECT_EQUAL(strcmp(os.c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); - EXPECT_EQUAL(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); + EXPECT_EQ(os.size(), 19u); + EXPECT_EQ(ss.str().size(), 19u); + EXPECT_EQ(strcmp(os.c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); + EXPECT_EQ(strcmp(ss.str().c_str(), "XXXXXXXXXXXXXXXX8.9"), 0); } } -void -AsciistreamTest::testString() +TEST(AsciistreamTest, test_string) { std::string ss("a"); @@ -335,56 +314,55 @@ AsciistreamTest::testString() { std::ostringstream oss; oss << ss << vs; - EXPECT_EQUAL("aa", oss.str()); + EXPECT_EQ("aa", oss.str()); } { asciistream oss; oss << ss << vs; - EXPECT_EQUAL("aa", oss.str()); + EXPECT_EQ("aa", oss.str()); } { std::istringstream iss("b c"); iss >> ss >> vs; - EXPECT_EQUAL("b", ss); - EXPECT_EQUAL("c", vs); + EXPECT_EQ("b", ss); + EXPECT_EQ("c", vs); } { std::istringstream iss("b c"); iss >> vs >> ss; - EXPECT_EQUAL("b", vs); - EXPECT_EQUAL("c", ss); + EXPECT_EQ("b", vs); + EXPECT_EQ("c", ss); } { asciistream iss("b c"); iss >> ss >> vs; - EXPECT_EQUAL("b", ss); - EXPECT_EQUAL("c", vs); + EXPECT_EQ("b", ss); + EXPECT_EQ("c", vs); } { asciistream iss("b c"); iss >> vs >> ss; - EXPECT_EQUAL("b", vs); - EXPECT_EQUAL("c", ss); + EXPECT_EQ("b", vs); + EXPECT_EQ("c", ss); } } -void -AsciistreamTest::testCreateFromFile() +TEST(AsciistreamTest, test_create_from_file) { asciistream is(asciistream::createFromFile("non-existing.txt")); EXPECT_TRUE(is.eof()); is = asciistream::createFromFile(TEST_PATH("test.txt")); EXPECT_FALSE(is.eof()); - EXPECT_EQUAL(12u, is.size()); + EXPECT_EQ(12u, is.size()); string s; is >> s; - EXPECT_EQUAL("line1", s); + EXPECT_EQ("line1", s); is >> s; - EXPECT_EQUAL("line2", s); + EXPECT_EQ("line2", s); EXPECT_FALSE(is.eof()); is >> s; - EXPECT_EQUAL("", s); + EXPECT_EQ("", s); EXPECT_TRUE(is.eof()); #ifdef __linux__ @@ -393,30 +371,28 @@ AsciistreamTest::testCreateFromFile() #endif } -void -AsciistreamTest::testWriteThenRead() +TEST(AsciistreamTest, test_write_then_read) { asciistream ios; ios << "3 words"; int n(0); string v; ios >> n >> v; - EXPECT_EQUAL(3, n); - EXPECT_EQUAL("words", v); + EXPECT_EQ(3, n); + EXPECT_EQ("words", v); EXPECT_TRUE(ios.eof()); } -void -AsciistreamTest::testGetLine() +TEST(AsciistreamTest, test_get_line) { asciistream is = asciistream("line 1\nline 2\nline 3"); string s; getline(is, s); - EXPECT_EQUAL("line 1", s); + EXPECT_EQ("line 1", s); getline(is, s); - EXPECT_EQUAL("line 2", s); + EXPECT_EQ("line 2", s); getline(is, s); - EXPECT_EQUAL("line 3", s); + EXPECT_EQ("line 3", s); } #define VERIFY_DOUBLE_SERIALIZATION(value, expected, format, precision) { \ @@ -424,11 +400,11 @@ AsciistreamTest::testGetLine() mystream << format; \ if (precision > 0) mystream << asciistream::Precision(precision); \ mystream << value; \ - EXPECT_EQUAL(expected, mystream.str()); \ + EXPECT_EQ(expected, mystream.str()); \ } -void -AsciistreamTest::testDouble() { +TEST(AsciistreamTest, test_double) +{ VERIFY_DOUBLE_SERIALIZATION(0.0, "0.000000", fixed, -1); VERIFY_DOUBLE_SERIALIZATION(0.0, "0.000000e+00", scientific, -1); VERIFY_DOUBLE_SERIALIZATION(0.0, "0", automatic, -1); @@ -502,119 +478,101 @@ AsciistreamTest::testDouble() { as << "1.0e-325"; dv = 42.0; as >> dv; - EXPECT_EQUAL(dv, 0.0); + EXPECT_EQ(dv, 0.0); as.clear(); as << "1.0e666"; dv = 42.0; - EXPECT_EXCEPTION(as >> dv, IllegalArgumentException, "double value '1.0e666' is outside of range."); - EXPECT_EQUAL(dv, 42.0); + EXPECT_THROW(as >> dv, IllegalArgumentException); + EXPECT_EQ(dv, 42.0); } -void -AsciistreamTest::testFloat() { +TEST(AsciistreamTest, test_float) +{ float f = 0; asciistream as("-5.490412E-39"); as >> f; - EXPECT_EQUAL(f, -5.490412E-39f); + EXPECT_EQ(f, -5.490412E-39f); as.clear(); as << "0.0001E-50"; f = 42.0; as >> f; - EXPECT_EQUAL(f, 0.0); + EXPECT_EQ(f, 0.0); as.clear(); as << "123.4E50"; f = 42.0; - EXPECT_EXCEPTION(as >> f, IllegalArgumentException, "float value '123.4E50' is outside of range."); - EXPECT_EQUAL(f, 42.0); + EXPECT_THROW(as >> f, IllegalArgumentException); + EXPECT_EQ(f, 42.0); errno = 0; char *ep; f = locale::c::strtof_au("-5.490412E-39", &ep); - EXPECT_EQUAL(f, -5.490412E-39f); - EXPECT_EQUAL(errno, 0); - EXPECT_EQUAL(*ep, 0); + EXPECT_EQ(f, -5.490412E-39f); + EXPECT_EQ(errno, 0); + EXPECT_EQ(*ep, 0); f = locale::c::strtof_au("0.0001E-50", &ep); - EXPECT_EQUAL(f, 0.0); - EXPECT_EQUAL(errno, 0); - EXPECT_EQUAL(*ep, 0); + EXPECT_EQ(f, 0.0); + EXPECT_EQ(errno, 0); + EXPECT_EQ(*ep, 0); f = locale::c::strtof_au("123.4E50", &ep); - EXPECT_EQUAL(f, HUGE_VALF); - EXPECT_EQUAL(errno, ERANGE); - EXPECT_EQUAL(*ep, 0); + EXPECT_EQ(f, HUGE_VALF); + EXPECT_EQ(errno, ERANGE); + EXPECT_EQ(*ep, 0); } -void -AsciistreamTest::testStateSaver() +TEST(AsciistreamTest, test_state_saver) { asciistream as; as << vespalib::hex << vespalib::setfill('0'); { asciistream::StateSaver stateSaver(as); as << vespalib::dec << vespalib::setfill('1'); - EXPECT_EQUAL(vespalib::dec, as.getBase()); - EXPECT_EQUAL('1', as.getFill()); + EXPECT_EQ(vespalib::dec, as.getBase()); + EXPECT_EQ('1', as.getFill()); } - ASSERT_EQUAL(vespalib::hex, as.getBase()); - ASSERT_EQUAL('0', as.getFill()); + ASSERT_EQ(vespalib::hex, as.getBase()); + ASSERT_EQ('0', as.getFill()); } -int -AsciistreamTest::Main() +TEST(AsciistreamTest, test_ascii_stream) { - TEST_INIT("asciistream_test"); - - TEST_DO(verify("per", "paal", "per", "per paal", ' ')); - TEST_DO(verify<float>(7.89, -1.3, "7.89", "7.89 -1.3", ' ')); - TEST_DO(verify<double>(7.89, -1.3, "7.89", "7.89 -1.3", ' ')); - TEST_DO(verify<bool>(true, false, "1", "1 0", ' ')); - TEST_DO(verify<char>(65, 66, "A", "A B", ' ')); - TEST_DO(verify<unsigned char>(65, 66, "A", "A B", ' ')); - TEST_DO(verify<signed char>(65, 66, "A", "A B", ' ')); -// TEST_DO(verify<int8_t>(65, -1, "65", "65 -1", ' ')); - TEST_DO(verify<int16_t>(0, -1, "0", "0 -1", ' ')); - TEST_DO(verify<int16_t>(789, -1, "789", "789 -1", ' ')); - TEST_DO(verify<int32_t>(789, -1, "789", "789 -1", ' ')); - TEST_DO(verify<int64_t>(789789789789789l, -1, "789789789789789", "789789789789789 -1", ' ')); -// TEST_DO(verify<uint8_t>(65, -1, "65", "65 255", ' ')); - TEST_DO(verify<uint16_t>(789, -1, "789", "789 65535", ' ')); - TEST_DO(verify<uint32_t>(789, -1, "789", "789 4294967295", ' ')); - TEST_DO(verify<uint64_t>(789789789789789l, -1, "789789789789789", "789789789789789 18446744073709551615", ' ')); - - TEST_DO(verifyBothWays<vespalib::string>("7.89", "7.89")); - TEST_DO(verifyBothWays<std::string>("7.89", "7.89")); - TEST_DO(verifyBothWays<float>(7.89, "7.89")); - TEST_DO(verifyBothWays<double>(7.89, "7.89")); - TEST_DO(verifyBothWays<bool>(true, "1")); - TEST_DO(verifyBothWays<bool>(false, "0")); - TEST_DO(verifyBothWays<char>(65, "A")); - TEST_DO(verifyBothWays<unsigned char>(65, "A")); - //TEST_DO(verifyBothWays<int8_t>(7, "7")); - //TEST_DO(verifyBothWays<uint8_t>(7, "7")); - TEST_DO(verifyBothWays<int16_t>(7, "7")); - TEST_DO(verifyBothWays<uint16_t>(7, "7")); - TEST_DO(verifyBothWays<int32_t>(7, "7")); - TEST_DO(verifyBothWays<uint32_t>(7, "7")); - TEST_DO(verifyBothWays<int64_t>(7, "7")); - TEST_DO(verifyBothWays<uint64_t>(7, "7")); - - testCopyConstruct(); - testMoveIsWellDefined(); - testIntegerManip(); - testFill(); - testString(); - testCreateFromFile(); - testWriteThenRead(); - testGetLine(); - testIllegalNumbers(); - testDouble(); - testFloat(); - testStateSaver(); - TEST_DONE(); + verify("per", "paal", "per", "per paal", ' ', "string"); + verify<float>(7.89, -1.3, "7.89", "7.89 -1.3", ' ', "float"); + verify<double>(7.89, -1.3, "7.89", "7.89 -1.3", ' ', "double"); + verify<bool>(true, false, "1", "1 0", ' ', "bool"); + verify<char>(65, 66, "A", "A B", ' ', "char"); + verify<unsigned char>(65, 66, "A", "A B", ' ', "unsigned char"); + verify<signed char>(65, 66, "A", "A B", ' ', "signed char"); +// verify<int8_t>(65, -1, "65", "65 -1", ' ', "int8_t"); + verify<int16_t>(0, -1, "0", "0 -1", ' ', "int16_t"); + verify<int16_t>(789, -1, "789", "789 -1", ' ', "int16_t again"); + verify<int32_t>(789, -1, "789", "789 -1", ' ', "int32_t"); + verify<int64_t>(789789789789789l, -1, "789789789789789", "789789789789789 -1", ' ', "int64_t"); +// verify<uint8_t>(65, -1, "65", "65 255", ' ', "uint8_t"); + verify<uint16_t>(789, -1, "789", "789 65535", ' ', "uint16_t"); + verify<uint32_t>(789, -1, "789", "789 4294967295", ' ', "uint32_t"); + verify<uint64_t>(789789789789789l, -1, "789789789789789", "789789789789789 18446744073709551615", ' ', "uint64_t"); + + verifyBothWays<vespalib::string>("7.89", "7.89", "vespalib::string"); + verifyBothWays<std::string>("7.89", "7.89", "stsd::string"); + verifyBothWays<float>(7.89, "7.89", "float"); + verifyBothWays<double>(7.89, "7.89", "double"); + verifyBothWays<bool>(true, "1", "bool"); + verifyBothWays<bool>(false, "0", "bool again"); + verifyBothWays<char>(65, "A", "char"); + verifyBothWays<unsigned char>(65, "A", "unsigned char"); + // verifyBothWays<int8_t>(7, "7", "int8_t"); + // verifyBothWays<uint8_t>(7, "7", "uint8_t"); + verifyBothWays<int16_t>(7, "7", "int16_t"); + verifyBothWays<uint16_t>(7, "7", "uint16_t"); + verifyBothWays<int32_t>(7, "7", "int32_t"); + verifyBothWays<uint32_t>(7, "7", "uint32_t"); + verifyBothWays<int64_t>(7, "7", "int64_t"); + verifyBothWays<uint64_t>(7, "7", "uint64_t"); } -TEST_APPHOOK(AsciistreamTest) +GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/tests/xmlserializable/CMakeLists.txt b/vespalib/src/tests/xmlserializable/CMakeLists.txt index 740f1f49bfb..4bd28a668a0 100644 --- a/vespalib/src/tests/xmlserializable/CMakeLists.txt +++ b/vespalib/src/tests/xmlserializable/CMakeLists.txt @@ -4,5 +4,6 @@ vespa_add_executable(vespalib_xmlserializable_test_app TEST xmlserializabletest.cpp DEPENDS vespalib + GTest::gtest ) vespa_add_test(NAME vespalib_xmlserializable_test_app COMMAND vespalib_xmlserializable_test_app) diff --git a/vespalib/src/tests/xmlserializable/xmlserializabletest.cpp b/vespalib/src/tests/xmlserializable/xmlserializabletest.cpp index c4d3fb9f1b9..3a6b933491a 100644 --- a/vespalib/src/tests/xmlserializable/xmlserializabletest.cpp +++ b/vespalib/src/tests/xmlserializable/xmlserializabletest.cpp @@ -1,35 +1,11 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#include <vespa/vespalib/testkit/testapp.h> +#include <vespa/vespalib/gtest/gtest.h> #include <vespa/vespalib/util/xmlstream.h> namespace vespalib { -class Test : public vespalib::TestApp -{ -public: - void testNormalUsage(); - void testEscaping(); - void testNesting(); - void testIndent(); - - int Main() override; -}; - -int -Test::Main() -{ - TEST_INIT("xmlserializables_test"); - srandom(1); - testNormalUsage(); - testEscaping(); - testNesting(); - testIndent(); - TEST_DONE(); -} - -void -Test::testNormalUsage() +TEST(XmlSerializableTest, test_normal_usage) { std::ostringstream ost; XmlOutputStream xos(ost); @@ -47,11 +23,10 @@ Test::testNormalUsage() "<door windowstate=\"up\"/>\n" "<description>This is a car description used to test</description>\n" "</car>"; - EXPECT_EQUAL(expected, ost.str()); + EXPECT_EQ(expected, ost.str()); } -void -Test::testEscaping() +TEST(XmlSerializableTest, test_escaping) { std::ostringstream ost; XmlOutputStream xos(ost); @@ -83,7 +58,7 @@ Test::testEscaping() "<auto1><>&	 \nfoo</auto1>\n" "<auto2 binaryencoding=\"base64\">PD4mCQANCmZvbw==</auto2>\n" "</__trash_->"; - EXPECT_EQUAL(expected, ost.str()); + EXPECT_EQ(expected, ost.str()); } namespace { @@ -103,8 +78,7 @@ namespace { }; } -void -Test::testNesting() +TEST(XmlSerializableTest, test_nesting) { std::ostringstream ost; XmlOutputStream xos(ost); @@ -127,11 +101,10 @@ Test::testNesting() "</door>\n" "<description>This is a car description used to test</description>\n" "</car>"; - EXPECT_EQUAL(expected, ost.str()); + EXPECT_EQ(expected, ost.str()); } -void -Test::testIndent() +TEST(XmlSerializableTest, test_indent) { std::ostringstream ost; XmlOutputStream xos(ost, " "); @@ -155,9 +128,9 @@ Test::testIndent() " <base binaryencoding=\"base64\">Zm9vYmFy</base>\n" " </nytag>\n" "</foo>"; - EXPECT_EQUAL(expected, ost.str()); + EXPECT_EQ(expected, ost.str()); } } // vespalib -TEST_APPHOOK(vespalib::Test) +GTEST_MAIN_RUN_ALL_TESTS() |