Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dd-java-agent/instrumentation/robolectric-4.13/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ muzzle {
// androidx.test:monitor is an Android archive (.aar) that a JVM configuration cannot consume;
// it is not referenced by the advice/helper. Mirror the compileOnly exclusion below.
excludeDependency 'androidx.test:monitor'
// Robolectric loads the selected Android SDK dynamically, so android-all is not a transitive
// dependency even though android.os.Build is available when the helper runs.
extraDependency 'org.robolectric:android-all:14-robolectric-10818077'
}
}

Expand All @@ -32,6 +35,7 @@ dependencies {
compileOnly(group: 'org.robolectric', name: 'robolectric', version: '4.16.1') {
exclude group: 'androidx.test', module: 'monitor'
}
compileOnly group: 'org.robolectric', name: 'android-all', version: '14-robolectric-10818077'
// RobolectricTestRunner extends JUnit's BlockJUnit4ClassRunner; JUnit must be on the compile
// classpath so its supertypes resolve (both javac and forbiddenApis walk the class hierarchy).
compileOnly group: 'junit', name: 'junit', version: '4.13.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ org.ow2.asm:asm-tree:9.8=compileClasspath
org.ow2.asm:asm-util:9.10.1=spotbugs
org.ow2.asm:asm-util:9.7.1=testRuntimeClasspath
org.ow2.asm:asm:9.10.1=buildTimeInstrumentationPlugin,compileClasspath,muzzleTooling,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath
org.robolectric:android-all:14-robolectric-10818077=compileClasspath
org.robolectric:annotations:4.16.1=compileClasspath
org.robolectric:junit:4.16.1=compileClasspath
org.robolectric:nativeruntime:4.16.1=compileClasspath
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package datadog.trace.instrumentation.robolectric;

import android.os.Build;
import datadog.trace.api.gateway.RequestContext;
import datadog.trace.api.gateway.RequestContextSlot;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
import datadog.trace.bootstrap.instrumentation.api.Tags;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.versioning.AndroidVersions;

public final class RobolectricTestAnnotator {

Expand All @@ -40,17 +41,44 @@ public static void annotate() {
}

span.setTag(Tags.TEST_ANDROID_API_LEVEL, apiLevel);
AndroidVersions.AndroidRelease release = AndroidVersions.getReleaseForSdkInt(apiLevel);
if (release != null) {
span.setTag(Tags.TEST_ANDROID_RELEASE, release.getVersion());
span.setTag(Tags.TEST_ANDROID_CODENAME, release.getShortCode());
span.setTag(Tags.TEST_ANDROID_RELEASE, Build.VERSION.RELEASE);
String androidCodename = androidCodename(apiLevel);
if (androidCodename != null) {
span.setTag(Tags.TEST_ANDROID_CODENAME, androidCodename);
}
String robolectricVersion = robolectricVersion();
if (robolectricVersion != null) {
span.setTag(Tags.TEST_ANDROID_ROBOLECTRIC_VERSION, robolectricVersion);
}
}

private static String androidCodename(int apiLevel) {
try {
// Released Android SDKs report "REL" through Build.VERSION.CODENAME. Derive the public
// short codename (NMR1, Sv2, U, and so on) from the matching VERSION_CODES field instead.
for (Field field : Build.VERSION_CODES.class.getFields()) {
if (field.getType() == int.class && field.getInt(null) == apiLevel) {
return androidCodename(field.getName());
}
}
} catch (Throwable t) {
// Ignore missing or inaccessible fields and omit the optional codename tag.
}
return null;
}

static String androidCodename(String versionCodeName) {
int minorReleaseIndex = versionCodeName.lastIndexOf("_MR");
if (minorReleaseIndex >= 0) {
return versionCodeName.substring(0, 1) + versionCodeName.substring(minorReleaseIndex + 1);
}
int versionIndex = versionCodeName.lastIndexOf("_V");
if (versionIndex >= 0) {
return versionCodeName.substring(0, 1) + "v" + versionCodeName.substring(versionIndex + 2);
}
return versionCodeName.substring(0, 1);
}

private static String robolectricVersion() {
try {
// RuntimeEnvironment is re-loaded by the sandbox classloader with no CodeSource, but the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package datadog.trace.instrumentation.robolectric;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.tabletest.junit.TableTest;

class RobolectricTestAnnotatorTest {

@TableTest({
"scenario | versionCodeName | codename",
"major release | JELLY_BEAN | J ",
"Jelly Bean MR1 | JELLY_BEAN_MR1 | JMR1 ",
"Jelly Bean MR2 | JELLY_BEAN_MR2 | JMR2 ",
"Lollipop MR1 | LOLLIPOP_MR1 | LMR1 ",
"Nougat MR1 | N_MR1 | NMR1 ",
"Oreo MR1 | O_MR1 | OMR1 ",
"Snow Cone v2 | S_V2 | Sv2 ",
"single word | TIRAMISU | T ",
"multi-word U | UPSIDE_DOWN_CAKE | U ",
"multi-word V | VANILLA_ICE_CREAM | V "
})
void derivesCodename(String versionCodeName, String codename) {
assertEquals(codename, RobolectricTestAnnotator.androidCodename(versionCodeName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ void testNew(
void testRobolectric(String gradleVersion, String projectName, int expectedTraces)
throws IOException {
Assumptions.assumeTrue(
JavaVirtualMachine.isJavaVersionBetween(17, 22), "Robolectric 4.16 supports JDK 17-21");
JavaVirtualMachine.isJavaVersionBetween(17, 22), "Robolectric 4.17 supports JDK 17-21");
Assumptions.assumeFalse(
OperatingSystem.architecture().isArm64(),
"Robolectric does not support arm64 (missing native runtime binaries, follow https://github.com/robolectric/robolectric/issues/9166)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ configurations.configureEach {

dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.16.1'
testImplementation 'org.robolectric:robolectric:4.17'
// Pre-built Android SDK jar for the level the fixtures configure.
testImplementation 'org.robolectric:android-all:14-robolectric-10818077'
// androidx.test:core pulls in androidx.test:monitor (InstrumentationRegistry); ext:junit provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@
"span.kind" : "test",
"test.android.codename" : "U",
"test.android.release" : "14",
"test.android.robolectric.version" : "4.16.1",
"test.android.robolectric.version" : "4.17",
"test.final_status" : "pass",
"test.framework" : "junit4",
"test.framework_version" : "4.13.2",
Expand Down Expand Up @@ -507,7 +507,7 @@
"span.kind" : "test",
"test.android.codename" : "U",
"test.android.release" : "14",
"test.android.robolectric.version" : "4.16.1",
"test.android.robolectric.version" : "4.17",
"test.final_status" : "pass",
"test.framework" : "junit4",
"test.framework_version" : "4.13.2",
Expand Down Expand Up @@ -688,4 +688,4 @@
},
"type" : "span",
"version" : 1
} ]
} ]