Add tests for ClassLoaderScoperWeakMap
MODIFY
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ClassLoaderScopedWeakMap.java
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/ClassLoaderScopedWeakMap.java
package datadog.trace.agent.tooling;
import datadog.trace.bootstrap.WeakMap;
-import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/** A registry which is scoped per-classloader able to hold key-value pairs with weak keys. */
public class ClassLoaderScopedWeakMap {
@@ -15,11 +15,10 @@ public class ClassLoaderScopedWeakMap {
* Gets the element registered at the specified key or register as new one retrieved by the
* provided supplier.
*/
- public synchronized Object getOrCreate(
- ClassLoader classLoader, Object key, Supplier valueSupplier) {
+ public Object getOrCreate(ClassLoader classLoader, Object key, Supplier valueSupplier) {
Map<Object, Object> classLoaderMap = map.get(classLoader);
if (classLoaderMap == null) {
- classLoaderMap = new HashMap<>();
+ classLoaderMap = new ConcurrentHashMap<>();
map.put(classLoader, classLoaderMap);
}

ADD
dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/ClassLoaderScopedWeakMapTest.groovy
+package datadog.trace.agent.tooling
+
+import spock.lang.Shared
+import spock.lang.Specification
+
+
+class ClassLoaderScopedWeakMapTest extends Specification {
+
+ @Shared
+ def classLoader1 = new ClassLoader() {
+ @Override
+ Class<?> loadClass(String name) throws ClassNotFoundException {
+ return super.loadClass(name)
+ }
+ }
+
+ @Shared
+ def classLoader2 = new ClassLoader() {
+ @Override
+ Class<?> loadClass(String name) throws ClassNotFoundException {
+ return super.loadClass(name)
+ }
+ }
+
+ def "getOrCreate a value"() {
+ setup:
+ def supplier = new CounterSupplier()
+ def sut = new ClassLoaderScopedWeakMap()
+
+ when:
+ def count = sut.getOrCreate(classLoader1, 'key', supplier)
+
+ then:
+ count == 1
+ supplier.counter == 1
+ }
+
+ def "getOrCreate a value multiple times same class loader same key"() {
+ setup:
+ def supplier = new CounterSupplier()
+ def sut = new ClassLoaderScopedWeakMap()
+
+ when:
+ def count1 = sut.getOrCreate(classLoader1, 'key', supplier)
+ def count2 = sut.getOrCreate(classLoader1, 'key', supplier)
+
+ then:
+ count1 == 1
+ count2 == 1
+ supplier.counter == 1
+ }
+
+ def "getOrCreate a value multiple times same class loader different keys"() {
+ setup:
+ def supplier = new CounterSupplier()
+ def sut = new ClassLoaderScopedWeakMap()
+
+ when:
+ def count1 = sut.getOrCreate(classLoader1, 'key1', supplier)
+ def count2 = sut.getOrCreate(classLoader1, 'key2', supplier)
+
+ then:
+ count1 == 1
+ count2 == 2
+ supplier.counter == 2
+ }
+
+ def "getOrCreate a value multiple times different class loader same key"() {
+ setup:
+ def supplier = new CounterSupplier()
+ def sut = new ClassLoaderScopedWeakMap()
+
+ when:
+ def count1 = sut.getOrCreate(classLoader1, 'key', supplier)
+ def count2 = sut.getOrCreate(classLoader2, 'key', supplier)
+
+ then:
+ count1 == 1
+ count2 == 2
+ supplier.counter == 2
+ }
+
+ class CounterSupplier implements ClassLoaderScopedWeakMap.Supplier {
+
+ def counter = 0
+
+ @Override
+ Object get() {
+ counter = counter + 1
+ return counter
+ }
+ }
+}

Add tests for ClassLoaderScoperWeakMap