Skip to content

Commit

Permalink
#10095 Extend Context as preparation for logging PR (#10096)
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Brandstätter <timo@swirldslabs.com>
  • Loading branch information
timo0 committed Nov 27, 2023
1 parent 7b3e849 commit adf825c
Show file tree
Hide file tree
Showing 20 changed files with 664 additions and 221 deletions.
37 changes: 36 additions & 1 deletion platform-sdk/docs/base/test-support/test-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,39 @@ executed in isolation (see `org.junit.jupiter.api.parallel.Isolated`).
### Context support

The `@WithContext`, `@WithGlobalContext`, `@WithThreadLocalContext` annotation are documented in the chapter of
the [Context API](./../context/context.md).
the [Context API](./../context/context.md).

### Executor support

The `@WithTestExecutor` annotation is used to inject a `TestExecutor` instance into a test. Each test using
`@WithTestExecutor` runs in isolation, ensuring that multiple tests do not share the same underlying thread pool
concurrently. This isolation helps prevent side effects between tests due to shared resources.

#### Usage

```java
@WithTestExecutor
public class MyConcurrentTest {
// Your concurrent test methods here...
}
```
#### Example

```java
@WithTestExecutor
public class TestExecutorExample {
@Inject
TestExecutor testExecutor;

// more code ...

@Test
void testWithConfig() {
// given
final List<Runnable> runnables =
IntStream.range(0, 20).mapToObj(this::createRunnable).toList();
testExecutor.executeAndWait(runnables);
}
}
```

Original file line number Diff line number Diff line change
Expand Up @@ -35,161 +35,71 @@ public interface Context {
*
* @param key the key
* @param value the value
* @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context
* @throws NullPointerException if the key or value is null
*/
void add(@NonNull final String key, @NonNull final String value);
AutoCloseable add(@NonNull String key, @NonNull String value);

/**
* remove a key-value pair from the context if available.
*
* @param key the key to remove
*/
void remove(@NonNull final String key);

/**
* Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the
* given key.
* <p>
* Internally the context does not use a stack to store changes. If the value has been changed between this call and
* any future call that sets the same key, the new value will be removed.
*
* @param key the key
* @param value the value
* @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context
* @throws NullPointerException if the key or value is null
*/
@NonNull
default AutoCloseable addWithRemovalOnClose(@NonNull final String key, @NonNull final String value) {
add(key, value);
return () -> remove(key);
}
void remove(@NonNull String key);

/**
* Adds a key-value pair to the context.
*
* @param key the key
* @param value the value
*/
@NonNull
default void add(@NonNull final String key, final int value) {
add(key, Integer.toString(value));
}

/**
* Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the given key.
*<p>
* Internally the context does not use a stack to store changes. If the value has been changed between this call and any future call that sets the same key, the new value will be removed.
* @param key the key
* @param value the value
* @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context
*/
@NonNull
default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final int value) {
return addWithRemovalOnClose(key, Integer.toString(value));
default AutoCloseable add(@NonNull String key, int value) {
return add(key, Integer.toString(value));
}

/**
* Adds a key-value pair to the context.
*
* @param key the key
* @param value the value
*/
@NonNull
default void add(@NonNull final String key, final long value) {
add(key, Long.toString(value));
}

/**
* Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the given key.
*<p>
* Internally the context does not use a stack to store changes. If the value has been changed between this call and any future call that sets the same key, the new value will be removed.
* @param key the key
* @param value the value
* @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context
*/
@NonNull
default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final long value) {
return addWithRemovalOnClose(key, Long.toString(value));
default AutoCloseable add(@NonNull String key, long value) {
return add(key, Long.toString(value));
}

/**
* Adds a key-value pair to the context.
*
* @param key the key
* @param value the value
*/
@NonNull
default void add(@NonNull final String key, final float value) {
add(key, Float.toString(value));
}

/**
* Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the
* given key.
* <p>
* Internally the context does not use a stack to store changes. If the value has been changed between this call and
* any future call that sets the same key, the new value will be removed.
*
* @param key the key
* @param value the value
* @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context
*/
@NonNull
default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final float value) {
return addWithRemovalOnClose(key, Float.toString(value));
default AutoCloseable add(@NonNull String key, float value) {
return add(key, Float.toString(value));
}

/**
* Adds a key-value pair to the context.
*
* @param key the key
* @param value the value
*/
@NonNull
default void add(@NonNull final String key, final double value) {
add(key, Double.toString(value));
}

/**
* Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the
* given key.
* <p>
* Internally the context does not use a stack to store changes. If the value has been changed between this call and
* any future call that sets the same key, the new value will be removed.
*
* @param key the key
* @param value the value
* @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context
*/
@NonNull
default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final double value) {
return addWithRemovalOnClose(key, Double.toString(value));
default AutoCloseable add(@NonNull String key, double value) {
return add(key, Double.toString(value));
}

/**
* Adds a key-value pair to the context.
*
* @param key the key
* @param value the value
*/
@NonNull
default void add(@NonNull final String key, final boolean value) {
add(key, Boolean.toString(value));
}

/**
* Adds a key-value pair to the context. The returned {@link AutoCloseable} can be used to remove the value for the
* given key.
* <p>
* Internally the context does not use a stack to store changes. If the value has been changed between this call and
* any future call that sets the same key, the new value will be removed.
*
* @param key the key
* @param value the value
* @return an {@link AutoCloseable} that can be used to remove the key-value pair from the context
*/
@NonNull
default AutoCloseable addWithRemovalOnClose(@NonNull final String key, final boolean value) {
return addWithRemovalOnClose(key, Boolean.toString(value));
default AutoCloseable add(@NonNull String key, boolean value) {
return add(key, Boolean.toString(value));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ private GlobalContext() {
}

@Override
public void add(@NonNull String key, @NonNull String value) {
public AutoCloseable add(@NonNull String key, @NonNull String value) {
Objects.requireNonNull(key, "key must not be null");
Objects.requireNonNull(value, "value must not be null");

contextMap.put(key, value);
return () -> remove(key);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private ThreadLocalContext() {
}

@Override
public void add(@NonNull String key, @NonNull String value) {
public AutoCloseable add(@NonNull String key, @NonNull String value) {
Objects.requireNonNull(key, "key must not be null");
Objects.requireNonNull(value, "value must not be null");

Expand All @@ -54,6 +54,7 @@ public void add(@NonNull String key, @NonNull String value) {
contextThreadLocal.set(contextMap);
}
contextMap.put(key, value);
return () -> remove(key);
}

@Override
Expand Down
3 changes: 2 additions & 1 deletion platform-sdk/swirlds-base/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
exports com.swirlds.base.utility;
exports com.swirlds.base.context;
exports com.swirlds.base.context.internal to
com.swirlds.base.test.fixtures;
com.swirlds.base.test.fixtures,
com.swirlds.logging;

requires static com.github.spotbugs.annotations;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ void testNullKeyOrValue() {
GlobalContext context = GlobalContext.getInstance();

// then
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, "value"));
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1));
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1L));
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1.0D));
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, 1.0F));
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, true));
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose("foo", null));
Assertions.assertThrows(NullPointerException.class, () -> context.addWithRemovalOnClose(null, null));
Assertions.assertThrows(NullPointerException.class, () -> context.add(null, "value"));
Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1));
Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1L));
Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1.0D));
Assertions.assertThrows(NullPointerException.class, () -> context.add(null, 1.0F));
Assertions.assertThrows(NullPointerException.class, () -> context.add(null, true));
Assertions.assertThrows(NullPointerException.class, () -> context.add("foo", null));
Assertions.assertThrows(NullPointerException.class, () -> context.add(null, null));
}

@Test
Expand All @@ -47,12 +47,12 @@ void testAllPut() {
GlobalContext context = GlobalContext.getInstance();

// when
context.addWithRemovalOnClose("key-string", "value");
context.addWithRemovalOnClose("key-int", 1);
context.addWithRemovalOnClose("key-long", 1L);
context.addWithRemovalOnClose("key-double", 1.0D);
context.addWithRemovalOnClose("key-float", 1.0F);
context.addWithRemovalOnClose("key-boolean", true);
context.add("key-string", "value");
context.add("key-int", 1);
context.add("key-long", 1L);
context.add("key-double", 1.0D);
context.add("key-float", 1.0F);
context.add("key-boolean", true);

// then
final Map<String, String> contextMap = context.getContextMap();
Expand All @@ -71,9 +71,9 @@ void testOverwrite() {
GlobalContext context = GlobalContext.getInstance();

// when
context.addWithRemovalOnClose("key", "a");
context.addWithRemovalOnClose("key", "b");
context.addWithRemovalOnClose("key", "c");
context.add("key", "a");
context.add("key", "b");
context.add("key", "c");

// then
final Map<String, String> contextMap = context.getContextMap();
Expand All @@ -87,7 +87,7 @@ void testRemove() {
GlobalContext context = GlobalContext.getInstance();

// when
context.addWithRemovalOnClose("key", "a");
context.add("key", "a");
context.remove("key");

// then
Expand All @@ -108,8 +108,8 @@ void testRemoveNullKey() {
void testClear() {
// given
GlobalContext context = GlobalContext.getInstance();
context.addWithRemovalOnClose("key", "a");
context.addWithRemovalOnClose("key-2", "a");
context.add("key", "a");
context.add("key-2", "a");

// when
context.clear();
Expand All @@ -123,7 +123,7 @@ void testClear() {
void testAutocloseable() {
// given
GlobalContext context = GlobalContext.getInstance();
AutoCloseable closeable = context.addWithRemovalOnClose("key", "a");
AutoCloseable closeable = context.add("key", "a");

// when
Assertions.assertDoesNotThrow(() -> closeable.close());
Expand Down
Loading

0 comments on commit adf825c

Please sign in to comment.