Apache Flink architectural tests for production code validation using ArchUnit framework
npx @tessl/cli install tessl/maven-org-apache-flink--flink-architecture-tests-production@2.1.0Apache Flink architectural tests for production code validation using the ArchUnit framework. This library provides a comprehensive suite of architectural rules and tests that validate code structure, API annotations, Table API conventions, and connector implementations across Flink's modules, ensuring consistent architectural patterns and enforcing coding standards for large-scale distributed stream processing systems.
pom.xml dependencies:
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-architecture-tests-production</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>import org.apache.flink.architecture.ProductionCodeArchitectureBase;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchTests;For specific rule classes:
import org.apache.flink.architecture.rules.ApiAnnotationRules;
import org.apache.flink.architecture.rules.TableApiRules;
import org.apache.flink.architecture.rules.ConnectorRules;import org.apache.flink.architecture.ProductionCodeArchitectureBase;
import org.apache.flink.architecture.common.ImportOptions;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchTests;
@AnalyzeClasses(
packages = "org.apache.flink",
importOptions = {
ImportOption.DoNotIncludeTests.class,
ImportOptions.ExcludeScalaImportOption.class,
ImportOptions.ExcludeShadedImportOption.class
}
)
public class MyArchitectureTest {
@ArchTest
public static final ArchTests PRODUCTION_RULES =
ArchTests.in(ProductionCodeArchitectureBase.class);
}The library is organized around several key components:
ProductionCodeArchitectureBase aggregates all production code rulesCentral setup class that aggregates all architectural tests for production code. This is the primary entry point for comprehensive architectural validation.
/**
* Central setup of architectural tests for the production code.
* Architectural tests should include this class via ArchTests.in(Class) to cover the common part.
*/
public class ProductionCodeArchitectureBase {
/** Tests for API annotation rules */
@ArchTest
public static final ArchTests API_ANNOTATIONS;
/** Tests for Table API rules */
@ArchTest
public static final ArchTests TABLE_API;
/** Tests for connector rules */
@ArchTest
public static final ArchTests CONNECTORS;
}Usage Example:
@ArchTest
public static final ArchTests COMMON_TESTS =
ArchTests.in(ProductionCodeArchitectureBase.class);Validates proper usage of Flink's API visibility annotations (@Public, @PublicEvolving, @Internal, etc.) to ensure consistent API design and prevent accidental exposure of internal APIs.
/**
* Rules for API visibility annotations.
*/
public class ApiAnnotationRules {
/** Ensures API classes have at least one visibility annotation */
@ArchTest
public static final ArchRule ANNOTATED_APIS;
/** Validates @Public methods use only public types */
@ArchTest
public static final ArchRule PUBLIC_API_METHODS_USE_ONLY_PUBLIC_API_TYPES;
/** Validates @PublicEvolving methods use appropriate types */
@ArchTest
public static final ArchRule PUBLIC_EVOLVING_API_METHODS_USE_ONLY_PUBLIC_EVOLVING_API_TYPES;
/** Prevents calls to @VisibleForTesting methods from production code */
@ArchTest
public static final ArchRule NO_CALLS_TO_VISIBLE_FOR_TESTING_METHODS;
}Usage Example:
@ArchTest
public static final ArchTests API_RULES =
ArchTests.in(ApiAnnotationRules.class);Enforces architectural patterns specific to Flink's Table API modules, including configuration option placement, factory implementations, and connector option packaging.
/**
* Rules for Table API.
*/
public class TableApiRules {
/** Fully qualified name for ConfigOption type */
public static final String CONFIG_OPTIONS_FQ_NAME =
"org.apache.flink.configuration.ConfigOption";
/** Ensures config options are placed in classes ending with "Options" */
@ArchTest
public static final ArchRule CONFIG_OPTIONS_IN_OPTIONS_CLASSES;
/** Prevents config options in table factory classes */
@ArchTest
public static final ArchRule TABLE_FACTORIES_CONTAIN_NO_CONFIG_OPTIONS;
/** Validates connector options package structure and annotations */
@ArchTest
public static final ArchRule CONNECTOR_OPTIONS_PACKAGE;
/** Ensures Table API classes have visibility annotations */
@ArchTest
public static final ArchRule ALL_CLASSES_IN_TABLE_API_SHOULD_HAVE_VISIBILITY_ANNOTATIONS;
}Usage Example:
@ArchTest
public static final ArchTests TABLE_RULES =
ArchTests.in(TableApiRules.class);Validates that Flink connector implementations follow proper architectural patterns and depend only on public APIs when interacting with core Flink modules.
/**
* Rules for Flink connectors.
*/
public class ConnectorRules {
/**
* Ensures connector classes depend only on public APIs outside connector packages
* Note: This rule is known to fail on Java 11 and Java 17 environments
*/
@ArchTest
@ArchTag(value = "org.apache.flink.testutils.junit.FailsOnJava11")
@ArchTag(value = "org.apache.flink.testutils.junit.FailsOnJava17")
public static final ArchRule CONNECTOR_CLASSES_ONLY_DEPEND_ON_PUBLIC_API;
}Usage Example:
@ArchTest
public static final ArchTests CONNECTOR_RULES =
ArchTests.in(ConnectorRules.class);Complete test class demonstrating proper setup and execution of all architectural tests with appropriate configuration.
/**
* Architecture tests.
*/
@AnalyzeClasses(
packages = "org.apache.flink",
importOptions = {
ImportOption.DoNotIncludeTests.class,
ImportOptions.ExcludeScalaImportOption.class,
ImportOptions.ExcludeShadedImportOption.class
}
)
public class ArchitectureTest {
/** Reference to all common production code tests */
@ArchTest
public static final ArchTests COMMON_TESTS;
}Architectural rule violations are reported through ArchUnit's standard violation reporting mechanism. Common violation types include:
Example Violation Report:
Architecture Violation [Priority: MEDIUM] - Rule 'Classes in API packages should have at least one API visibility annotation.' was violated (2 times):
Class <org.apache.flink.api.common.SomeClass> does not fulfill: are directly annotated with at least one of [@Internal, @Experimental, @PublicEvolving, @Public, @Deprecated]
Class <org.apache.flink.api.java.AnotherClass> does not fulfill: are directly annotated with at least one of [@Internal, @Experimental, @PublicEvolving, @Public, @Deprecated]Key Constants Used in Rules:
The architectural rules reference several important package patterns and constants that may appear in violation messages:
"org.apache.flink.connector..", "org.apache.flink.streaming.connectors.." - Package patterns used to identify connector modules"org.apache.flink.util.." - Utility package patterns allowed for connector dependencies".*/flink-table-(api-(bridge-base|java(|-bridge))|common)/.*" - Regex pattern for identifying Table API modules"org.apache.flink.configuration.ConfigOption" - Fully qualified name used in Table API rules"..shaded.." - Pattern for identifying shaded/relocated packagesThe library includes these key dependencies:
-Xmx settings)Known Issues:
CONNECTOR_CLASSES_ONLY_DEPEND_ON_PUBLIC_API rule in ConnectorRules is known to fail on Java 11 and Java 17 environments. This is marked with @ArchTag annotations and can be excluded if running on these Java versions.forkCount=1 to consolidate memory usage.ExcludeScalaImportOption as ArchUnit has limited Scala support.