Skip to content

Commit c405eec

Browse files
committed
archRulesTest compile and runtime classpaths should include all dependencies from archRules source set
fixes #26
1 parent 8d13af2 commit c405eec

File tree

3 files changed

+179
-1
lines changed

3 files changed

+179
-1
lines changed

nebula-archrules-gradle-plugin/src/main/kotlin/com/netflix/nebula/archrules/gradle/ArchrulesLibraryPlugin.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class ArchrulesLibraryPlugin : Plugin<Project> {
6262
useJUnitJupiter()
6363
dependencies {
6464
implementation(project())
65-
implementation(archRulesSourceSet.output)
65+
implementation(archRulesSourceSet.runtimeClasspath)
6666
implementation("com.netflix.nebula:nebula-archrules-core:$version")
6767
}
6868
javaExt.sourceSets.named("archRulesTest").configure {

nebula-archrules-gradle-plugin/src/test/kotlin/com/netflix/nebula/archrules/gradle/ArchrulesLibraryPluginTest.kt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,67 @@ class ArchrulesLibraryPluginTest {
198198
.hasNoMutableStateWarnings()
199199
.hasNoDeprecationWarnings()
200200
}
201+
202+
@Test
203+
fun `plugin sets up tests for rules with dependencies`() {
204+
val runner = testProject(projectDir) {
205+
properties {
206+
gradleCache(true)
207+
}
208+
settings {
209+
name("library-with-rules")
210+
}
211+
subProject("rules") {
212+
group("com.example")
213+
plugins {
214+
id("java-library")
215+
id("com.netflix.nebula.archrules.library")
216+
}
217+
repositories {
218+
maven("https://netflixoss.jfrog.io/artifactory/gradle-plugins")
219+
mavenCentral()
220+
}
221+
dependencies(
222+
"""archRulesImplementation(project(":helper"))""",
223+
"""archRulesTestImplementation("org.jspecify:jspecify:1.0.0")"""
224+
)
225+
src {
226+
main {
227+
exampleLibraryClass()
228+
}
229+
sourceSet("archRules") {
230+
exampleNullabilityArchRule() // rules that uses a helper from a dependency
231+
}
232+
sourceSet("archRulesTest") {
233+
exampleTestForNullabilityArchRule()
234+
}
235+
}
236+
}
237+
subProject("helper") {
238+
group("com.example")
239+
plugins {
240+
id("java-library")
241+
}
242+
repositories {
243+
maven("https://netflixoss.jfrog.io/artifactory/gradle-plugins")
244+
mavenCentral()
245+
}
246+
dependencies("""implementation("com.tngtech.archunit:archunit:1.4.1")""")
247+
src {
248+
main {
249+
exampleHelperClass()
250+
}
251+
}
252+
}
253+
}
254+
255+
val result = runner.run("check", "--stacktrace")
256+
257+
assertThat(result.task(":rules:archRulesTest"))
258+
.`as`("archRules test task runs")
259+
.hasOutcome(TaskOutcome.SUCCESS, TaskOutcome.FROM_CACHE)
260+
assertThat(result)
261+
.hasNoMutableStateWarnings()
262+
.hasNoDeprecationWarnings()
263+
}
201264
}

nebula-archrules-gradle-plugin/src/test/kotlin/com/netflix/nebula/archrules/gradle/TestKitDslExtensions.kt

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,31 @@ public class LibraryClass {
3737
)
3838
}
3939

40+
fun SourceSetBuilder.exampleHelperClass() {
41+
java(
42+
"com/example/library/HaveNoTests.java",
43+
//language=java
44+
"""
45+
package com.example.library;
46+
47+
import com.tngtech.archunit.base.DescribedPredicate;
48+
import com.tngtech.archunit.core.domain.JavaClass;
49+
50+
public class HaveNoTests extends DescribedPredicate<JavaClass> {
51+
public HaveNoTests() {
52+
super("have no tests");
53+
}
54+
55+
@Override
56+
public boolean test(JavaClass javaClass) {
57+
return javaClass.getMembers().stream()
58+
.noneMatch(it -> it.isAnnotatedWith("org.junit.jupiter.api.Test"));
59+
}
60+
}
61+
"""
62+
)
63+
}
64+
4065
fun SourceSetBuilder.exampleDeprecatedArchRule() {
4166
java(
4267
"com/example/library/LibraryArchRules.java",
@@ -72,6 +97,43 @@ public class LibraryArchRules implements ArchRulesService {
7297
)
7398
}
7499

100+
fun SourceSetBuilder.exampleNullabilityArchRule() {
101+
java(
102+
"com/example/library/NullabilityArchRules.java",
103+
//language=java
104+
"""
105+
package com.example.library;
106+
107+
import com.netflix.nebula.archrules.core.ArchRulesService;
108+
import com.tngtech.archunit.core.domain.JavaModifier;
109+
import com.tngtech.archunit.core.domain.properties.HasModifiers;
110+
import com.tngtech.archunit.lang.ArchRule;
111+
import com.tngtech.archunit.lang.Priority;
112+
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
113+
import java.util.Map;
114+
import static com.tngtech.archunit.lang.conditions.ArchConditions.fullyQualifiedName;
115+
116+
public class NullabilityArchRules implements ArchRulesService {
117+
public static final ArchRule PUBLIC_CLASSES_SHOULD_BE_NULL_MARKED = ArchRuleDefinition.priority(Priority.MEDIUM)
118+
.classes().that()
119+
.areTopLevelClasses()
120+
.and().arePublic()
121+
.and().containAnyMembersThat(HasModifiers.Predicates.modifier(JavaModifier.PUBLIC))
122+
.and(new HaveNoTests())
123+
.and().areNotAnnotatedWith("kotlin.Metadata")
124+
.should().beAnnotatedWith("org.jspecify.annotations.NullMarked")
125+
.allowEmptyShould(true)
126+
.because("public classes should be null marked");
127+
128+
@Override
129+
public Map<String, ArchRule> getRules() {
130+
return Map.of("public classes should be @NullMarked", PUBLIC_CLASSES_SHOULD_BE_NULL_MARKED);
131+
}
132+
}
133+
"""
134+
)
135+
}
136+
75137
fun SourceSetBuilder.exampleDeprecatedUsage(className: String = "FailingCode") {
76138
java(
77139
"com/example/consumer/$className.java",
@@ -128,6 +190,59 @@ public class LibraryArchRulesTest {
128190
Assertions.assertTrue(result.hasViolation());
129191
}
130192
}
193+
"""
194+
)
195+
}
196+
197+
fun SourceSetBuilder.exampleTestForNullabilityArchRule() {
198+
java("com/example/library/FailingCode.java",
199+
//language=java
200+
"""
201+
package com.example.library;
202+
public class FailingCode {
203+
public void aMethod() {
204+
}
205+
}
206+
""")
207+
java("com/example/library/PassingCode.java",
208+
//language=java
209+
"""
210+
package com.example.library;
211+
import org.jspecify.annotations.NullMarked;
212+
@NullMarked
213+
public class PassingCode {
214+
public void aMethod() {
215+
}
216+
}
217+
""")
218+
java(
219+
"com/example/library/NullabilityArchRulesTest.java",
220+
//language=java
221+
"""
222+
package com.example.library;
223+
224+
import com.netflix.nebula.archrules.core.ArchRulesService;
225+
import com.netflix.nebula.archrules.core.Runner;
226+
import com.tngtech.archunit.lang.EvaluationResult;
227+
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
228+
229+
import org.junit.jupiter.api.Test;
230+
import org.junit.jupiter.api.Assertions;
231+
232+
public class NullabilityArchRulesTest {
233+
234+
@Test
235+
public void test_pass() {
236+
EvaluationResult result = Runner.check(NullabilityArchRules.PUBLIC_CLASSES_SHOULD_BE_NULL_MARKED, PassingCode.class);
237+
Assertions.assertFalse(result.hasViolation());
238+
}
239+
240+
@Test
241+
public void test_fail() {
242+
EvaluationResult result = Runner.check(NullabilityArchRules.PUBLIC_CLASSES_SHOULD_BE_NULL_MARKED, FailingCode.class);
243+
Assertions.assertTrue(result.hasViolation());
244+
}
245+
}
131246
"""
132247
)
133248
}

0 commit comments

Comments
 (0)