diff --git a/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java b/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java index 03a3dd1648f..42441491a23 100644 --- a/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java +++ b/stroom-analytics/stroom-analytics-impl/src/main/java/stroom/analytics/impl/AbstractAnalyticFieldListConsumer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.analytics.impl; import stroom.query.api.v2.SearchRequest; diff --git a/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java b/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java index 054842a29b7..33ee5e6ea4c 100644 --- a/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java +++ b/stroom-annotation/stroom-annotation-impl-db/src/main/java/stroom/annotation/impl/db/AnnotationDaoImpl.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.annotation.impl.db; import stroom.annotation.api.AnnotationFields; diff --git a/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java b/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java index cf8f692d4d5..a397914a438 100644 --- a/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java +++ b/stroom-annotation/stroom-annotation-impl/src/main/java/stroom/annotation/impl/AnnotationReceiverDecoratorFactory.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.annotation.impl; import stroom.annotation.api.AnnotationFields; diff --git a/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java b/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java index 0578575f7b4..a24d23b37cd 100644 --- a/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java +++ b/stroom-app/src/test/java/stroom/search/TestQueuesWithTaskContext.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.search; import stroom.query.language.functions.Val; @@ -114,8 +130,8 @@ void testTaskContext() { } else { try { queue.put(new Event(1, id, Val.of( - ValString.create("test"), - ValString.create("test")))); + ValString.create("test"), + ValString.create("test")))); } catch (CompleteException e) { throw new RuntimeException(e); } diff --git a/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java b/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java index 1fdf3f0fa97..9737c4974f3 100644 --- a/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java +++ b/stroom-index/stroom-index-impl-db/src/main/java/stroom/index/impl/db/IndexShardDaoImpl.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.index.impl.db; import stroom.db.util.ExpressionMapper; diff --git a/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java b/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java index b81c0e87402..acb5eea11a1 100644 --- a/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java +++ b/stroom-index/stroom-index-lucene553/src/main/java/stroom/index/lucene553/Lucene553ShardSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Crown Copyright + * Copyright 2016-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java b/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java index 2d99193208c..1b5553ba2ac 100644 --- a/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java +++ b/stroom-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/Lucene980ShardSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Crown Copyright + * Copyright 2016-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java b/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java index 4186bd5f7d4..3558b3777d0 100644 --- a/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java +++ b/stroom-meta/stroom-meta-impl-db/src/main/java/stroom/meta/impl/db/MetaDaoImpl.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.meta.impl.db; import stroom.data.retention.api.DataRetentionConfig; diff --git a/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java b/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java index 9a9c1524ae9..fbf10cc8439 100644 --- a/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java +++ b/stroom-query/stroom-query-api/src/main/java/stroom/query/api/v2/ParamUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Crown Copyright + * Copyright 2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ public static List parse(final String string) { } final String trimmed = string.trim(); - if (trimmed.length() == 0) { + if (trimmed.isEmpty()) { return Collections.emptyList(); } diff --git a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java index 4c3773feeb1..71965520a75 100644 --- a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java +++ b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/FlatResultCreator.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java index 1a3919a054f..4b0530b4e46 100644 --- a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java +++ b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/MapDataStore.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -132,7 +132,7 @@ public void accept(final Val[] values) { final boolean[] groupIndices = groupIndicesByDepth[depth]; final boolean[] valueIndices = valueIndicesByDepth[depth]; - Val[] groupValues = Val.empty(); + Val[] groupValues = Val.emptyArray(); if (groupSize > 0) { groupValues = new Val[groupSize]; } diff --git a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java index 1ede89ed318..634e2b71e2d 100644 --- a/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java +++ b/stroom-query/stroom-query-common/src/main/java/stroom/query/common/v2/StoredValueKeyFactoryImpl.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.common.v2; import stroom.query.language.functions.Generator; @@ -61,7 +77,7 @@ public Val[] getGroupValues(final int depth, final StoredValues storedValues) { } return values; } - return Val.empty(); + return Val.emptyArray(); } @Override diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java index 2e43e48ce46..5d18337d985 100644 --- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java +++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/AbstractDataStoreTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java index 497b52f6e85..88c5c433e9d 100644 --- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java +++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbDataStore.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java index 2ba86996cbe..b76faeaeeeb 100644 --- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java +++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestLmdbRowKeyFactoryFactory.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.common.v2; import stroom.bytebuffer.impl6.ByteBufferFactory; diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java index f7ad01a0e33..2fa06c1d79f 100644 --- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java +++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValHasher.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.common.v2; import stroom.query.language.functions.Val; diff --git a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java index 87154596a09..ff5d5dcfffd 100644 --- a/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java +++ b/stroom-query/stroom-query-common/src/test/java/stroom/query/common/v2/TestValueSerialisation.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.common.v2; import stroom.bytebuffer.impl6.ByteBufferFactory; diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java index c9e23a72325..54a9ff4be05 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractFunction.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -39,7 +39,7 @@ abstract class AbstractFunction implements Function, Appendable { @Override public void setParams(final Param[] params) throws ParseException { if (params.length < minParams || params.length > maxParams) { - throw new ExpressionException("Invalid number of parameters supplied for '" + name + "' + function"); + throw new ParseException("Invalid number of parameters supplied for '" + name + "' + function", 0); } this.params = params; diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java index 59d48f4e9ec..5714d1464b1 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractIncludeExclude.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,7 +52,7 @@ public void setParams(final Param[] params) throws ParseException { boolean found = false; for (int i = 1; i < params.length && !found; i++) { final String regex = params[i].toString(); - if (regex.length() == 0) { + if (regex.isEmpty()) { throw new ParseException( "An empty regex has been defined for argument of '" + name + "' function", 0); } @@ -78,7 +78,7 @@ public void setParams(final Param[] params) throws ParseException { if (params[i] instanceof Val) { // Test regex is valid. final String regex = params[i].toString(); - if (regex.length() == 0) { + if (regex.isEmpty()) { throw new ParseException( "An empty regex has been defined for argument of '" + name + "' function", 0); } @@ -106,6 +106,10 @@ public boolean hasAggregate() { abstract boolean inverse(); + + // -------------------------------------------------------------------------------- + + abstract static class AbstractGen extends AbstractManyChildGenerator { AbstractGen(final Generator[] childGenerators) { @@ -127,7 +131,7 @@ public Val eval(final StoredValues storedValues, final Supplier child final Val v = childGenerators[i].eval(storedValues, childDataSupplier); if (v.type().isValue()) { final String regex = v.toString(); - if (regex.length() > 0) { + if (!regex.isEmpty()) { final Pattern pattern = PatternCache.get(regex); if (pattern.matcher(value).matches()) { found = true; diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java index c4556c378b8..809abc2d2fa 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractManyChildFunction.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Crown Copyright + * Copyright 2016-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,12 +35,9 @@ public void setParams(final Param[] params) throws ParseException { functions = new Function[params.length]; for (int i = 0; i < params.length; i++) { final Param param = params[i]; - if (param instanceof Function) { - final Function func = (Function) param; - functions[i] = func; - } else { - functions[i] = new StaticValueFunction((Val) param); - } + functions[i] = param instanceof final Function func + ? func + : new StaticValueFunction((Val) param); } } diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java index d9d2144929a..f9b5ae61928 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/AbstractStringFunction.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -71,11 +71,19 @@ public boolean requiresChildData() { abstract Operation getOperation(); + + // -------------------------------------------------------------------------------- + + interface Operation { String apply(String value); } + + // -------------------------------------------------------------------------------- + + private static final class Gen extends AbstractSingleChildGenerator { private final Operation operation; diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java index a470c4b6d5f..9f5fe5672cc 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Contains.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -93,6 +93,10 @@ public boolean hasAggregate() { return super.hasAggregate(); } + + // -------------------------------------------------------------------------------- + + private static final class Gen extends AbstractManyChildGenerator { Gen(final Generator[] childGenerators) { diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java index 14590dc7e0e..b191090eda6 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Count.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -62,6 +62,10 @@ public boolean hasAggregate() { return isAggregate(); } + + // -------------------------------------------------------------------------------- + + private static final class Gen extends AbstractNoChildGenerator { private final CountReference countReference; diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java index d9c9acd072a..4d7da5dd11f 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/CountUnique.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Crown Copyright + * Copyright 2018-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ @FunctionDef( name = CountUnique.NAME, commonCategory = FunctionCategory.AGGREGATE, - commonReturnType = ValLong.class, + commonReturnType = ValInteger.class, commonReturnDescription = "The number of unique values", signatures = { @FunctionSignature( diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java index 6ca0a94df1c..88ef086a50b 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -94,7 +94,7 @@ public void setParams(final Param[] params) throws ParseException { String newValue = params[params.length - 1].toString(); for (int i = 1; i < params.length - 1; i += 2) { final String regex = params[i].toString(); - if (regex.length() == 0) { + if (regex.isEmpty()) { throw new ParseException( "An empty regex has been defined for argument of '" + name + "' function", 0); } @@ -113,7 +113,7 @@ public void setParams(final Param[] params) throws ParseException { if (params[i] instanceof Val) { // Test regex is valid. final String regex = params[i].toString(); - if (regex.length() == 0) { + if (regex.isEmpty()) { throw new ParseException( "An empty regex has been defined for argument of '" + name + "' function", 0); } @@ -144,6 +144,10 @@ public boolean hasAggregate() { return super.hasAggregate(); } + + // -------------------------------------------------------------------------------- + + private static final class Gen extends AbstractManyChildGenerator { Gen(final Generator[] childGenerators) { diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java index b42d264cc4a..662f638e92f 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Hash.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,12 +18,13 @@ import stroom.query.language.functions.ref.StoredValues; import stroom.query.language.token.Param; - -import com.google.common.io.BaseEncoding; +import stroom.util.NullSafe; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.ParseException; +import java.util.HexFormat; +import java.util.Objects; import java.util.function.Supplier; @SuppressWarnings("unused") //Used by FunctionFactory @@ -70,107 +71,155 @@ name = "salt", description = "The salt value to create the hash with.", argType = ValString.class)})}) -class Hash extends AbstractFunction { +class Hash extends AbstractManyChildFunction { static final String NAME = "hash"; static final String DEFAULT_ALGORITHM = "SHA-256"; + static final MessageDigest DEFAULT_ALGORITHM_DIGEST; + static final Function DEFAULT_ALGORITHM_FUNC = StaticValueFunction.of(DEFAULT_ALGORITHM); - private String algorithm = DEFAULT_ALGORITHM; - private String salt; - - private Generator gen; - private Function function; - private boolean hasAggregate; + private static final HexFormat HEX_FORMAT = HexFormat.of().withLowerCase(); - public Hash(final String name) { - super(name, 1, 3); + static { + try { + DEFAULT_ALGORITHM_DIGEST = MessageDigest.getInstance(DEFAULT_ALGORITHM); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } } - private static String hash(final String value, - final String algorithm, - final String salt) throws NoSuchAlgorithmException { - // Create MessageDigest object. - final MessageDigest digest = MessageDigest.getInstance(algorithm); - if (salt != null) { - digest.update(salt.getBytes()); - } + private Generator generator; + private MessageDigest messageDigest; - final byte[] arr = digest.digest(value.getBytes()); + private boolean simple; - // TODO: 30/01/2023 In Java17+ use HexFormat class - return BaseEncoding.base16() - .lowerCase() - .encode(arr); + public Hash(final String name) { + super(name, 1, 3); } @Override public void setParams(final Param[] params) throws ParseException { super.setParams(params); + final int paramCount = params.length; - if (params.length >= 2) { - algorithm = ParamParseUtil.parseStringParam(params, 1, name); - if (algorithm == null) { - algorithm = DEFAULT_ALGORITHM; - } + if (paramCount < 1) { + throw new ParseException("Expected to get at least one argument to '" + name + "' function", 0); } - if (params.length >= 3) { - salt = ParamParseUtil.parseStringParam(params, 2, name); + + if (paramCount > 3) { + throw new ParseException("Expected to get at most three arguments to '" + name + "' function", 0); } - try { - // Test that the algorithm is a valid one. - MessageDigest.getInstance(algorithm); + // See if this is a purely static computation. + simple = ParamParseUtil.supportsStaticComputation(params); - final Param param = params[0]; - if (param instanceof Function) { - function = (Function) param; - hasAggregate = function.hasAggregate(); + if (simple) { + // All static values, however unlikely + final String valueToHash = ParamParseUtil.parseStringParam(params, 0, name); + String algorithm = paramCount >= 2 + ? ParamParseUtil.parseStringParam(params, 1, name) + : null; + algorithm = Objects.requireNonNullElse(algorithm, DEFAULT_ALGORITHM); + final String salt = paramCount == 3 + ? ParamParseUtil.parseStringParam(params, 2, name) + : null; - } else { - final String string = param.toString(); - if (string == null) { - throw new ParseException("Unable to convert first argument of '" + name + "' function to string", - 0); + try { + final MessageDigest messageDigest = Objects.equals(algorithm, DEFAULT_ALGORITHM) + ? DEFAULT_ALGORITHM_DIGEST + : MessageDigest.getInstance(algorithm); + generator = StaticValueFunction.of(hash(valueToHash, messageDigest, salt)) + .createGenerator(); + } catch (NoSuchAlgorithmException e) { + throw new ParseException("Second argument of '" + name + "' function '" + algorithm + + "' is not a valid hash algorithm name.", 0); + } + } else { + // If we have a static algorithm param, then get the digest to hold on the + // generator, so we don't need to get it for each row. + if (paramCount >= 2) { + final Param algoParam = params[1]; + if (algoParam instanceof Val val) { + final String algo = val.toString(); + messageDigest = verifyAndGetAlgorithm(algo); } - gen = new StaticValueFunction(ValString.create(hash(string, algorithm, salt))).createGenerator(); } - } catch (final NoSuchAlgorithmException e) { + } + } + + private static String hash(final String value, + final String algorithm, + final String salt) throws ParseException { + MessageDigest digest = algorithm != null + ? verifyAndGetAlgorithm(algorithm) + : DEFAULT_ALGORITHM_DIGEST; + return hash(value, digest, salt); + } + + private static String hash(final String value, + final MessageDigest messageDigest, + final String salt) { + final MessageDigest digest = Objects.requireNonNullElse(messageDigest, DEFAULT_ALGORITHM_DIGEST); + digest.reset(); + if (salt != null) { + digest.update(salt.getBytes()); + } + final byte[] arr = digest.digest(value.getBytes()); + return HEX_FORMAT.formatHex(arr); + } + + private static MessageDigest verifyAndGetAlgorithm(final String algorithm) throws ParseException { + try { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { throw new ParseException(e.getMessage(), 0); } } @Override public Generator createGenerator() { - if (gen != null) { - return gen; + if (generator != null) { + return generator; } - - final Generator childGenerator = function.createGenerator(); - return new Gen(childGenerator, algorithm, salt); + return super.createGenerator(); } @Override public boolean hasAggregate() { - return hasAggregate; + if (simple) { + return false; + } + return super.hasAggregate(); + } + + @Override + protected Generator createGenerator(final Generator[] childGenerators) { + return new ManyChildGenerator(childGenerators, messageDigest); } @Override public boolean requiresChildData() { - if (function != null) { - return function.requiresChildData(); - } return super.requiresChildData(); } - private static final class Gen extends AbstractSingleChildGenerator { - private final String algorithm; + // -------------------------------------------------------------------------------- + + + /** + * For cases where the algorithm and salt are both static + */ + private static final class SingleChildGenerator extends AbstractSingleChildGenerator { + + private final MessageDigest messageDigest; private final String salt; - Gen(final Generator childGenerator, final String algorithm, final String salt) { + SingleChildGenerator(final Generator childGenerator, + final MessageDigest messageDigest, + final String salt) { super(childGenerator); - this.algorithm = algorithm; + this.messageDigest = messageDigest; this.salt = salt; } @@ -187,8 +236,71 @@ public Val eval(final StoredValues storedValues, final Supplier child } try { - return ValString.create(hash(val.toString(), algorithm, salt)); - } catch (final NoSuchAlgorithmException | RuntimeException e) { + return ValString.create(hash(val.toString(), messageDigest, salt)); + } catch (final RuntimeException e) { + return ValErr.create(e.getMessage()); + } + } + } + + + // -------------------------------------------------------------------------------- + + + private static final class ManyChildGenerator extends AbstractManyChildGenerator { + + private MessageDigest messageDigest = DEFAULT_ALGORITHM_DIGEST; + + ManyChildGenerator(final Generator[] childGenerators, + final MessageDigest messageDigest) { + super(childGenerators); + this.messageDigest = messageDigest; + } + + @Override + public Val eval(final StoredValues storedValues, final Supplier childDataSupplier) { + + final Val valToHash = childGenerators[0].eval(storedValues, childDataSupplier); + if (!valToHash.type().isValue()) { + return ValErr.wrap(valToHash, "First argument of '" + Hash.NAME + "' is not a value."); + } + + final Val algo; + if (childGenerators.length > 1) { + algo = childGenerators[1].eval(storedValues, childDataSupplier); + if (Val.isNull(algo)) { + messageDigest = DEFAULT_ALGORITHM_DIGEST; + } else if (!algo.type().isValue()) { + return ValErr.wrap(algo, "Second argument of '" + Hash.NAME + "' is not a value."); + } + } else { + algo = ValNull.INSTANCE; + } + + final Val salt; + if (childGenerators.length > 2) { + salt = childGenerators[2].eval(storedValues, childDataSupplier); + if (!salt.type().isValue()) { + return ValErr.wrap(salt, "Third argument of '" + Hash.NAME + "' is not a value."); + } + } else { + salt = ValNull.INSTANCE; + } + + try { + if (messageDigest != null) { + return ValString.create(hash( + NullSafe.get(valToHash, Val::toString), + messageDigest, + NullSafe.get(salt, Val::toString))); + } else { + return ValString.create(hash( + NullSafe.get(valToHash, Val::toString), + NullSafe.getOrElse(algo, Val::toString, DEFAULT_ALGORITHM), + NullSafe.get(salt, Val::toString))); + } + + } catch (final RuntimeException | ParseException e) { return ValErr.create(e.getMessage()); } } diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java index a622e153d45..38d5a6fd8c9 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ParamParseUtil.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.language.functions; import stroom.query.language.token.Param; @@ -77,4 +93,18 @@ private static String getPos(int pos) { } return String.valueOf(pos); } + + public static boolean supportsStaticComputation(final Param... params) { + // See if this is a static computation. + boolean simple = true; + if (params != null) { + for (Param param : params) { + if (!(param instanceof Val)) { + simple = false; + break; + } + } + } + return simple; + } } diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java index cb0c6325a31..a94b170b50c 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/StaticValueFunction.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -32,6 +32,14 @@ public StaticValueFunction(final Val value) { this.gen = new StaticValueGen(value); } + public static StaticValueFunction of(final Val value) { + return new StaticValueFunction(value); + } + + public static StaticValueFunction of(final String value) { + return new StaticValueFunction(ValString.create(value)); + } + @Override public void setParams(final Param[] params) { // Ignore diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java index 0d5439b454e..484add4379c 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/Val.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Crown Copyright + * Copyright 2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,6 +95,8 @@ default boolean hasNumericValue() { */ Comparator getDefaultComparator(final boolean isCaseSensitive); + // TODO rename of( to arrayOf( to make it a bit more clear you are getting an array back + // Best done on master as it affects a lot of files static Val[] of(final Val... values) { return values; } @@ -115,7 +117,7 @@ static Val[] of(final double... d) { return Val.of(result); } - static Val[] empty() { + static Val[] emptyArray() { return EMPTY_VALUES; } @@ -152,6 +154,21 @@ static Val nullSafeCreate(final T1 value, } } + static Val requireNonNullElse(final Val val, final Val other) { + if (val != null && !val.type().isNull()) { + return val; + } else { + return other; + } + } + + static boolean isNull(final Val val) { + return val == null + || val == ValNull.INSTANCE + || Objects.equals(ValNull.INSTANCE, val) + || val.type().isNull(); + } + /** * Create a {@link Val} of the appropriate subclass for the java * type passed, e.g. diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java index d2a4bf44e31..754c611c475 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValSerialiser.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.language.functions; import stroom.query.language.functions.ref.DataReader; @@ -68,7 +84,7 @@ public static void write(final DataWriter writer, final Val val) { } public static Val[] readArray(final DataReader reader) { - Val[] values = Val.empty(); + Val[] values = Val.emptyArray(); final int valueCount = reader.readByteUnsigned(); if (valueCount > 0) { diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java index 8b511c5883a..75aed99694a 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/functions/ValString.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Crown Copyright + * Copyright 2018-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,7 +43,7 @@ public final class ValString implements Val { ValComparators.GENERIC_CASE_INSENSITIVE_COMPARATOR); public static final Type TYPE = Type.STRING; - static final ValString EMPTY = new ValString(""); + public static final ValString EMPTY = new ValString(""); private final String value; // Permanent lazy cache of the slightly costly conversion to long/double diff --git a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java index eb665be5525..d0123221137 100644 --- a/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java +++ b/stroom-query/stroom-query-language/src/main/java/stroom/query/language/token/TokenType.java @@ -237,7 +237,7 @@ public enum TokenType { }); KEYWORDS_VALID_AFTER = Collections.unmodifiableMap(new EnumMap<>(validNextKeywords)); - LOGGER.debug("KEYWORDS:\n{}", + LOGGER.trace("KEYWORDS:\n{}", ALL_KEYWORDS.stream() .map(keyword -> { return LogUtil.message(""" diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java index be341ea65fb..b09e1e734b4 100644 --- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractExpressionParserTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.language.functions; import stroom.query.language.functions.ref.KryoDataReader; @@ -195,25 +211,25 @@ protected void testSelectors(final String expression, protected void compute(final String expression, final Val[] values, - final Consumer consumer) { + final ValAssertion consumer) { compute(expression, 1, values, consumer); } protected void compute(final String expression, - final Consumer consumer) { + final ValAssertion consumer) { compute(expression, 1, consumer); } protected void compute(final String expression, final int valueCount, - final Consumer consumer) { + final ValAssertion consumer) { createExpression(expression, valueCount, exp -> { final ValueReferenceIndex valueReferenceIndex = new ValueReferenceIndex(); exp.addValueReferences(valueReferenceIndex); final StoredValues storedValues = valueReferenceIndex.createStoredValues(); final Generator gen = exp.createGenerator(); final Val out = gen.eval(storedValues, null); - consumer.accept(out); + consumer.actual(out); testKryo(valueReferenceIndex, gen, storedValues); }); } @@ -221,7 +237,7 @@ protected void compute(final String expression, protected void compute(final String expression, final int valueCount, final Val[] values, - final Consumer consumer) { + final ValAssertion valAssertion) { createExpression(expression, valueCount, exp -> { final ValueReferenceIndex valueReferenceIndex = new ValueReferenceIndex(); exp.addValueReferences(valueReferenceIndex); @@ -229,7 +245,7 @@ protected void compute(final String expression, final Generator gen = exp.createGenerator(); gen.set(values, storedValues); final Val out = gen.eval(storedValues, null); - consumer.accept(out); + valAssertion.actual(out); testKryo(valueReferenceIndex, gen, storedValues); }); } diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java index 45ed08d14c6..1390bbea9ab 100644 --- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/AbstractFunctionTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.language.functions; import stroom.query.language.functions.ref.StoredValues; diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java index 4009032e650..793615fe3f9 100644 --- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,7 +20,6 @@ import io.vavr.Tuple; import org.assertj.core.api.Assertions; -import org.assertj.core.data.Offset; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; @@ -97,7 +96,7 @@ void testMatch1() { void testMatch2() { createGenerator("match('this', 'that')", (gen, storedValues) -> { final Val out = gen.eval(storedValues, null); - assertThat(out.toBoolean()).isFalse(); + ValAssertions.valFalse().actual(out); }); } @@ -105,161 +104,160 @@ void testMatch2() { void testMatch3() { compute("match(${val1}, 'this')", Val.of("this"), - out -> assertThat(out.toBoolean()).isTrue()); + ValAssertions.valTrue()); } @Test void testMatch4() { compute("match(${val1}, 'that')", Val.of("this"), - out -> assertThat(out.toBoolean()).isFalse()); + ValAssertions.valFalse()); } @Test void testTrue() { compute("true()", - out -> assertThat(out.toBoolean()).isTrue()); + ValAssertions.valTrue()); } @Test void testFalse() { compute("false()", - out -> assertThat(out.toBoolean()).isFalse()); + ValAssertions.valFalse()); } @Test void testNull() { - compute("null()", - out -> assertThat(out).isInstanceOf(ValNull.class)); + compute("null()", ValAssertions.valNull()); } @Test void testErr() { compute("err()", - out -> assertThat(out).isInstanceOf(ValErr.class)); + ValAssertions.valErr()); } @Test void testNotTrue() { compute("not(true())", - out -> assertThat(out.toBoolean()).isFalse()); + ValAssertions.valFalse()); } @Test void testNotFalse() { compute("not(false())", - out -> assertThat(out.toBoolean()).isTrue()); + ValAssertions.valTrue()); } @Test void testAnd1() { compute("and(false(), false())", - out -> assertThat(out.toBoolean()).isFalse()); + ValAssertions.valFalse()); } @Test void testAnd2() { compute("and(false(), true())", - out -> assertThat(out.toBoolean()).isFalse()); + ValAssertions.valFalse()); } @Test void testAnd3() { compute("and(true(), true())", - out -> assertThat(out.toBoolean()).isTrue()); + ValAssertions.valTrue()); } @Test void testOr1() { compute("or(false(), false())", - out -> assertThat(out.toBoolean()).isFalse()); + ValAssertions.valFalse()); } @Test void testOr2() { compute("or(false(), true())", - out -> assertThat(out.toBoolean()).isTrue()); + ValAssertions.valTrue()); } @Test void testOr3() { compute("or(true(), true())", - out -> assertThat(out.toBoolean()).isTrue()); + ValAssertions.valTrue()); } @Test void testIf1() { compute("if(true(), 'this', 'that')", - out -> assertThat(out.toString()).isEqualTo("this")); + ValAssertions.valString("this")); } @Test void testIf2() { compute("if(false(), 'this', 'that')", - out -> assertThat(out.toString()).isEqualTo("that")); + ValAssertions.valString("that")); } @Test void testIf3() { compute("if(${val1}, 'this', 'that')", Val.of("true"), - out -> assertThat(out.toString()).isEqualTo("this")); + ValAssertions.valString("this")); } @Test void testIf4() { compute("if(${val1}, 'this', 'that')", Val.of("false"), - out -> assertThat(out.toString()).isEqualTo("that")); + ValAssertions.valString("that")); } @Test void testIf5() { compute("if(match(${val1}, 'foo'), 'this', 'that')", Val.of("foo"), - out -> assertThat(out.toString()).isEqualTo("this")); + ValAssertions.valString("this")); } @Test void testIf6() { compute("if(match(${val1}, 'foo'), 'this', 'that')", Val.of("bar"), - out -> assertThat(out.toString()).isEqualTo("that")); + ValAssertions.valString("that")); } @Test void testNotIf() { compute("if(not(${val1}), 'this', 'that')", Val.of("false"), - out -> assertThat(out.toString()).isEqualTo("this")); + ValAssertions.valString("this")); } @Test void testIf_nullHandling() { compute("if(${val1}=null(), true(), false())", Val.of(ValNull.INSTANCE), - out -> assertThat(out.type().isError()).isTrue()); + ValAssertions.valErr()); } @Test void testReplace1() { compute("replace('this', 'is', 'at')", Val.of(3D), - out -> assertThat(out.toString()).isEqualTo("that")); + ValAssertions.valString("that")); } @Test void testReplace2() { compute("replace(${val1}, 'is', 'at')", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("that")); + ValAssertions.valString("that")); } @Test void testConcat1() { compute("concat('this', ' is ', 'it')", Val.of(3D), - out -> assertThat(out.toString()).isEqualTo("this is it")); + ValAssertions.valString("this is it")); } @@ -267,28 +265,28 @@ void testConcat1() { void testConcat1Plus() { compute("'this'+' is '+'it'", Val.of(3D), - out -> assertThat(out.toString()).isEqualTo("this is it")); + ValAssertions.valString("this is it")); } @Test void testConcat2() { compute("concat(${val1}, ' is ', 'it')", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("this is it")); + ValAssertions.valString("this is it")); } @Test void testConcatSingle1() { compute("concat(${val1})", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("this")); + ValAssertions.valString("this")); } @Test void testConcatSingle2() { compute("concat('hello')", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("hello")); + ValAssertions.valString("hello")); } @Test @@ -296,7 +294,7 @@ void testConcatNUll() { compute("concat(${val1}, ${val2})", 2, Val.of(ValNull.INSTANCE, ValNull.INSTANCE), - out -> assertThat(out.toString()).isEqualTo("")); + ValAssertions.valString("")); } @Test @@ -304,7 +302,7 @@ void testConcatNullPlus1() { compute("${val1}+${val2}", 2, Val.of(ValNull.INSTANCE, ValNull.INSTANCE), - out -> assertThat(out).isEqualTo(ValNull.INSTANCE)); + ValAssertions.valNull()); } @Test @@ -312,7 +310,7 @@ void testConcatNullPlus2() { compute("${val1}+${val2}+'test'", 2, Val.of(ValNull.INSTANCE, ValNull.INSTANCE), - out -> assertThat(out.toString()).isEqualTo("test")); + ValAssertions.valString("test")); } @Test @@ -320,7 +318,7 @@ void testConcatNullPlus3() { compute("${val1}+${val2}+''", 2, Val.of(ValNull.INSTANCE, ValNull.INSTANCE), - out -> assertThat(out.toString()).isEqualTo("")); + ValAssertions.valString("")); } @Test @@ -328,7 +326,7 @@ void testConcatBooleanPlus1() { compute("${val1}+${val2}", 2, Val.of(ValBoolean.TRUE, ValBoolean.TRUE), - out -> assertThat(out.toString()).isEqualTo("2")); + ValAssertions.valDouble(2)); } @Test @@ -336,16 +334,15 @@ void testConcatBooleanPlus2() { compute("${val1}+${val2}+''", 2, Val.of(ValBoolean.TRUE, ValBoolean.TRUE), - out -> assertThat(out.toString()).isEqualTo("2")); + ValAssertions.valString("2")); } - @Test void testConcatBooleanPlus3() { compute("${val1}+${val2}+'test'", 2, Val.of(ValBoolean.TRUE, ValBoolean.TRUE), - out -> assertThat(out.toString()).isEqualTo("2test")); + ValAssertions.valString("2test")); } @Test @@ -353,7 +350,7 @@ void testConcatBooleanPlus4() { compute("${val1}+'test'+${val2}", 2, Val.of(ValBoolean.TRUE, ValBoolean.TRUE), - out -> assertThat(out.toString()).isEqualTo("truetesttrue")); + ValAssertions.valString("truetesttrue")); } @@ -361,239 +358,238 @@ void testConcatBooleanPlus4() { void testStaticString1() { compute("'hello'", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("hello")); + ValAssertions.valString("hello")); } @Test void testStaticString2() { compute("'[Click Here](http://www.somehost.com/somepath){DIALOG}'", Val.of("this"), - out -> assertThat(out.toString()) - .isEqualTo("[Click Here](http://www.somehost.com/somepath){DIALOG}")); + ValAssertions.valString("[Click Here](http://www.somehost.com/somepath){DIALOG}")); } @Test void testStaticNumber() { compute("50", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("50")); + ValAssertions.valDouble(50)); } @Test void testStringLength1() { compute("stringLength(${val1})", Val.of("this"), - out -> assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D))); + ValAssertions.valInteger(4)); } @Test void testSubstring1() { compute("substring(${val1}, 1, 2)", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("h")); + ValAssertions.valString("h")); } @Test void testSubstring3() { compute("substring(${val1}, 2, 99)", Val.of("his"), - out -> assertThat(out.toString()).isEqualTo("s")); + ValAssertions.valString("s")); } @Test void testSubstring4() { compute("substring(${val1}, 1+1, 99-1)", Val.of("his"), - out -> assertThat(out.toString()).isEqualTo("s")); + ValAssertions.valString("s")); } @Test void testSubstring5() { compute("substring(${val1}, 2+5, 99-1)", Val.of("his"), - out -> assertThat(out.toString()).isEmpty()); + ValAssertions.valStringEmpty()); } @Test void testSubstringBefore1() { compute("substringBefore(${val1}, '-')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("aa")); + ValAssertions.valString("aa")); } @Test void testSubstringBefore2() { compute("substringBefore(${val1}, 'a')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEmpty()); + ValAssertions.valStringEmpty()); } @Test void testSubstringBefore3() { compute("substringBefore(${val1}, 'b')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("aa-")); + ValAssertions.valString("aa-")); } @Test void testSubstringBefore4() { compute("substringBefore(${val1}, 'q')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEmpty()); + ValAssertions.valStringEmpty()); } @Test void testSubstringAfter1() { compute("substringAfter(${val1}, '-')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("bb")); + ValAssertions.valString("bb")); } @Test void testSubstringAfter2() { compute("substringAfter(${val1}, 'a')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("a-bb")); + ValAssertions.valString("a-bb")); } @Test void testSubstringAfter3() { compute("substringAfter(${val1}, 'b')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("b")); + ValAssertions.valString("b")); } @Test void testSubstringAfter4() { compute("substringAfter(${val1}, 'q')", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEmpty()); + ValAssertions.valStringEmpty()); } @Test void testIndexOf() { compute("indexOf(${val1}, '-')", Val.of("aa-bb"), - out -> assertThat(out.toInteger().intValue()).isEqualTo(2)); + ValAssertions.valInteger(2)); } @Test void testIndexOf1() { compute("substring(${val1}, indexOf(${val1}, '-'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("-bb")); + ValAssertions.valString("-bb")); } @Test void testIndexOf2() { compute("substring(${val1}, indexOf(${val1}, 'a'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("aa-bb")); + ValAssertions.valString("aa-bb")); } @Test void testIndexOf3() { compute("substring(${val1}, indexOf(${val1}, 'b'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("bb")); + ValAssertions.valString("bb")); } @Test void testIndexOf4() { compute("substring(${val1}, indexOf(${val1}, 'q'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("")); + ValAssertions.valString("")); } @Test void testLastIndexOf1() { compute("substring(${val1}, lastIndexOf(${val1}, '-'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("-bb")); + ValAssertions.valString("-bb")); } @Test void testLastIndexOf2() { compute("substring(${val1}, lastIndexOf(${val1}, 'a'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("a-bb")); + ValAssertions.valString("a-bb")); } @Test void testLastIndexOf3() { compute("substring(${val1}, lastIndexOf(${val1}, 'b'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("b")); + ValAssertions.valString("b")); } @Test void testLastIndexOf4() { compute("substring(${val1}, lastIndexOf(${val1}, 'q'), stringLength(${val1}))", Val.of("aa-bb"), - out -> assertThat(out.toString()).isEqualTo("")); + ValAssertions.valStringEmpty()); } @Test void testDecode1() { compute("decode(${val1}, 'hullo', 'hello', 'goodbye')", Val.of("hullo"), - out -> assertThat(out.toString()).isEqualTo("hello")); + ValAssertions.valString("hello")); } @Test void testDecode2() { compute("decode(${val1}, 'h.+o', 'hello', 'goodbye')", Val.of("hullo"), - out -> assertThat(out.toString()).isEqualTo("hello")); + ValAssertions.valString("hello")); } @Test void testInclude1() { compute("include(${val1}, 'this', 'that')", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("this")); + ValAssertions.valString("this")); } @Test void testInclude2() { compute("include(${val1}, 'this', 'that')", Val.of("that"), - out -> assertThat(out.toString()).isEqualTo("that")); + ValAssertions.valString("that")); } @Test void testInclude3() { compute("include(${val1}, 'this', 'that')", Val.of("other"), - out -> assertThat(out.toString()).isNull()); + ValAssertions.valNull()); } @Test void testExclude1() { compute("exclude(${val1}, 'this', 'that')", Val.of("this"), - out -> assertThat(out.toString()).isNull()); + ValAssertions.valNull()); } @Test void testExclude2() { compute("exclude(${val1}, 'this', 'that')", Val.of("that"), - out -> assertThat(out.toString()).isNull()); + ValAssertions.valNull()); } @Test void testExclude3() { compute("exclude(${val1}, 'this', 'that')", Val.of("other"), - out -> assertThat(out.toString()).isEqualTo("other")); + ValAssertions.valString("other")); } @Test void testEncodeUrl() { compute("encodeUrl('https://www.somesite.com:8080/this/path?query=string')", Val.of(""), - out -> assertThat(out.toString()).isEqualTo( + ValAssertions.valString( "https%3A%2F%2Fwww.somesite.com%3A8080%2Fthis%2Fpath%3Fquery%3Dstring")); } @@ -601,117 +597,112 @@ void testEncodeUrl() { void testDecodeUrl() { compute("decodeUrl('https%3A%2F%2Fwww.somesite.com%3A8080%2Fthis%2Fpath%3Fquery%3Dstring')", Val.of(""), - out -> assertThat(out.toString()) - .isEqualTo("https://www.somesite.com:8080/this/path?query=string")); + ValAssertions.valString("https://www.somesite.com:8080/this/path?query=string")); } @Test void testEquals1() { compute("equals(${val1}, 'plop')", Val.of("plop"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test void testEquals2() { compute("equals(${val1}, ${val1})", Val.of("plop"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test void testEquals3() { compute("equals(${val1}, 'plip')", Val.of("plop"), - out -> assertThat(out.toString()).isEqualTo("false")); + ValAssertions.valFalse()); } @Test void testEquals4() { compute("equals(${val1}, ${val2})", 2, Val.of("plop", "plip"), - out -> assertThat(out.toString()).isEqualTo("false")); + ValAssertions.valFalse()); } @Test void testEquals5() { compute("equals(${val1}, ${val2})", 2, Val.of("plop", "plop"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test void testEquals6() { compute("${val1}=${val2}", 2, Val.of("plop", "plop"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test void testEqualsNull1() { compute("${val1}=null()", Val.of(ValNull.INSTANCE), - out -> assertThat(out.type().isError()).isTrue()); + ValAssertions.valErr()); } @Test void testEqualsNull2() { compute("${val1}=null()", Val.of("plop"), - out -> assertThat(out.type().isError()).isTrue()); + ValAssertions.valErr()); } @Test void testEqualsNull3() { compute("null()=null()", Val.of("plop"), - out -> assertThat(out.type().isError()).isTrue()); + ValAssertions.valErr()); } @Test void testEqualsNull4() { compute("if(${val1}=null(), true(), false())", Val.of(ValNull.INSTANCE), - out -> assertThat(out.type().isError()).isTrue()); + ValAssertions.valErr()); } @Test void testIsNull1() { compute("isNull(${val1})", Val.of(ValNull.INSTANCE), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test void testIsNull2() { compute("isNull(${val1})", Val.of("plop"), - out -> assertThat(out.toString()).isEqualTo("false")); + ValAssertions.valFalse()); } @Test void testIsNull3() { compute("isNull(null())", Val.of("plop"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test void testIsNull4() { compute("if(isNull(${val1}), true(), false())", Val.of(ValNull.INSTANCE), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test void testLessThan1() { - compute("lessThan(1, 0)", - 2, - out -> assertThat(out.toString()).isEqualTo("false")); + compute("lessThan(1, 0)", 2, ValAssertions.valFalse()); } @Test void testLessThan2() { - compute("lessThan(1, 1)", - 2, - out -> assertThat(out.toString()).isEqualTo("false")); + compute("lessThan(1, 1)", 2, ValAssertions.valFalse()); } @Test @@ -719,7 +710,7 @@ void testLessThan3() { compute("lessThan(${val1}, ${val2})", 2, Val.of(1D, 2D), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -727,7 +718,7 @@ void testLessThan4() { compute("lessThan(${val1}, ${val2})", 2, Val.of("fred", "fred"), - out -> assertThat(out.toString()).isEqualTo("false")); + ValAssertions.valFalse()); } @Test @@ -735,7 +726,7 @@ void testLessThan5() { compute("lessThan(${val1}, ${val2})", 2, Val.of("fred", "fred1"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -743,21 +734,21 @@ void testLessThan6() { compute("lessThan(${val1}, ${val2})", 2, Val.of("fred1", "fred"), - out -> assertThat(out.toString()).isEqualTo("false")); + ValAssertions.valFalse()); } @Test void testLessThanOrEqualTo1() { compute("lessThanOrEqualTo(1, 0)", 2, - out -> assertThat(out.toString()).isEqualTo("false")); + ValAssertions.valFalse()); } @Test void testLessThanOrEqualTo2() { compute("lessThanOrEqualTo(1, 1)", 2, - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -765,7 +756,7 @@ void testLessThanOrEqualTo3() { compute("lessThanOrEqualTo(${val1}, ${val2})", 2, Val.of(1D, 2D), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -773,7 +764,7 @@ void testLessThanOrEqualTo3_mk2() { compute("(${val1}<=${val2})", 2, Val.of(1D, 2D), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -781,7 +772,7 @@ void testLessThanOrEqualTo4() { compute("lessThanOrEqualTo(${val1}, ${val2})", 2, Val.of("fred", "fred"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -789,7 +780,7 @@ void testLessThanOrEqualTo5() { compute("lessThanOrEqualTo(${val1}, ${val2})", 2, Val.of("fred", "fred1"), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -797,7 +788,7 @@ void testLessThanOrEqualTo6() { compute("lessThanOrEqualTo(${val1}, ${val2})", 2, Val.of("fred1", "fred"), - out -> assertThat(out.toString()).isEqualTo("false")); + ValAssertions.valFalse()); } @Test @@ -805,7 +796,7 @@ void testGreaterThanOrEqualTo1() { compute("greaterThanOrEqualTo(${val1}, ${val2})", 2, Val.of(2D, 1D), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @Test @@ -813,7 +804,7 @@ void testGreaterThanOrEqualTo1_mk2() { compute("(${val1}>=${val2})", 2, Val.of(2D, 1D), - out -> assertThat(out.toString()).isEqualTo("true")); + ValAssertions.valTrue()); } @TestFactory @@ -1107,33 +1098,134 @@ Stream testBooleanExpressions() { void testSubstring2() { compute("substring(${val1}, 0, 99)", Val.of("this"), - out -> assertThat(out.toString()).isEqualTo("this")); + ValAssertions.valString("this")); + } + + @Test + void testContains() { + compute("contains(${val1}, ${val2})", Val.of("foobar", "foo"), ValAssertions.valTrue()); + } + + @Test + void testHash_static1() { + compute("hash('foo')", + null, + ValAssertions.valString( + "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae")); + } + + @Test + void testHash_static2() { + compute("hash('foo', 'MD5')", + null, + ValAssertions.valString( + "acbd18db4cc2f85cedef654fccc4a4d8")); + } + + @Test + void testHash_static3() { + compute("hash('foo', 'MD5', 'some salt')", + null, + ValAssertions.valString( + "c58c215b43ef3b3480c0d0f770ec1b57")); } @Test void testHash1() { compute("hash(${val1})", Val.of("test"), - out -> assertThat(out.toString()).isEqualTo( + ValAssertions.valString( "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")); } @Test void testHash2() { - compute("hash(${val1}, 'SHA-512')", - Val.of("test"), - out -> assertThat(out.toString()).isEqualTo( + compute("hash(${val1}, ${val2})", + Val.of("test", "SHA-512"), + ValAssertions.valString( "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff")); } @Test void testHash3() { - compute("hash(${val1}, 'SHA-512', 'mysalt')", - Val.of("test"), - out -> assertThat(out.toString()).isEqualTo( + compute("hash(${val1}, ${val2}, ${val3})", + Val.of("test", "SHA-512", "mysalt"), + ValAssertions.valString( "af2910d4d8acf3fcf9683d3ca4425327cb1b4b48bc690f566e27b0e0144c17af82066cf6af14d3a30312ed9df671e0e24b1c66ed3973d1a7836899d75c4d6bb8")); } + @Test + void testHash4() { + compute("hash(${val1})", + Val.of(123), + ValAssertions.valString( + "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3")); + } + + @Test + void testHash5() { + compute("hash(${val1}, ${val2}, ${val3})", + Val.of(ValLong.create(123), ValString.create("SHA-256"), ValLong.create(456)), + ValAssertions.valString( + "c1cf024576e9c756b252bd5035efc64c72c17affe236909ded190d266a5bfdf1")); + } + + @Test + void testHash6() { + compute("hash(${val1})", + Val.of(ValErr.create("bad things happened")), + ValAssertions.valErrContainsIgnoreCase("bad things")); + } + + @Test + void testHash7() { + compute("hash(${val1}, ${val2})", + Val.of("test", "BAD ALGO"), + ValAssertions.valErrContainsIgnoreCase("BAD ALGO", "digest")); + } + + @Test + void testHash8() { + Assertions.assertThatThrownBy(() -> { + compute("hash()", + null, + null); + }).isInstanceOf(TokenException.class); + } + + @Test + void testHash9() { + Assertions.assertThatThrownBy(() -> { + compute("hash(${val1}, ${val2}, ${val3}, ${val4)", + Val.of("test", "SHA-512", "mysalt", "BAD PARAM"), + null); + }).isInstanceOf(TokenException.class); + } + + @Test + void testHash10() { + compute("hash(${val1}, concat('SHA-', ${val2}))", + Val.of(ValString.create("test"), ValLong.create(256)), + ValAssertions.valString( + "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08")); + } + + @Test + void testHash11() { + compute("hash(${val1}, 'MD5', ${val2})", + Val.of("test", "mysalt"), + ValAssertions.valString( + "ea43fd72fb05dd2cb8e186abd56afc47")); + } + + @Test + void testHash12() { + compute("hash(${val1}, ${val2}, 'mysalt')", + Val.of("test", "MD5"), + ValAssertions.valString( + "ea43fd72fb05dd2cb8e186abd56afc47")); + } + @Test void testJoining1() { createGenerator("joining(${val1}, ',')", (gen, storedValues) -> { @@ -1142,7 +1234,7 @@ void testJoining1() { gen.set(Val.of("three"), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toString()).isEqualTo("one,two,three"); + ValAssertions.valString("one,two,three").actual(out); }); } @@ -1154,7 +1246,7 @@ void testJoining2() { gen.set(Val.of("three"), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toString()).isEqualTo("onetwothree"); + ValAssertions.valString("onetwothree").actual(out); }); } @@ -1165,13 +1257,13 @@ void testCount() { gen.set(Val.of(133D), storedValues); Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D)); + ValAssertions.valLong(2).actual(out); gen.set(Val.of(11D), storedValues); gen.set(Val.of(122D), storedValues); out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D)); + ValAssertions.valLong(4).actual(out); }); } @@ -1185,7 +1277,7 @@ void testCountGroups() { createChildDataSupplier(List.of(storedValues, storedValues)); Val out = gen.eval(storedValues, childDataSupplier); - assertThat(out.toInteger()).isEqualTo(2); + ValAssertions.valLong(2).actual(out); }); } @@ -1196,13 +1288,13 @@ void testCountUnique() { gen.set(Val.of(133D), storedValues); Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D)); + ValAssertions.valInteger(2).actual(out); gen.set(Val.of(11D), storedValues); gen.set(Val.of(122D), storedValues); out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3D, Offset.offset(0D)); + ValAssertions.valInteger(3).actual(out); }); } @@ -1213,13 +1305,13 @@ void testCountUniqueStaticValue() { gen.set(Val.of(133D), storedValues); Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D)); + ValAssertions.valInteger(1).actual(out); gen.set(Val.of(11D), storedValues); gen.set(Val.of(122D), storedValues); out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D)); + ValAssertions.valInteger(1).actual(out); }); } @@ -1227,14 +1319,14 @@ void testCountUniqueStaticValue() { void testAdd1() { compute("3+4", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(7D, Offset.offset(0D))); + ValAssertions.valDouble(7D)); } @Test void testAdd2() { compute("3+4+5", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(12D, Offset.offset(0D))); + ValAssertions.valDouble(12D)); } @Test @@ -1244,13 +1336,13 @@ void testAdd3() { gen.set(Val.of(1D), storedValues); Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D)); + ValAssertions.valDouble(4D).actual(out); gen.set(Val.of(1D), storedValues); gen.set(Val.of(1D), storedValues); out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(6D, Offset.offset(0D)); + ValAssertions.valDouble(6D).actual(out); }); } @@ -1258,7 +1350,7 @@ void testAdd3() { void testSubtract1() { compute("3-4", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(-1D, Offset.offset(0D))); + ValAssertions.valDouble(-1D)); } @Test @@ -1268,13 +1360,13 @@ void testSubtract2() { gen.set(Val.of(1D), storedValues); Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(0D, Offset.offset(0D)); + ValAssertions.valDouble(0D).actual(out); gen.set(Val.of(1D), storedValues); gen.set(Val.of(1D), storedValues); out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(-2D, Offset.offset(0D)); + ValAssertions.valDouble(-2D).actual(out); }); } @@ -1282,7 +1374,7 @@ void testSubtract2() { void testMultiply1() { compute("3*4", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(12D, Offset.offset(0D))); + ValAssertions.valDouble(12D)); } @Test @@ -1292,23 +1384,20 @@ void testMultiply2() { gen.set(Val.of(1D), storedValues); Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D)); + ValAssertions.valDouble(4D).actual(out); gen.set(Val.of(1D), storedValues); gen.set(Val.of(1D), storedValues); out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D)); + ValAssertions.valDouble(8D).actual(out); }); } @Test void testDivide1() { compute("8/4", - out -> { -// gen.set(getVal(1D)); - assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D)); - }); + ValAssertions.valDouble(2D)); } @Test @@ -1318,13 +1407,13 @@ void testDivide2() { gen.set(Val.of(1D), storedValues); Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D)); + ValAssertions.valDouble(4D).actual(out); gen.set(Val.of(1D), storedValues); gen.set(Val.of(1D), storedValues); out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D)); + ValAssertions.valDouble(2D).actual(out); }); } @@ -1340,21 +1429,21 @@ void testDivide_byZero() { void testFloorNum1() { compute("floor(8.4234)", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D))); + ValAssertions.valDouble(8D)); } @Test void testFloorNum2() { compute("floor(8.5234)", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D))); + ValAssertions.valDouble(8D)); } @Test void testFloorNum3() { compute("floor(${val1})", Val.of(1.34D), - out -> assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D))); + ValAssertions.valDouble(1D)); } @Test @@ -1364,7 +1453,7 @@ void testFloorNum4() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3D, Offset.offset(0D)); + ValAssertions.valDouble(3D).actual(out); }); } @@ -1375,7 +1464,7 @@ void testFloorNum5() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3.8D, Offset.offset(0D)); + ValAssertions.valDouble(3.8D).actual(out); }); } @@ -1386,7 +1475,7 @@ void testFloorNum6() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3.86D, Offset.offset(0D)); + ValAssertions.valDouble(3.86D).actual(out); }); } @@ -1394,21 +1483,21 @@ void testFloorNum6() { void testCeilNum1() { compute("ceiling(8.4234)", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(9D, Offset.offset(0D))); + ValAssertions.valDouble(9D)); } @Test void testCeilNum2() { compute("ceiling(8.5234)", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(9D, Offset.offset(0D))); + ValAssertions.valDouble(9D)); } @Test void testCeilNum3() { compute("ceiling(${val1})", Val.of(1.34D), - out -> assertThat(out.toDouble()).isEqualTo(2D, Offset.offset(0D))); + ValAssertions.valDouble(2D)); } @Test @@ -1418,7 +1507,7 @@ void testCeilNum4() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D)); + ValAssertions.valDouble(4D).actual(out); }); } @@ -1429,7 +1518,7 @@ void testCeilNum5() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3.9D, Offset.offset(0D)); + ValAssertions.valDouble(3.9D).actual(out); }); } @@ -1440,7 +1529,7 @@ void testCeilNum6() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3.87D, Offset.offset(0D)); + ValAssertions.valDouble(3.87D).actual(out); }); } @@ -1448,21 +1537,21 @@ void testCeilNum6() { void testRoundNum1() { compute("round(8.4234)", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(8D, Offset.offset(0D))); + ValAssertions.valDouble(8D)); } @Test void testRoundNum2() { compute("round(8.5234)", Val.of(1D), - out -> assertThat(out.toDouble()).isEqualTo(9D, Offset.offset(0D))); + ValAssertions.valDouble(9D)); } @Test void testRoundNum3() { compute("round(${val1})", Val.of(1.34D), - out -> assertThat(out.toDouble()).isEqualTo(1D, Offset.offset(0D))); + ValAssertions.valDouble(1D)); } @Test @@ -1472,7 +1561,7 @@ void testRoundNum4() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(4D, Offset.offset(0D)); + ValAssertions.valDouble(4D).actual(out); }); } @@ -1483,7 +1572,7 @@ void testRoundNum5() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3.9D, Offset.offset(0D)); + ValAssertions.valDouble(3.9D).actual(out); }); } @@ -1494,7 +1583,7 @@ void testRoundNum6() { gen.set(Val.of(1.8655D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toDouble()).isEqualTo(3.87D, Offset.offset(0D)); + ValAssertions.valDouble(3.87D).actual(out); }); } @@ -1504,7 +1593,8 @@ void testDuration1() { gen.set(Val.of(1.34D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toLong()).isEqualTo(DateUtil.parseNormalDateTimeString("2014-02-22T11:12:12.888Z")); + ValAssertions.valDate("2014-02-22T11:12:12.888Z") + .actual(out); }); } @@ -1514,7 +1604,8 @@ void testDuration2() { gen.set(Val.of(1.34D), storedValues); final Val out = gen.eval(storedValues, null); - assertThat(out.toLong()).isEqualTo(DateUtil.parseNormalDateTimeString("2014-02-22T12:12:15.888Z")); + ValAssertions.valDate("2014-02-22T12:12:15.888Z") + .actual(out); }); } @@ -1543,11 +1634,9 @@ void testDuration2() { roundYear, 2014-02-22T12:12:12.888Z, 2014-01-01T00:00:00.000Z """) void testTime(final String expr, final String input, final String expectedResult) { - final double expectedMs = DateUtil.parseNormalDateTimeString(expectedResult); + final long expectedMs = DateUtil.parseNormalDateTimeString(expectedResult); final String expression = expr + "(${val1})"; - compute(expression, - Val.of(input), - out -> assertThat(out.toDouble()).isEqualTo(expectedMs, Offset.offset(0D))); + compute(expression, Val.of(input), ValAssertions.valDate(expectedMs)); } @TestFactory @@ -1562,9 +1651,7 @@ Stream testBODMAS() { .map(testCase -> DynamicTest.dynamicTest(testCase.toString(), () -> compute(testCase.expression, testCase.inputValues, - out -> assertThat(out.toDouble()) - .isEqualTo(testCase.expectedResult.toDouble(), - Offset.offset(0D))))); + ValAssertions.valDouble(testCase.expectedResult.toDouble())))); } @TestFactory @@ -1643,14 +1730,14 @@ Stream testCasts() { void testMappedValues1() { compute("param('testkey')", Val.of("100"), - out -> assertThat(out).isEqualTo(ValString.create("testvalue"))); + ValAssertions.valString("testvalue")); } @Test void testMappedValues2() { compute("params()", Val.of("100"), - out -> assertThat(out).isEqualTo(ValString.create("testkey=\"testvalue\""))); + ValAssertions.valString("testkey=\"testvalue\"")); } @TestFactory diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java index b4eee14a464..0dba7b03933 100644 --- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserAggregates.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java index 4f31881c850..1de1774e8ea 100644 --- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserLinks.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java index cdfc7fc98a0..4c5c92da5cc 100644 --- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParserUris.java @@ -1,11 +1,11 @@ /* - * Copyright 2017 Crown Copyright + * Copyright 2017-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java index 5cee9e969f9..ac439ae314b 100644 --- a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestHash.java @@ -1,7 +1,31 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.query.language.functions; +import org.junit.jupiter.api.Test; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HexFormat; import java.util.stream.Stream; +import static org.assertj.core.api.Assertions.assertThat; + class TestHash extends AbstractFunctionTest { @Override @@ -38,7 +62,8 @@ Stream getTestCases() { ValString.create("sha-256")), TestCase.of( "sha512_noSalt", - ValString.create("ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"), + ValString.create( + "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"), ValString.create("test"), ValString.create("sha-512")), TestCase.of( @@ -61,10 +86,36 @@ Stream getTestCases() { ValString.create("haveSomeSalt")), TestCase.of( "sha512_withSalt", - ValString.create("7559c1cac090b47296f8d8ab5835202821a0024d113b3c4636648d5dce22213ebc3464bb4003890bc763ad2b4c14a5cf4f84241441aefe140d30d8600e5e2520"), + ValString.create( + "7559c1cac090b47296f8d8ab5835202821a0024d113b3c4636648d5dce22213ebc3464bb4003890bc763ad2b4c14a5cf4f84241441aefe140d30d8600e5e2520"), + ValString.create("test"), + ValString.create("sha-512"), + ValString.create("haveSomeSalt")), + TestCase.of( + "md5_withSalt", + ValString.create( + "7559c1cac090b47296f8d8ab5835202821a0024d113b3c4636648d5dce22213ebc3464bb4003890bc763ad2b4c14a5cf4f84241441aefe140d30d8600e5e2520"), ValString.create("test"), ValString.create("sha-512"), ValString.create("haveSomeSalt")) ); } + + /** + * Just make sure digest resetting works. + */ + @Test + void testHash() throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + digest.update("salt".getBytes(StandardCharsets.UTF_8)); + String hex1 = HexFormat.of().formatHex(digest.digest("foo".getBytes(StandardCharsets.UTF_8))); + + digest.reset(); + + digest.update("salt".getBytes(StandardCharsets.UTF_8)); + String hex2 = HexFormat.of().formatHex(digest.digest("foo".getBytes(StandardCharsets.UTF_8))); + + assertThat(hex2) + .isEqualTo(hex1); + } } diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertion.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertion.java new file mode 100644 index 00000000000..ac866dec51b --- /dev/null +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertion.java @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package stroom.query.language.functions; + +/** + * An assertion of a {@link Val} + */ +@FunctionalInterface +public interface ValAssertion { + + /** + * The actual or output {@link Val} for the assertion to test. + */ + void actual(Val actual); +} diff --git a/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertions.java b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertions.java new file mode 100644 index 00000000000..4b5f0d01c83 --- /dev/null +++ b/stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/ValAssertions.java @@ -0,0 +1,162 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package stroom.query.language.functions; + +import org.assertj.core.api.Assertions; + +import java.time.Instant; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Various methods for asserting a {@link Val} value. + */ +public class ValAssertions { + + public static final ValAssertion VAL_NULL_ASSERTION = (Val actual) -> { + Assertions.assertThat(actual) + .isInstanceOf(ValNull.class); + Assertions.assertThat((ValNull) actual) + .isSameAs(ValNull.INSTANCE); + }; + + public static final ValAssertion VAL_ERR_ASSERTION = (Val actual) -> + Assertions.assertThat(actual) + .isInstanceOf(ValErr.class); + + public static final ValAssertion VAL_TRUE_ASSERTION = (Val actual) -> + Assertions.assertThat(actual) + .isInstanceOf(ValBoolean.class) + .isSameAs(ValBoolean.TRUE) + .extracting(Val::toBoolean) + .isEqualTo(true); + + public static final ValAssertion VAL_FALSE_ASSERTION = (Val actual) -> + Assertions.assertThat(actual) + .isInstanceOf(ValBoolean.class) + .isSameAs(ValBoolean.FALSE) + .extracting(Val::toBoolean) + .isEqualTo(false); + + public static final ValAssertion VAL_EMPTY_STRING_ASSERTION = (Val actual) -> + assertThat(actual) + .isInstanceOf(ValString.class) + .isSameAs(ValString.EMPTY) + .extracting(Val::toString) + .isEqualTo(""); + + private ValAssertions() { + } + + public static ValAssertion valTrue() { + return VAL_TRUE_ASSERTION; + } + + public static ValAssertion valFalse() { + return VAL_FALSE_ASSERTION; + } + + public static ValAssertion valNull() { + return VAL_NULL_ASSERTION; + } + + public static ValAssertion valErr() { + return VAL_ERR_ASSERTION; + } + + /** + * @param expectedSubStrings sub-strings that are expected to appear in the error message in any order. + */ + public static ValAssertion valErrContainsIgnoreCase(final String... expectedSubStrings) { + return (Val actual) -> { + Assertions.assertThat(actual) + .isInstanceOf(ValErr.class); + + for (final String expectedSubString : expectedSubStrings) { + Assertions.assertThat(actual.toString()) + .containsIgnoringCase(expectedSubString); + } + }; + } + + public static ValAssertion valString(final String expected) { + return (Val actual) -> + Assertions.assertThat(actual) + .isEqualTo(ValString.create(expected)); + } + + public static ValAssertion valStringEmpty() { + return VAL_EMPTY_STRING_ASSERTION; + } + + public static ValAssertion valDouble(final double expected) { + return (Val out) -> + Assertions.assertThat(out) + .isEqualTo(ValDouble.create(expected)) + .extracting(Val::toDouble) + .isEqualTo(expected); + } + + public static ValAssertion valFloat(final float expected) { + return (Val out) -> + Assertions.assertThat(out) + .isEqualTo(ValFloat.create(expected)) + .extracting(Val::toFloat) + .isEqualTo(expected); + } + + public static ValAssertion valInteger(final int expected) { + return (Val out) -> + Assertions.assertThat(out) + .isEqualTo(ValInteger.create(expected)) + .extracting(Val::toInteger) + .isEqualTo(expected); + } + + public static ValAssertion valLong(final long expected) { + return (Val out) -> + Assertions.assertThat(out) + .isEqualTo(ValLong.create(expected)) + .extracting(Val::toLong) + .isEqualTo(expected); + } + + public static ValAssertion valDate(final long expectedEpochMs) { + return (Val out) -> + Assertions.assertThat(out) + .isInstanceOf(ValDate.class) + .extracting(Val::toLong) + .isEqualTo(expectedEpochMs); + } + + public static ValAssertion valDate(final String expectedNormalDateTimeString) { + return valDate(DateUtil.parseNormalDateTimeString(expectedNormalDateTimeString)); + } + + public static ValAssertion valDate(final Instant expectedInstant) { + return valDate(expectedInstant.toEpochMilli()); + } + + /** + * No type checking, just that {@link Val#toString()} is equal to expected. + */ + public static ValAssertion valAsString(final String expected) { + return (Val out) -> + Assertions.assertThat(out.toString()) + .isEqualTo(expected); + } +} diff --git a/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java b/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java index d5b21532d94..9d13591d357 100644 --- a/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java +++ b/stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/ElasticSearchTaskHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Crown Copyright + * Copyright 2016-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -248,8 +248,8 @@ private void searchSlice(final ElasticIndexDoc elasticIndex, taskContext.info(() -> LogUtil.message("Processed {} hits", totalHits)); final ScrollResponse scrollResponse = elasticClient.scroll(s -> s - .scrollId(scrollId) - .scroll(scrollTime), + .scrollId(scrollId) + .scroll(scrollTime), ObjectNode.class ); diff --git a/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java b/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java index baf6d79772c..4d713f3d85c 100644 --- a/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java +++ b/stroom-search/stroom-search-extraction/src/main/java/stroom/search/extraction/StandardFieldListConsumer.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.search.extraction; import stroom.query.api.v2.QueryKey; diff --git a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java index f54c0d63728..aa1e2a70bdf 100644 --- a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java +++ b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestQueues.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.search.impl; import stroom.query.api.v2.QueryKey; diff --git a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java index 5baa0dc8ece..ffa100e14b1 100644 --- a/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java +++ b/stroom-search/stroom-search-impl/src/test/java/stroom/search/impl/TestSearchResultCreation.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.search.impl; import stroom.bytebuffer.impl6.ByteBufferFactoryImpl; diff --git a/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java b/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java index e3ee787949c..5103baa45f2 100644 --- a/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java +++ b/stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SolrSearchTaskHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Crown Copyright + * Copyright 2016-2024 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java index 77179d3f48a..9b5506871ca 100644 --- a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java +++ b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SearchHelper.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.state.impl.dao; import stroom.entity.shared.ExpressionCriteria; diff --git a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java index 25be5b8d501..e0c394881b9 100644 --- a/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java +++ b/stroom-state/stroom-state-impl/src/main/java/stroom/state/impl/dao/SessionDao.java @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stroom.state.impl.dao; import stroom.entity.shared.ExpressionCriteria; @@ -40,7 +56,6 @@ import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.literal; import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.selectFrom; import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.createTable; -import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.dropTable; public class SessionDao extends AbstractStateDao { diff --git a/unreleased_changes/20241011_111802_755__4444.md b/unreleased_changes/20241011_111802_755__4444.md new file mode 100644 index 00000000000..238f38ea4e0 --- /dev/null +++ b/unreleased_changes/20241011_111802_755__4444.md @@ -0,0 +1,24 @@ +* Issue **#4444** : Change the `hash()` expression function to allow the `algorithm` and `salt` arguments to be the result of functions, e.g. `hash(${field1}, concat('SHA-', ${algoLen}), ${salt})`. + + +```sh +# ******************************************************************************** +# Issue title: hash() function salt parameter will only accept a simple string +# Issue link: https://github.com/gchq/stroom/issues/4444 +# ******************************************************************************** + +# ONLY the top line will be included as a change entry in the CHANGELOG. +# The entry should be in GitHub flavour markdown and should be written on a SINGLE +# line with no hard breaks. You can have multiple change files for a single GitHub issue. +# The entry should be written in the imperative mood, i.e. 'Fix nasty bug' rather than +# 'Fixed nasty bug'. +# +# Examples of acceptable entries are: +# +# +# * Issue **123** : Fix bug with an associated GitHub issue in this repository +# +# * Issue **namespace/other-repo#456** : Fix bug with an associated GitHub issue in another repository +# +# * Fix bug with no associated GitHub issue. +```