Skip to content

Commit 3ff06d6

Browse files
committed
Start on RandomnessExtension
1 parent 9ecb29e commit 3ff06d6

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* https://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*
14+
*/
15+
16+
package org.spockframework.runtime.extension.builtin;
17+
18+
import spock.config.ConfigurationObject;
19+
20+
import java.util.Optional;
21+
22+
@ConfigurationObject("randomness")
23+
public class RandomnessConfig {
24+
public static final String SEED_KEY = "spock.randomness.seed";
25+
Object seed = Optional.of((Object) System.getProperty(SEED_KEY)).orElseGet(System::currentTimeMillis);
26+
boolean printSeedValueOnStart = false;
27+
boolean printSeedValueOnFirstUse = true;
28+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* https://www.apache.org/licenses/LICENSE-2.0
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*
14+
*/
15+
16+
package org.spockframework.runtime.extension.builtin;
17+
18+
import org.spockframework.runtime.extension.IGlobalExtension;
19+
import org.spockframework.runtime.extension.IMethodInvocation;
20+
import org.spockframework.runtime.extension.ISpockExecution;
21+
import org.spockframework.runtime.extension.IStore;
22+
import org.spockframework.util.Checks;
23+
24+
import java.util.Random;
25+
import java.util.concurrent.atomic.AtomicBoolean;
26+
import java.util.function.Supplier;
27+
28+
public class RandomnessExtension implements IGlobalExtension {
29+
private static final IStore.Namespace NAMESPACE = IStore.Namespace.create(RandomnessExtension.class);
30+
31+
private final RandomnessConfig config;
32+
33+
public RandomnessExtension(RandomnessConfig config) {
34+
this.config = config;
35+
}
36+
37+
38+
long getSeedValue() {
39+
Object seed = config.seed;
40+
Checks.notNull(seed, () -> "seed must not be null");
41+
if (seed instanceof Number) {
42+
return ((Number) seed).longValue();
43+
}
44+
String stringRepresentation = String.valueOf(seed);
45+
try {
46+
return Long.parseLong(stringRepresentation);
47+
} catch (NumberFormatException ignore) {
48+
}
49+
return stringRepresentation.hashCode();
50+
}
51+
52+
@Override
53+
public void executionStart(ISpockExecution spockExecution) {
54+
long seedValue = getSeedValue();
55+
if (config.printSeedValueOnStart) {
56+
printSeedValue(seedValue);
57+
spockExecution.getStore(NAMESPACE).put("randomnessSource", ((RandomnessSource) () -> new Random(seedValue)));
58+
} else if (config.printSeedValueOnFirstUse) {
59+
AtomicBoolean printed = new AtomicBoolean();
60+
spockExecution.getStore(NAMESPACE).put("randomnessSource", ((RandomnessSource) () -> {
61+
if (printed.compareAndSet(false, true)) {
62+
printSeedValue(seedValue);
63+
}
64+
return new Random(seedValue);
65+
}));
66+
} else {
67+
spockExecution.getStore(NAMESPACE).put("randomnessSource", ((RandomnessSource) () -> new Random(seedValue)));
68+
}
69+
70+
}
71+
72+
private static void printSeedValue(long seedValue) {
73+
System.err.printf("Spock Randomness using seed=%d you can rerun with -D%s=%d%n", seedValue, RandomnessConfig.SEED_KEY, seedValue);
74+
}
75+
76+
public static RandomnessSource getRandomnessSupplier(IMethodInvocation methodInvocation) {
77+
return methodInvocation.getStore(NAMESPACE).get("randomnessSource", RandomnessSource.class);
78+
}
79+
80+
@FunctionalInterface
81+
public interface RandomnessSource extends Supplier<Random> {
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
org.spockframework.runtime.extension.builtin.IncludeExcludeExtension
22
org.spockframework.runtime.extension.builtin.OptimizeRunOrderExtension
3+
org.spockframework.runtime.extension.builtin.RandomnessExtension
34
org.spockframework.runtime.extension.builtin.UnrollExtension

0 commit comments

Comments
 (0)