Skip to content

Commit ccec9cb

Browse files
committed
Add archunit tests for naming conventions
Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
1 parent 1225510 commit ccec9cb

File tree

1 file changed

+98
-3
lines changed

1 file changed

+98
-3
lines changed

src/test/java/org/kohsuke/github/ArchTests.java

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,68 @@
11
package org.kohsuke.github;
22

33
import com.tngtech.archunit.base.DescribedPredicate;
4+
import com.tngtech.archunit.base.HasDescription;
45
import com.tngtech.archunit.core.domain.*;
56
import com.tngtech.archunit.core.domain.properties.HasName;
67
import com.tngtech.archunit.core.domain.properties.HasOwner;
8+
import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation;
79
import com.tngtech.archunit.core.importer.ClassFileImporter;
810
import com.tngtech.archunit.core.importer.ImportOption;
911
import com.tngtech.archunit.lang.ArchCondition;
1012
import com.tngtech.archunit.lang.ArchRule;
13+
import com.tngtech.archunit.lang.conditions.ArchConditions;
1114
import org.apache.commons.io.IOUtils;
1215
import org.apache.commons.lang3.StringUtils;
1316
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
1417
import org.apache.commons.lang3.builder.ToStringBuilder;
1518
import org.apache.commons.lang3.builder.ToStringStyle;
1619
import org.junit.BeforeClass;
1720
import org.junit.Test;
21+
import org.kohsuke.github.GHDiscussion.Creator;
22+
import org.kohsuke.github.GHPullRequestCommitDetail.Commit;
23+
import org.kohsuke.github.GHPullRequestCommitDetail.CommitPointer;
1824

1925
import java.io.Closeable;
2026
import java.io.InputStream;
2127
import java.io.OutputStream;
2228
import java.io.Reader;
2329
import java.lang.reflect.Field;
30+
import java.net.URL;
2431
import java.nio.charset.Charset;
32+
import java.time.Instant;
2533
import java.util.Arrays;
2634
import java.util.stream.Collectors;
2735

2836
import static com.google.common.base.Preconditions.checkNotNull;
37+
import static com.tngtech.archunit.base.DescribedPredicate.not;
38+
import static com.tngtech.archunit.base.DescribedPredicate.or;
2939
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
3040
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAPackage;
3141
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.type;
42+
import static com.tngtech.archunit.core.domain.JavaMember.Predicates.declaredIn;
43+
import static com.tngtech.archunit.core.domain.JavaModifier.FINAL;
44+
import static com.tngtech.archunit.core.domain.JavaModifier.STATIC;
45+
import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier;
3246
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
3347
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining;
48+
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching;
3449
import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner;
3550
import static com.tngtech.archunit.core.domain.properties.HasParameterTypes.Predicates.rawParameterTypes;
51+
import static com.tngtech.archunit.core.domain.properties.HasReturnType.Predicates.rawReturnType;
3652
import static com.tngtech.archunit.lang.conditions.ArchConditions.*;
3753
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
54+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
55+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noFields;
56+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noMethods;
3857
import static org.hamcrest.MatcherAssert.assertThat;
3958
import static org.hamcrest.Matchers.greaterThan;
4059

4160
// TODO: Auto-generated Javadoc
4261
/**
4362
* The Class ArchTests.
4463
*/
64+
@SuppressWarnings({ "LocalVariableNamingConvention", "TestMethodWithoutAssertion", "UnqualifiedStaticUsage",
65+
"unchecked", "MethodMayBeStatic", "FieldNamingConvention", "StaticCollection" })
4566
public class ArchTests {
4667

4768
private static final JavaClasses classFiles = new ClassFileImporter()
@@ -69,6 +90,43 @@ public static void beforeClass() {
6990
assertThat(classFiles.size(), greaterThan(0));
7091
}
7192

93+
@Test
94+
public void testRequireFollowingNamingConvention() {
95+
final String reason = "This project follows standard java naming conventions and does not allow the use of underscores in names.";
96+
97+
final ArchRule fieldsNotFollowingConvention = noFields().that()
98+
.arePublic()
99+
.and(not(enumConstants()))
100+
.and(not(modifier(STATIC).and(modifier(FINAL)).as("static final")))
101+
.should(haveNamesContainingUnless("_"))
102+
.because(reason);
103+
104+
@SuppressWarnings("AccessStaticViaInstance")
105+
final ArchRule methodsNotFollowingConvention = noMethods().that()
106+
.arePublic()
107+
.should(haveNamesContainingUnless("_",
108+
nameMatching("[A-Z0-9\\_]+"),
109+
// currently failing cases
110+
// TODO: 2025-03-28 Fix & remove these
111+
declaredIn(PagedIterable.class).and(name("_iterator")).and(rawReturnType(PagedIterator.class)),
112+
declaredIn(GHRepositoryBuilder.class).and(name("private_")).and(rawReturnType(Object.class)),
113+
declaredIn(GHDeployKey.class).and(name("getAdded_by")).and(rawReturnType(String.class)),
114+
declaredIn(GHDeployKey.class).and(name("isRead_only")).and(rawReturnType(boolean.class)),
115+
declaredIn(Creator.class).and(name("private_")).and(rawReturnType(Creator.class)),
116+
declaredIn(GHGistBuilder.class).and(name("public_")).and(rawReturnType(GHGistBuilder.class)),
117+
declaredIn(Commit.class).and(name("getComment_count")).and(rawReturnType(int.class)),
118+
declaredIn(CommitPointer.class).and(name("getHtml_url")).and(rawReturnType(URL.class)),
119+
declaredIn(GHRelease.class).and(name("getPublished_at")).and(rawReturnType(Instant.class))))
120+
.because(reason);
121+
122+
final ArchRule classesNotFollowingConvention = noClasses().should(haveNamesContainingUnless("_"))
123+
.because(reason);
124+
125+
fieldsNotFollowingConvention.check(classFiles);
126+
methodsNotFollowingConvention.check(classFiles);
127+
classesNotFollowingConvention.check(classFiles);
128+
}
129+
72130
/**
73131
* Test require use of assert that.
74132
*/
@@ -78,10 +136,10 @@ public void testRequireUseOfAssertThat() {
78136
final String reason = "This project uses `assertThat(...)` or `assertThrows(...)` instead of other `assert*()` methods.";
79137

80138
final DescribedPredicate<HasName> assertMethodOtherThanAssertThat = nameContaining("assert")
81-
.and(DescribedPredicate.not(name("assertThat")).and(DescribedPredicate.not(name("assertThrows"))));
139+
.and(not(name("assertThat")).and(not(name("assertThrows"))));
82140

83141
final ArchRule onlyAssertThatRule = classes()
84-
.should(not(callMethodWhere(target(assertMethodOtherThanAssertThat))))
142+
.should(ArchConditions.not(callMethodWhere(target(assertMethodOtherThanAssertThat))))
85143
.because(reason);
86144

87145
onlyAssertThatRule.check(testClassFiles);
@@ -135,6 +193,27 @@ public void testRequireUseOfOnlySpecificApacheCommons() {
135193
onlyApprovedApacheCommonsMethods.check(classFiles);
136194
}
137195

196+
/**
197+
* Have names containing unless.
198+
*
199+
* @param infix
200+
* the infix
201+
* @param unlessPredicates
202+
* the unless predicates
203+
* @return the arch condition
204+
*/
205+
public static <T extends HasDescription & HasSourceCodeLocation & HasName> ArchCondition<T> haveNamesContainingUnless(
206+
final String infix,
207+
final DescribedPredicate<? super T>... unlessPredicates) {
208+
DescribedPredicate<? super T> restrictedNameContaining = nameContaining(infix);
209+
210+
if (unlessPredicates.length > 0) {
211+
final DescribedPredicate<T> allowed = or(unlessPredicates);
212+
restrictedNameContaining = unless(nameContaining(infix), allowed);
213+
}
214+
return have(restrictedNameContaining);
215+
}
216+
138217
/**
139218
* Not call methods in package unless.
140219
*
@@ -156,7 +235,7 @@ public static ArchCondition<JavaClass> notCallMethodsInPackageUnless(final Strin
156235
}
157236
restrictedPackageCalls = unless(restrictedPackageCalls, allowed);
158237
}
159-
return not(callMethodWhere(restrictedPackageCalls));
238+
return ArchConditions.not(callMethodWhere(restrictedPackageCalls));
160239
}
161240

162241
/**
@@ -200,6 +279,10 @@ public static <T> DescribedPredicate<T> unless(DescribedPredicate<? super T> fir
200279
return new UnlessPredicate(first, second);
201280
}
202281

282+
private DescribedPredicate<? super JavaField> enumConstants() {
283+
return new EnumConstantFieldPredicate();
284+
}
285+
203286
private static class UnlessPredicate<T> extends DescribedPredicate<T> {
204287
private final DescribedPredicate<T> current;
205288
private final DescribedPredicate<? super T> other;
@@ -215,4 +298,16 @@ public boolean test(T input) {
215298
return current.test(input) && !other.test(input);
216299
}
217300
}
301+
302+
private static final class EnumConstantFieldPredicate extends DescribedPredicate<JavaField> {
303+
private EnumConstantFieldPredicate() {
304+
super("are not enum constants");
305+
}
306+
307+
@Override
308+
public boolean test(JavaField javaField) {
309+
JavaClass owner = javaField.getOwner();
310+
return owner.isEnum() && javaField.getRawType().isAssignableTo(owner.reflect());
311+
}
312+
}
218313
}

0 commit comments

Comments
 (0)