Skip to content

Commit eace412

Browse files
Config and system properties preservation in ddspec
1 parent 4f9ae43 commit eace412

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

utils/test-utils/src/main/groovy/datadog/trace/test/util/DDSpecification.groovy

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
package datadog.trace.test.util
22

3+
34
import net.bytebuddy.agent.ByteBuddyAgent
45
import net.bytebuddy.agent.builder.AgentBuilder
56
import net.bytebuddy.dynamic.ClassFileLocator
67
import net.bytebuddy.dynamic.Transformer
8+
import org.junit.Rule
9+
import org.junit.contrib.java.lang.system.EnvironmentVariables
10+
import org.junit.contrib.java.lang.system.RestoreSystemProperties
711
import spock.lang.Specification
812

13+
import java.lang.reflect.Constructor
14+
import java.lang.reflect.Field
15+
import java.lang.reflect.Modifier
16+
917
import static net.bytebuddy.description.modifier.FieldManifestation.VOLATILE
1018
import static net.bytebuddy.description.modifier.Ownership.STATIC
1119
import static net.bytebuddy.description.modifier.Visibility.PUBLIC
@@ -15,13 +23,22 @@ import static net.bytebuddy.matcher.ElementMatchers.none
1523
abstract class DDSpecification extends Specification {
1624
private static final String CONFIG = "datadog.trace.api.Config"
1725

26+
private static Field CONFIG_INSTANCE_FIELD
27+
private static Constructor CONFIG_CONSTRUCTOR
28+
1829
static {
1930
makeConfigInstanceModifiable()
2031
}
2132

2233
// Keep track of config instance already made modifiable
2334
private static isConfigInstanceModifiable = false
2435

36+
@Rule
37+
public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
38+
39+
@Rule
40+
protected final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
41+
2542
static void makeConfigInstanceModifiable() {
2643
if (isConfigInstanceModifiable) {
2744
return
@@ -43,6 +60,46 @@ abstract class DDSpecification extends Specification {
4360
.transform(Transformer.ForField.withModifiers(PUBLIC, STATIC, VOLATILE))
4461
}
4562
.installOn(instrumentation)
63+
64+
Class configClass = Class.forName(CONFIG)
65+
CONFIG_INSTANCE_FIELD = configClass.getDeclaredField("INSTANCE")
66+
CONFIG_CONSTRUCTOR = configClass.getDeclaredConstructor()
67+
CONFIG_CONSTRUCTOR.setAccessible(true)
68+
4669
isConfigInstanceModifiable = true
4770
}
71+
72+
void cleanupSpec() {
73+
rebuildConfig()
74+
}
75+
76+
void setup() {
77+
rebuildConfig()
78+
}
79+
80+
void injectSysConfig(String name, String value) {
81+
String prefixedName = name.startsWith("dd.") ? name : "dd." + name
82+
System.setProperty(prefixedName, value)
83+
rebuildConfig()
84+
}
85+
86+
void injectEnvConfig(String name, String value) {
87+
String prefixedName = name.startsWith("DD_") ? name : "DD_" + name
88+
environmentVariables.set(prefixedName, value)
89+
rebuildConfig()
90+
}
91+
92+
/**
93+
* Reset the global configuration. Please note that Runtime ID is preserved to the pre-existing value.
94+
*/
95+
synchronized static void rebuildConfig() {
96+
// Ensure the class was re-transformed properly in DDSpecification.makeConfigInstanceModifiable()
97+
assert Modifier.isPublic(CONFIG_INSTANCE_FIELD.getModifiers())
98+
assert Modifier.isStatic(CONFIG_INSTANCE_FIELD.getModifiers())
99+
assert Modifier.isVolatile(CONFIG_INSTANCE_FIELD.getModifiers())
100+
assert !Modifier.isFinal(CONFIG_INSTANCE_FIELD.getModifiers())
101+
102+
def newConfig = CONFIG_CONSTRUCTOR.newInstance()
103+
CONFIG_INSTANCE_FIELD.set(null, newConfig)
104+
}
48105
}

utils/test-utils/test-utils.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ dependencies {
66

77
compile deps.bytebuddy
88
compile deps.bytebuddyagent
9+
10+
compile group: 'com.github.stefanbirkner', name: 'system-rules', version: '1.19.0'
911
}

0 commit comments

Comments
 (0)