diff --git a/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/RateLimiters.java b/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/RateLimiters.java index 582f890f0..676a873e6 100644 --- a/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/RateLimiters.java +++ b/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/RateLimiters.java @@ -25,13 +25,9 @@ public enum RateLimiters { private static final Logger logger = LogManager.getLogger(RateLimiters.class); public static synchronized RateLimiter createOrUpdate(final NBComponent parent, final RateLimiter extant, final SimRateSpec spec) { - return createOrUpdate(parent, extant, spec, "cycle"); - } - - public static synchronized RateLimiter createOrUpdate(final NBComponent parent, final RateLimiter extant, final SimRateSpec spec,final String type) { if (null == extant) { - final RateLimiter rateLimiter= new SimRate(parent, spec, type); + final RateLimiter rateLimiter= new SimRate(parent, spec); RateLimiters.logger.info(() -> "Using rate limiter: " + rateLimiter); return rateLimiter; diff --git a/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/SimRate.java b/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/SimRate.java index f2e48122a..e2848b3fc 100644 --- a/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/SimRate.java +++ b/engine-core/src/main/java/io/nosqlbench/engine/api/activityapi/simrate/SimRate.java @@ -79,58 +79,34 @@ public class SimRate extends NBBaseComponent implements RateLimiter, Thread.Unca private long startTime; public SimRate(NBComponent parent, SimRateSpec spec) { - this(parent, spec, "cycle"); - } - - public SimRate(NBComponent parent, SimRateSpec spec, String type) { - super(parent, NBLabels.forKV()); + super(parent, NBLabels.forKV().and("rateType", + (spec instanceof CycleRateSpec? "cycle" : "stride"))); this.spec = spec; - initMetrics(type); + initMetrics(); startFiller(); } - private void initMetrics(String type) { - if (type.equalsIgnoreCase("cycle")) { - create().gauge( - "cycles_waittime", - () -> (double) getWaitTimeDuration().get(ChronoUnit.NANOS), - MetricCategory.Core, - "The cumulative scheduling delay which accrues when" + - " an activity is not able to execute operations as fast as requested." - ); - create().gauge( - "config_cyclerate", - () -> spec.opsPerSec, - MetricCategory.Config, - "The configured cycle rate in ops/s" - ); - create().gauge( - "config_burstrate", - () -> spec.burstRatio, - MetricCategory.Config, - "the configured burst rate as a multiplier to the configured cycle rate. ex: 1.05 means 5% faster is allowed." - ); - } else { - create().gauge( - "stride_waittime", - () -> (double) getWaitTimeDuration().get(ChronoUnit.NANOS), - MetricCategory.Core, - "The cumulative scheduling delay which accrues when" + - " an activity is not able to execute operations as fast as requested." - ); - create().gauge( - "config_striderate", - () -> spec.opsPerSec, - MetricCategory.Config, - "The configured stride rate in ops/s" - ); - create().gauge( - "config_burstrate", - () -> spec.burstRatio, - MetricCategory.Config, - "the configured burst rate as a multiplier to the configured cycle rate. ex: 1.05 means 5% faster is allowed." - ); - } + private void initMetrics() { + String rateType = getLabels().valueOf("rateType"); + create().gauge( + rateType + "s_waittime", + () -> (double) getWaitTimeDuration().get(ChronoUnit.NANOS), + MetricCategory.Core, + "The cumulative scheduling delay which accrues when" + + " an activity is not able to execute operations as fast as requested." + ); + create().gauge( + "config_" + rateType + "rate", + () -> spec.opsPerSec, + MetricCategory.Config, + "The configured cycle rate in ops/s" + ); + create().gauge( + rateType + "_config_burstrate", + () -> spec.burstRatio, + MetricCategory.Config, + "the configured burst rate as a multiplier to the configured cycle rate. ex: 1.05 means 5% faster is allowed." + ); } public long refill() { diff --git a/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java b/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java index 44da12c1f..e391b3753 100644 --- a/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java +++ b/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java @@ -89,8 +89,6 @@ public class SimpleActivity extends NBStatusComponent implements Activity, Invok private ActivityMetricProgressMeter progressMeter; private String workloadSource = "unspecified"; private final RunStateTally tally = new RunStateTally(); - public static final String STRIDE = "stride"; - public static final String CYCLE = "cycle"; public SimpleActivity(NBComponent parent, ActivityDef activityDef) { super(parent, NBLabels.forKV("activity", activityDef.getAlias()).and(activityDef.auxLabels())); @@ -317,11 +315,11 @@ public class SimpleActivity extends NBStatusComponent implements Activity, Invok } public void createOrUpdateStrideLimiter(SimRateSpec spec) { - strideLimiter = RateLimiters.createOrUpdate(this, strideLimiter, spec, STRIDE); + strideLimiter = RateLimiters.createOrUpdate(this, strideLimiter, spec); } public void createOrUpdateCycleLimiter(SimRateSpec spec) { - cycleLimiter = RateLimiters.createOrUpdate(this, cycleLimiter, spec, CYCLE); + cycleLimiter = RateLimiters.createOrUpdate(this, cycleLimiter, spec); } /** diff --git a/virtdata-api/src/main/java/io/nosqlbench/virtdata/api/bindings/VirtDataConversions.java b/virtdata-api/src/main/java/io/nosqlbench/virtdata/api/bindings/VirtDataConversions.java index 189575829..d04005194 100644 --- a/virtdata-api/src/main/java/io/nosqlbench/virtdata/api/bindings/VirtDataConversions.java +++ b/virtdata-api/src/main/java/io/nosqlbench/virtdata/api/bindings/VirtDataConversions.java @@ -20,10 +20,7 @@ import io.nosqlbench.nb.api.errors.BasicError; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.TypeVariable; +import java.lang.reflect.*; import java.security.InvalidParameterException; import java.util.*; import java.util.function.LongFunction; @@ -70,6 +67,18 @@ public class VirtDataConversions { private static final Logger logger = LogManager.getLogger(VirtDataConversions.class); + public static T[] adaptFunctionArray(F[] functionObjects, Class functionType, Class... resultSignature) { + T[] functions = (T[]) Array.newInstance(functionType, functionObjects.length); + + for (int i = 0; i < functionObjects.length; i++) { + F func = functionObjects[i]; + T adapted = adaptFunction(func, functionType, resultSignature); + functions[i]=adapted; + } + return functions; + } + + public static List adaptFunctionList(F[] funcs, Class functionType, Class... resultSignature) { List functions = new ArrayList<>(); for (Object func : funcs) { diff --git a/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/Concat.java b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/Concat.java new file mode 100644 index 000000000..639cb5ea7 --- /dev/null +++ b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/Concat.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2024 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.virtdata.library.basics.shared.from_long.to_string; + +import io.nosqlbench.virtdata.api.annotations.Categories; +import io.nosqlbench.virtdata.api.annotations.Category; +import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper; +import io.nosqlbench.virtdata.api.bindings.VirtDataConversions; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.LongBinaryOperator; +import java.util.function.LongFunction; +import java.util.regex.Matcher; + + +/** + *

This is the core implementation of the Concat style of String + * binding. It is the newer and recommended version of {@link Template}.

+ * + *

Users should use one of these wrappers: + *

    + *
  • {@link ConcatCycle} - all inputs are the cycle value
  • + *
  • {@link ConcatHashed} - all inputs are a hash of (cycle+step)
  • + *
  • {@link ConcatStepped} - all inputs are (cycle+step)
  • + *
  • {@link ConcatFixed} - all inputs are always the same value
  • + *
  • {@link ConcatChained} - all inputs are chained hashes of the previous one
  • + *

+ *

+ *


+ * + *

This implementation is available for specialized use when needed, but the + * above versions are much more self-explanatory and easy to use.

+ * + *

As with previous implementations, the basic input which is fed to the functions + * is the sum of the input cycle and the step, where the step is simply the index of + * the insertion point within the template string. These start at 0, so a template string + * which contains "{}-{}" will have two steps, 0, and 1. For cycle 35, the first + * function will take input 35, and the second 36. This can create some local neighborhood + * similarity in test data, so other forms are provided which can hash the values for + * an added degree of (effective) randomness and one that chains these so that each + * set of values from a Concat binding are quite distinct from each other.

+ *

+ *


+ *

Binding functions used to populate each step of the template may have their own bounds + * of output values like {@link Combinations}. These are easy to use internally since they + * work well with the hashing. However, some other functions may operate over the whole space + * of long values, and come with no built-in cardinality constraints. It is recommended to + * use those with built-in constraints when you want to render a discrete population of values.

+ */ +@ThreadSafeMapper +@Categories(Category.general) +public class Concat implements LongFunction { + + private final static Logger logger = LogManager.getLogger(Concat.class); + protected final LongBinaryOperator cycleStepMapper; + protected final String[] literals; + protected final LongFunction[] functions; + + public Concat(String template, Object... functions) { + this(Long::sum, template, functions); + } + + public Concat(LongBinaryOperator cycleStepMapper, String template, Object... functions) { + this.cycleStepMapper = cycleStepMapper; + this.literals = parseTemplate(template); + if (literals.length > 1 && functions.length < 1) { + logger.warn("You provided zero functions to go with concat template " + template + ", inserting diagnostic function for \"v:\"(cycle+step)"); + this.functions = new LongFunction[]{l -> "v:" + l}; + } else { + this.functions = VirtDataConversions.adaptFunctionArray(functions, LongFunction.class, Object.class); + } + } + + @Override + public String apply(long cycle) { + StringBuilder buffer = new StringBuilder(); + buffer.setLength(0); + for (int i = 0; i < literals.length - 1; i++) { + buffer.append(literals[i]); + long value = cycleStepMapper.applyAsLong(cycle, i); + int funcIdx = Math.min(functions.length - 1, i); + LongFunction selectedFunction = functions[funcIdx]; + String string = selectedFunction.apply(value); + buffer.append(string); + } + buffer.append(literals[literals.length - 1]); + return buffer.toString(); + } + + + private String[] parseTemplate(String template) { + try { + List literals = new ArrayList<>(); + java.util.regex.Pattern p = java.util.regex.Pattern.compile("\\{}"); + Matcher m = p.matcher(template); + int pos = 0; + while (m.find()) { + literals.add(template.substring(pos, m.start())); + pos = m.end(); + } + String partial = template.substring(pos); + literals.add(partial); + return literals.toArray(new String[0]); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatChained.java b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatChained.java new file mode 100644 index 000000000..643704c7f --- /dev/null +++ b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatChained.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.virtdata.library.basics.shared.from_long.to_string; + +import io.nosqlbench.virtdata.api.annotations.Categories; +import io.nosqlbench.virtdata.api.annotations.Category; +import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper; +import io.nosqlbench.virtdata.library.basics.shared.from_long.to_long.Hash; + +import java.util.function.LongFunction; + +/** + *

This is a variant of Concat which chains the hash values + * from step to step so that each of the provided functions will + * yield unrelated values. The first input value to a function + * is a hash of the cycle input value, the next is a hash of the + * first input value, and so on.

+ */ +@ThreadSafeMapper +@Categories(Category.general) +public class ConcatChained extends Concat { + private final static Hash hash = new Hash(); + public ConcatChained(String template, Object... functions) { + super((c,s) -> hash.applyAsLong(c+s), template, functions); + } + + @Override + public String apply(long cycle) { + StringBuilder buffer = new StringBuilder(); + buffer.setLength(0); + buffer.append(literals[0]); + long value = cycle; + for (int i = 0; i < literals.length-1; i++) { + value = hash.applyAsLong(value); + buffer.append(literals[i]); + int funcIdx = Math.min(functions.length - 1, i); + LongFunction selectedFunction = functions[funcIdx]; + String string = selectedFunction.apply(value); + buffer.append(string); + } + buffer.append(literals[literals.length-1]); + return buffer.toString(); + } + + +} diff --git a/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatCycle.java b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatCycle.java new file mode 100644 index 000000000..3abcf8751 --- /dev/null +++ b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatCycle.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.virtdata.library.basics.shared.from_long.to_string; + +import io.nosqlbench.virtdata.api.annotations.Categories; +import io.nosqlbench.virtdata.api.annotations.Category; +import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper; + +/** + *

This is a variant of Concat which always uses the input cycle value + * as the input for all the functions provided.

+ */ +@ThreadSafeMapper +@Categories(Category.general) +public class ConcatCycle extends Concat { + + public ConcatCycle(String template, Object... functions) { + super((c,s) -> c, template, functions); + } +} diff --git a/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatFixed.java b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatFixed.java new file mode 100644 index 000000000..859a1b8e3 --- /dev/null +++ b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatFixed.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.virtdata.library.basics.shared.from_long.to_string; + +import io.nosqlbench.virtdata.api.annotations.Categories; +import io.nosqlbench.virtdata.api.annotations.Category; +import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper; +import io.nosqlbench.virtdata.api.bindings.VirtDataConversions; + +import java.util.function.LongUnaryOperator; + +/** + *

This is a variant of Concat which always uses the same value + * as input for the functions provided.

+ */ +@ThreadSafeMapper +@Categories(Category.general) +public class ConcatFixed extends Concat { + + public ConcatFixed(long value, String template, Object... functions) { + super((c,s) -> value, template, functions); + } +} diff --git a/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatHashed.java b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatHashed.java new file mode 100644 index 000000000..df40a5a99 --- /dev/null +++ b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatHashed.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.virtdata.library.basics.shared.from_long.to_string; + +import io.nosqlbench.virtdata.api.annotations.Categories; +import io.nosqlbench.virtdata.api.annotations.Category; +import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper; +import io.nosqlbench.virtdata.library.basics.shared.from_long.to_long.Hash; + +/** + *

This is a variant of Concat which always hashes the cycle+step value + * for each function provided.

+ */ +@ThreadSafeMapper +@Categories(Category.general) +public class ConcatHashed extends Concat { + private final static Hash hash = new Hash(); + public ConcatHashed(String template, Object... functions) { + super((c,s) -> hash.applyAsLong(c+s), template, functions); + } +} diff --git a/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatStepped.java b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatStepped.java new file mode 100644 index 000000000..df0bbbc74 --- /dev/null +++ b/virtdata-lib-basics/src/main/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatStepped.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.virtdata.library.basics.shared.from_long.to_string; + +import io.nosqlbench.virtdata.api.annotations.Categories; +import io.nosqlbench.virtdata.api.annotations.Category; +import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper; +import io.nosqlbench.virtdata.api.bindings.VirtDataConversions; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.LongBinaryOperator; +import java.util.function.LongFunction; +import java.util.regex.Matcher; + +/** + *

This is a variant of Concat which uses the cycle+step sum for each + * of the functions provided.

+ */ +@ThreadSafeMapper +@Categories(Category.general) +public class ConcatStepped extends Concat { + + public ConcatStepped(String template, Object... functions) { + super(Long::sum, template, functions); + } +} diff --git a/virtdata-lib-basics/src/test/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatTest.java b/virtdata-lib-basics/src/test/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatTest.java new file mode 100644 index 000000000..ae39c8ab4 --- /dev/null +++ b/virtdata-lib-basics/src/test/java/io/nosqlbench/virtdata/library/basics/shared/from_long/to_string/ConcatTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.virtdata.library.basics.shared.from_long.to_string; + +import io.nosqlbench.virtdata.library.basics.shared.conversions.from_long.ToHexString; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class ConcatTest { + + @Test + public void testEmptyString() { + Concat p = new Concat(""); + assertThat(p.apply(3L)).isEqualTo(""); + } + + @Test + public void testMismatchedInserts() { + Concat c = new Concat("{}"); + assertThat(c.apply(3L)).isEqualTo("v:3"); + } + + @Test + public void testOnlyLiteral() { + Concat l = new Concat(Long::sum, "literal"); + assertThat(l.apply(3L)).isEqualTo("literal"); + } + @Test + public void testSimpleValue() { + Concat p = new Concat(Long::sum, "{}", new NumberNameToString()); + assertThat(p.apply(1)).isEqualTo("one"); + } + + @Test + public void testFixedCycle() { + Concat p = new Concat((c, s) -> c, "{}-{}", new NumberNameToString()); + assertThat(p.apply(3L)).isEqualTo("three-three"); + } + + @Test + public void testSteppedCycle() { + Concat p = new Concat(Long::sum, "{}-{}", new NumberNameToString()); + assertThat(p.apply(3L)).isEqualTo("three-four"); + } + + + @Test + public void testConcatChained() { + ConcatChained cc = new ConcatChained("{}-{}", new ToHexString()); + assertThat(cc.apply(1)).isEqualTo("5752fae69d1653da-7dfbf78ca62528b5"); + } + +}