Skip to content

Commit

Permalink
Merge reactor#2776 into 3.4.11
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbasle committed Oct 4, 2021
2 parents 3dfebb5 + f117f59 commit cb926e5
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 26 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ ext {
archUnitVersion = '0.21.0'

// For reactor-tools
byteBuddyVersion = '1.10.9' //sync with plugin version above //TODO bump to 1.11.16 with breaking changes
byteBuddyVersion = '1.11.16' //dependency, but plugin usage is now in a mock build done via TestKit
cgLibVersion = '3.3.0'

// JMH
Expand Down
47 changes: 32 additions & 15 deletions reactor-tools/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
* limitations under the License.
*/

plugins {
id 'net.bytebuddy.byte-buddy-gradle-plugin' version "$byteBuddyVersion" apply false
}
import org.apache.tools.ant.filters.ReplaceTokens

apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'org.unbroken-dome.test-sets'
Expand Down Expand Up @@ -56,6 +54,11 @@ dependencies {
testImplementation "cglib:cglib:$cgLibVersion"

jarFileTestImplementation "org.assertj:assertj-core:$assertJVersion"

buildPluginTestImplementation gradleTestKit()
buildPluginTestImplementation platform("org.junit:junit-bom:${jUnitPlatformVersion}")
buildPluginTestImplementation "org.junit.jupiter:junit-jupiter-api"
buildPluginTestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
}

test {
Expand Down Expand Up @@ -160,18 +163,32 @@ javaAgentTest {
}
project.tasks.check.dependsOn(javaAgentTest)

// See https://github.com/raphw/byte-buddy/issues/833
compileBuildPluginTestJava.doLast(
new net.bytebuddy.build.gradle.TransformationAction(
project,
new net.bytebuddy.build.gradle.ByteBuddyExtension(project).tap {
transformation {
plugin = "reactor.tools.agent.ReactorDebugByteBuddyPlugin"
}
},
compileBuildPluginTestJava
)
)
project.tasks.buildPluginTest.mustRunAfter(shadowJar)
project.tasks.buildPluginTest.dependsOn(shadowJar)

task generateMockGradle(type: Copy) {
def coreJar = rootProject.findProject("reactor-core").buildDir.toString() + "/libs/reactor-core-" + version + ".jar"
def agentJar = buildDir.toString() + "/libs/reactor-tools-" + version + "-original.jar"
def mockGradleDir = buildDir.toString() + "/mock-gradle"

from "$projectDir/src/buildPluginTest/resources/mock-gradle"
into "$mockGradleDir"
filter(ReplaceTokens, tokens: [
CORE: coreJar,
AGENT: agentJar,
REACTIVE_STREAMS_VERSION: rootProject.ext.reactiveStreamsVersion,
JUNIT_BOM_VERSION: rootProject.ext.jUnitPlatformVersion,
BYTE_BUDDY_VERSION: rootProject.ext.byteBuddyVersion
])
}

buildPluginTest {
def mockGradleDir = "$buildDir/mock-gradle"
println "will run mock gradle build from $mockGradleDir"
systemProperty "mock-gradle-dir", mockGradleDir
}

project.tasks.buildPluginTest.dependsOn(generateMockGradle)
project.tasks.check.dependsOn(buildPluginTest)

tasks.withType(Test).all {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2021 VMware Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package reactor.tools.agent;

import java.io.File;

import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.BuildTask;
import org.gradle.testkit.runner.GradleRunner;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

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

/**
* @author Simon Baslé
*/
class ApplyingByteBuddyPluginGradleTest {

static File testProjectDir;

@BeforeEach
void setup() {
String testProjectPath = System.getProperty("mock-gradle-dir");
assertNotNull(testProjectPath, "Cannot find testProjectPath, set or verify -Dmock-gradle-dir");
testProjectDir = new File(testProjectPath);
assertTrue(testProjectDir.exists() && testProjectDir.isDirectory(), "testProjectDir not created correctly");
}

@Test
void applyingByteBuddyPluginDuringGradleBuild() {
BuildResult result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withDebug(true)
.withArguments("test", "--info", "--stacktrace")
.build();

//the test task in reactor-tools/src/buildPluginTest/resources/mock-gradle/src/test/java/demo/SomeClassTest.java
//checks that applying the reactor-tool ByteBuddy plugin in Gradle instruments prod code but not test code.

assertTrue(result.getOutput().contains("test"));
final BuildTask task = result.task(":test");
assertNotNull(task);
assertEquals(TaskOutcome.SUCCESS, task.getOutcome());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2021 VMware Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

buildscript {
repositories {
mavenCentral()
}
dependencies {
//the plugin feature only works with the -original jar !!
//otherwise implemented Plugin interface is the shaded one
classpath files("@AGENT@")
}
}

plugins {
id "net.bytebuddy.byte-buddy-gradle-plugin" version "@BYTE_BUDDY_VERSION@"
id 'java'
}

repositories {
mavenCentral()
}

ext {
//smoke test to fail the mock gradle if it is wrongly configured with the shaded jar rather than the original
if (!"@AGENT@".endsWith("-original.jar")) {
throw new GradleException("The build file must be configured with reactor-tools' -original.jar version !!")
}
}

dependencies {
implementation "org.reactivestreams:reactive-streams:@REACTIVE_STREAMS_VERSION@"
implementation files("@CORE@")

testImplementation platform("org.junit:junit-bom:@JUNIT_BOM_VERSION@")
testImplementation "org.junit.jupiter:junit-jupiter-api"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"

testImplementation "org.assertj:assertj-core:3.20.2"
}

test {
useJUnitPlatform()
}

byteBuddy {
transformation {
plugin = reactor.tools.agent.ReactorDebugByteBuddyPlugin.class
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2021 VMware Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

rootProject.name = 'bytebuddy-and-reactoragent'
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2021 VMware Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package demo;

import reactor.core.publisher.Flux;

public class SomeClass {

public Flux<Integer> obtainFlux() {
return Flux.just(1);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2021 VMware Inc. or its affiliates, All Rights Reserved.
* Copyright (c) 2021 VMware Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,30 +14,34 @@
* limitations under the License.
*/

package reactor.tools.agent;
package demo;

import org.junit.jupiter.api.Test;

import reactor.core.Scannable;
import reactor.core.publisher.Flux;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.STRING;

/**
* This test assumes that the transformation is applied at build time
* and does not manually install it.
*/
public class ReactorDebugBuildPluginTest {
public class SomeClassTest {

@Test
public void shouldAddAssemblyInfo() {
int baseline = getBaseline();
Flux<Integer> flux = Flux.just(1);
//the first level is instantiated from the production code, which is instrumented
Flux<Integer> flux = new SomeClass().obtainFlux();
//the second level is instantiated here in test code, which isn't instrumented
flux = flux.map(i -> i);

assertThat(Scannable.from(flux).stepName())
.startsWith("Flux.just ⇢ at reactor.tools.agent.ReactorDebugBuildPluginTest.shouldAddAssemblyInfo(ReactorDebugBuildPluginTest.java:" + (baseline + 1));
}
Scannable scannable = Scannable.from(flux);

private static int getBaseline() {
return new Exception().getStackTrace()[1].getLineNumber();
assertThat(scannable.steps())
.hasSize(2)
.endsWith("map")
.first(STRING).startsWith("Flux.just ⇢ at demo.SomeClass.obtainFlux(SomeClass.java:");
}
}

0 comments on commit cb926e5

Please sign in to comment.