Airblader commented on a change in pull request #18333:
URL: https://github.com/apache/flink/pull/18333#discussion_r783821321



##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/ArchitectureTest.java
##########
@@ -78,4 +79,36 @@ public boolean includes(Location location) {
             return !location.matches(SHADED);
         }
     }
+
+    /**
+     * Exclude locations that contains test classes.
+     *
+     * <p>Note: classes e.g. within jars under flink-test-utils-parent pom 
module are located as
+     * production code and should be excluded as test classes. Please see 
{@link
+     * ImportOption.Predefined#DO_NOT_INCLUDE_TESTS}
+     */
+    static class ExcludeTestJarsImportOption implements ImportOption {
+        private static final Pattern TEST = 
Pattern.compile(".*-test.*\\.jar.*");
+
+        @Override
+        public boolean includes(Location location) {
+            return !location.matches(TEST);
+        }
+    }
+
+    /**
+     * Include test relevant classes.
+     *
+     * <p>Note: since the test should be work both when maven and Intellij. 
The pattern will be
+     * improved to be more precise continuously.
+     */
+    static class OnlyTestJarsImportOption implements ImportOption {

Review comment:
       Can we just use the inverse of the import option above?
   
   This pattern is a bit "dangerous", because it would easily find anything 
that contains "test" anywhere in the entire location.

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/Predicates.java
##########
@@ -50,5 +83,78 @@
                                 && field.getRawType().isEquivalentTo(clazz));
     }
 
+    /**
+     * Tests that the given field is {@code public final} and not {@code 
static} and of the given
+     * type {@code clazz} .
+     */
+    public static DescribedPredicate<JavaField> arePublicFinalOfTyp(Class<?> 
clazz) {
+        return 
is(ofType(clazz)).and(isPublic()).and(isFinal()).and(isNotStatic());
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type {@code clazz}
+     * .
+     */
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTyp(Class<?> clazz) {

Review comment:
       Typ → Type

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/Predicates.java
##########
@@ -50,5 +83,78 @@
                                 && field.getRawType().isEquivalentTo(clazz));
     }
 
+    /**
+     * Tests that the given field is {@code public final} and not {@code 
static} and of the given
+     * type {@code clazz} .
+     */
+    public static DescribedPredicate<JavaField> arePublicFinalOfTyp(Class<?> 
clazz) {
+        return 
is(ofType(clazz)).and(isPublic()).and(isFinal()).and(isNotStatic());
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type {@code clazz}
+     * .
+     */
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTyp(Class<?> clazz) {
+        return arePublicStaticOfType(clazz).and(isFinal());
+    }
+
+    /**
+     * Tests that the given field is {@code public final} and of the given 
type {@code clazz} with
+     * exactly the given {@code annotationType}.
+     */
+    public static DescribedPredicate<JavaField> 
arePublicFinalOfTypeWithAnnotation(
+            Class<?> clazz, Class<? extends Annotation> annotationType) {
+        return arePublicFinalOfTyp(clazz).and(annotatedWith(annotationType));
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type {@code clazz}
+     * with exactly the given {@code annotationType}.
+     */
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTypeWithAnnotation(
+            Class<?> clazz, Class<? extends Annotation> annotationType) {
+        return 
arePublicStaticFinalOfTyp(clazz).and(annotatedWith(annotationType));
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type. It must have
+     * any of the given {@code annotationTypes}
+     */
+    @SafeVarargs
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTypeWithOneOfAnnotations(
+            Class<?> clazz, Class<? extends Annotation>... annotationTypes) {
+        return 
arePublicStaticFinalOfTyp(clazz).and(annotatedWithOneOf(annotationTypes));
+    }
+
     private Predicates() {}
+
+    /**
+     * A predicate to determine if a {@link JavaClass} contains one or more 
{@link JavaField }

Review comment:
       ```suggestion
        * A predicate to determine if a {@link JavaClass} contains one or more 
{@link JavaField}
   ```

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/JavaFieldPredicates.java
##########
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *     http://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 org.apache.flink.architecture.common;
+
+import com.tngtech.archunit.base.DescribedPredicate;
+import com.tngtech.archunit.core.domain.JavaAnnotation;
+import com.tngtech.archunit.core.domain.JavaField;
+import com.tngtech.archunit.core.domain.JavaModifier;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
+/** Fine-grained predicates focus on the JavaField. */
+public class JavaFieldPredicates {
+
+    /**
+     * Match the public modifier of the {@link JavaField}.
+     *
+     * @return A {@link DescribedPredicate} returning true, if and only if the 
tested {@link
+     *     JavaField} has the public modifier.
+     */
+    public static DescribedPredicate<JavaField> isPublic() {
+        return DescribedPredicate.describe(
+                "public", field -> 
field.getModifiers().contains(JavaModifier.PUBLIC));
+    }
+
+    /**
+     * Match the static modifier of the {@link JavaField}.
+     *
+     * @return A {@link DescribedPredicate} returning true, if and only if the 
tested {@link
+     *     JavaField} has the static modifier.
+     */
+    public static DescribedPredicate<JavaField> isStatic() {
+        return DescribedPredicate.describe(
+                "static", field -> 
field.getModifiers().contains(JavaModifier.STATIC));
+    }
+
+    /**
+     * Match none static modifier of the {@link JavaField}.
+     *
+     * @return A {@link DescribedPredicate} returning true, if and only if the 
tested {@link
+     *     JavaField} has no static modifier.
+     */
+    public static DescribedPredicate<JavaField> isNotStatic() {
+        return DescribedPredicate.describe(
+                "not static", field -> 
!field.getModifiers().contains(JavaModifier.STATIC));
+    }
+
+    /**
+     * Match the final modifier of the {@link JavaField}.
+     *
+     * @return A {@link DescribedPredicate} returning true, if and only if the 
tested {@link
+     *     JavaField} has the final modifier.
+     */
+    public static DescribedPredicate<JavaField> isFinal() {
+        return DescribedPredicate.describe(
+                "final", field -> 
field.getModifiers().contains(JavaModifier.FINAL));
+    }

Review comment:
       These methods seem like they add more overhead than they save code. 
Since they're only called from other constructed methods (like 
`arePublicStaticFinalOfType`) I don't think we really need them or gain 
anything, but I don't feel too strongly either way.

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/ArchitectureTest.java
##########
@@ -78,4 +79,36 @@ public boolean includes(Location location) {
             return !location.matches(SHADED);
         }
     }
+
+    /**
+     * Exclude locations that contains test classes.
+     *
+     * <p>Note: classes e.g. within jars under flink-test-utils-parent pom 
module are located as
+     * production code and should be excluded as test classes. Please see 
{@link
+     * ImportOption.Predefined#DO_NOT_INCLUDE_TESTS}
+     */
+    static class ExcludeTestJarsImportOption implements ImportOption {

Review comment:
       Maybe this is a good time to move all of our import options into a 
separate `ImportOptions` util class, especially since we have a second class 
now that references them. What do you think?

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/Predicates.java
##########
@@ -50,5 +83,78 @@
                                 && field.getRawType().isEquivalentTo(clazz));
     }
 
+    /**
+     * Tests that the given field is {@code public final} and not {@code 
static} and of the given
+     * type {@code clazz} .
+     */
+    public static DescribedPredicate<JavaField> arePublicFinalOfTyp(Class<?> 
clazz) {

Review comment:
       Typ → Type

##########
File path: flink-architecture-tests/src/test/resources/archunit.properties
##########
@@ -19,6 +19,11 @@
 # By default we allow removing existing violations, but fail when new 
violations are added.
 freeze.store.default.allowStoreUpdate=true
 
+# must be set to true to allow the creation of a new violation store
+# default is false
+# set to true when new ArchRule has been developed.
+#freeze.store.default.allowStoreCreation=true.

Review comment:
       nit:
   
   ```suggestion
   # Enable this if a new (frozen) rule has been added in order to create the 
initial store and record the existing violations.
   #freeze.store.default.allowStoreCreation=true.
   ```

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/Predicates.java
##########
@@ -40,7 +51,29 @@
                 .forSubtype();
     }
 
-    /** Tests that the given field is {@code public static} and of the given 
type. */
+    /**
+     * @return A {@link DescribedPredicate} returning true, if and only if the 
predicate {@link
+     *     JavaField} could be found in the {@link JavaClass}.
+     */
+    public static DescribedPredicate<JavaClass> 
containAnyFieldsInClassHierarchyThat(
+            DescribedPredicate<? super JavaField> predicate) {
+        return new ContainAnyFieldsThatPredicate<>(
+                "fields",
+                new ChainableFunction<JavaClass, Set<JavaField>>() {
+                    @Override
+                    public Set<JavaField> apply(JavaClass input) {
+                        // need to get all fields with the inheritance 
hierarchy
+                        return input.getAllFields();
+                    }
+                },
+                predicate);
+    }
+
+    /**
+     * Tests that the given field is {@code public static} and of the given 
type {@code clazz} .
+     *
+     * <p>Attention: changing the description will add a rule into the 
stored.rules.

Review comment:
       What's the purpose of this comment? This is true for all predicate 
functions.

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/Predicates.java
##########
@@ -40,7 +51,29 @@
                 .forSubtype();
     }
 
-    /** Tests that the given field is {@code public static} and of the given 
type. */
+    /**
+     * @return A {@link DescribedPredicate} returning true, if and only if the 
predicate {@link
+     *     JavaField} could be found in the {@link JavaClass}.
+     */
+    public static DescribedPredicate<JavaClass> 
containAnyFieldsInClassHierarchyThat(

Review comment:
       ```suggestion
       public static DescribedPredicate<JavaClass> 
containsAnyFieldsInClassHierarchyThat(
   ```

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/Predicates.java
##########
@@ -50,5 +83,78 @@
                                 && field.getRawType().isEquivalentTo(clazz));
     }
 
+    /**
+     * Tests that the given field is {@code public final} and not {@code 
static} and of the given
+     * type {@code clazz} .
+     */
+    public static DescribedPredicate<JavaField> arePublicFinalOfTyp(Class<?> 
clazz) {
+        return 
is(ofType(clazz)).and(isPublic()).and(isFinal()).and(isNotStatic());
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type {@code clazz}
+     * .
+     */
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTyp(Class<?> clazz) {
+        return arePublicStaticOfType(clazz).and(isFinal());
+    }
+
+    /**
+     * Tests that the given field is {@code public final} and of the given 
type {@code clazz} with
+     * exactly the given {@code annotationType}.
+     */
+    public static DescribedPredicate<JavaField> 
arePublicFinalOfTypeWithAnnotation(
+            Class<?> clazz, Class<? extends Annotation> annotationType) {
+        return arePublicFinalOfTyp(clazz).and(annotatedWith(annotationType));
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type {@code clazz}
+     * with exactly the given {@code annotationType}.
+     */
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTypeWithAnnotation(
+            Class<?> clazz, Class<? extends Annotation> annotationType) {
+        return 
arePublicStaticFinalOfTyp(clazz).and(annotatedWith(annotationType));
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type. It must have
+     * any of the given {@code annotationTypes}
+     */
+    @SafeVarargs
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTypeWithOneOfAnnotations(
+            Class<?> clazz, Class<? extends Annotation>... annotationTypes) {
+        return 
arePublicStaticFinalOfTyp(clazz).and(annotatedWithOneOf(annotationTypes));
+    }
+
     private Predicates() {}
+
+    /**
+     * A predicate to determine if a {@link JavaClass} contains one or more 
{@link JavaField }
+     * matching the supplied predicate.
+     */
+    private static class ContainAnyFieldsThatPredicate<T extends JavaField>
+            extends DescribedPredicate<JavaClass> {
+        private final Function<JavaClass, Set<T>> getFields;
+        private final DescribedPredicate<? super T> predicate;
+
+        ContainAnyFieldsThatPredicate(
+                String fieldDescription,
+                Function<JavaClass, Set<T>> getFields,
+                DescribedPredicate<? super T> predicate) {
+            super("contain any " + fieldDescription + " that " + 
predicate.getDescription());

Review comment:
       ```suggestion
               super("contains any " + fieldDescription + " that " + 
predicate.getDescription());
   ```
   
   Same for the class name itself

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/ArchitectureTest.java
##########
@@ -78,4 +79,36 @@ public boolean includes(Location location) {
             return !location.matches(SHADED);
         }
     }
+
+    /**
+     * Exclude locations that contains test classes.
+     *
+     * <p>Note: classes e.g. within jars under flink-test-utils-parent pom 
module are located as
+     * production code and should be excluded as test classes. Please see 
{@link
+     * ImportOption.Predefined#DO_NOT_INCLUDE_TESTS}
+     */
+    static class ExcludeTestJarsImportOption implements ImportOption {
+        private static final Pattern TEST = 
Pattern.compile(".*-test.*\\.jar.*");

Review comment:
       That extra `.*` after `-test` allows for arbitrarily much text to be 
there before the `.jar`. I think this could easily allow too much. Can we 
restrict that? What is that `.*` supposed to match currently?

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/common/Predicates.java
##########
@@ -50,5 +83,78 @@
                                 && field.getRawType().isEquivalentTo(clazz));
     }
 
+    /**
+     * Tests that the given field is {@code public final} and not {@code 
static} and of the given
+     * type {@code clazz} .
+     */
+    public static DescribedPredicate<JavaField> arePublicFinalOfTyp(Class<?> 
clazz) {
+        return 
is(ofType(clazz)).and(isPublic()).and(isFinal()).and(isNotStatic());
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type {@code clazz}
+     * .
+     */
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTyp(Class<?> clazz) {
+        return arePublicStaticOfType(clazz).and(isFinal());
+    }
+
+    /**
+     * Tests that the given field is {@code public final} and of the given 
type {@code clazz} with
+     * exactly the given {@code annotationType}.
+     */
+    public static DescribedPredicate<JavaField> 
arePublicFinalOfTypeWithAnnotation(
+            Class<?> clazz, Class<? extends Annotation> annotationType) {
+        return arePublicFinalOfTyp(clazz).and(annotatedWith(annotationType));
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type {@code clazz}
+     * with exactly the given {@code annotationType}.
+     */
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTypeWithAnnotation(
+            Class<?> clazz, Class<? extends Annotation> annotationType) {
+        return 
arePublicStaticFinalOfTyp(clazz).and(annotatedWith(annotationType));
+    }
+
+    /**
+     * Tests that the given field is {@code public static final} and of the 
given type. It must have
+     * any of the given {@code annotationTypes}
+     */
+    @SafeVarargs
+    public static DescribedPredicate<JavaField> 
arePublicStaticFinalOfTypeWithOneOfAnnotations(

Review comment:
       This method seems to be unused. And it's the only caller of 
`annotatedWithOneOf` which is then also unused.

##########
File path: 
flink-architecture-tests/src/test/java/org/apache/flink/architecture/rules/ITCaseRules.java
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ *     http://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 org.apache.flink.architecture.rules;
+
+import org.apache.flink.core.testutils.AllCallbackWrapper;
+import org.apache.flink.runtime.testutils.MiniClusterExtension;
+import org.apache.flink.test.util.AbstractTestBase;
+import org.apache.flink.test.util.MiniClusterWithClientResource;
+
+import com.tngtech.archunit.junit.ArchTest;
+import com.tngtech.archunit.lang.ArchRule;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static com.tngtech.archunit.core.domain.JavaModifier.ABSTRACT;
+import static com.tngtech.archunit.library.freeze.FreezingArchRule.freeze;
+import static org.apache.flink.architecture.common.Conditions.fulfill;
+import static 
org.apache.flink.architecture.common.GivenJavaClasses.javaClassesThat;
+import static 
org.apache.flink.architecture.common.Predicates.arePublicFinalOfTypeWithAnnotation;
+import static 
org.apache.flink.architecture.common.Predicates.arePublicStaticFinalOfTyp;
+import static 
org.apache.flink.architecture.common.Predicates.arePublicStaticFinalOfTypeWithAnnotation;
+import static 
org.apache.flink.architecture.common.Predicates.containAnyFieldsInClassHierarchyThat;
+
+/** Rules for Integration Tests. */
+public class ITCaseRules {
+
+    @ArchTest
+    public static final ArchRule INTEGRATION_TEST_ENDING_WITH_ITCASE =
+            freeze(
+                    javaClassesThat()
+                            .areAssignableTo(AbstractTestBase.class)
+                            .and()
+                            .doNotHaveModifier(ABSTRACT)
+                            .should()
+                            .haveSimpleNameEndingWith("ITCase"));
+
+    @ArchTest
+    public static final ArchRule ITCASE_USE_MINICLUSTER =
+            freeze(
+                    javaClassesThat()
+                            .haveSimpleNameEndingWith("ITCase")
+                            .and()
+                            .areTopLevelClasses()
+                            .and()
+                            .doNotHaveModifier(ABSTRACT)
+                            .should(
+                                    fulfill(
+                                            // JUnit 5 violation check
+                                            
containAnyFieldsInClassHierarchyThat(
+                                                            
arePublicStaticFinalOfTyp(
+                                                                    
MiniClusterExtension.class))
+                                                    .and(
+                                                            
containAnyFieldsInClassHierarchyThat(
+                                                                    
arePublicStaticFinalOfTypeWithAnnotation(
+                                                                            
AllCallbackWrapper
+                                                                               
     .class,
+                                                                            
RegisterExtension
+                                                                               
     .class)))
+                                                    // JUnit 4 violation 
check, which should be

Review comment:
       Is the JUnit migration being tracked on JIRA? It'd be better to create a 
task there to do this rather than waiting for someone to find this in the 
future and removing it. :-)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to