-
Notifications
You must be signed in to change notification settings - Fork 19
feat: add integration tests for Java generator #222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
|
|
||
| "dagger.io/dagger" | ||
| "github.com/open-feature/cli/test/integration" | ||
| ) | ||
|
|
||
| // Test implements the integration test for the Java generator | ||
| type Test struct { | ||
| // ProjectDir is the absolute path to the root of the project | ||
| ProjectDir string | ||
| // TestDir is the absolute path to the test directory | ||
| TestDir string | ||
| } | ||
|
|
||
| // New creates a new Test | ||
| func New(projectDir, testDir string) *Test { | ||
| return &Test{ | ||
| ProjectDir: projectDir, | ||
| TestDir: testDir, | ||
| } | ||
| } | ||
|
|
||
| // Run executes the Java integration test using Dagger | ||
| func (t *Test) Run(ctx context.Context, client *dagger.Client) (*dagger.Container, error) { | ||
| // Source code container | ||
| source := client.Host().Directory(t.ProjectDir) | ||
| testFiles := client.Host().Directory(t.TestDir, dagger.HostDirectoryOpts{ | ||
| Include: []string{"pom.xml", "src/**/*.java"}, | ||
| }) | ||
|
|
||
| // Build the CLI | ||
| cli := client.Container(). | ||
| From("golang:1.24-alpine"). | ||
| WithExec([]string{"apk", "add", "--no-cache", "git"}). | ||
| WithDirectory("/src", source). | ||
| WithWorkdir("/src"). | ||
| WithExec([]string{"go", "mod", "tidy"}). | ||
| WithExec([]string{"go", "mod", "download"}). | ||
| WithExec([]string{"go", "build", "-o", "cli", "./cmd/openfeature"}) | ||
|
|
||
| // Generate Java client | ||
| generated := cli.WithExec([]string{ | ||
| "./cli", "generate", "java", | ||
| "--manifest=/src/sample/sample_manifest.json", | ||
| "--output=/tmp/generated", | ||
| "--package-name=dev.openfeature.generated", | ||
| }) | ||
|
|
||
| // Get generated files | ||
| generatedFiles := generated.Directory("/tmp/generated") | ||
|
|
||
| // Test Java compilation with the generated files | ||
| javaContainer := client.Container(). | ||
| From("maven:3.9-eclipse-temurin-21-alpine"). | ||
| WithWorkdir("/app"). | ||
| WithDirectory("/app", testFiles). | ||
| WithDirectory("/app/src/main/java/dev/openfeature/generated", generatedFiles). | ||
| WithExec([]string{"mvn", "clean", "compile", "-B", "-q"}). | ||
| WithExec([]string{"mvn", "exec:java", "-Dexec.mainClass=dev.openfeature.Main", "-q"}) | ||
|
|
||
| return javaContainer, nil | ||
| } | ||
|
|
||
| // Name returns the name of the integration test | ||
| func (t *Test) Name() string { | ||
| return "java" | ||
| } | ||
|
|
||
| func main() { | ||
| ctx := context.Background() | ||
|
|
||
| // Get project root | ||
| projectDir, err := os.Getwd() | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "Failed to get project dir: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| // Get test directory | ||
| testDir, err := filepath.Abs(filepath.Join(projectDir, "test/java-integration")) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "Failed to get test dir: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| // Create and run the Java integration test | ||
| test := New(projectDir, testDir) | ||
|
|
||
| if err := integration.RunTest(ctx, test); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,45 +7,29 @@ import ( | |
| ) | ||
|
|
||
| func main() { | ||
| // Run the language-specific tests | ||
| fmt.Println("=== Running all integration tests ===") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| // Run the C# integration test | ||
| csharpCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/csharp") | ||
| csharpCmd.Stdout = os.Stdout | ||
| csharpCmd.Stderr = os.Stderr | ||
| if err := csharpCmd.Run(); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error running C# integration test: %v\n", err) | ||
| os.Exit(1) | ||
| tests := []struct { | ||
| name string | ||
| path string | ||
| }{ | ||
| {"C#", "github.com/open-feature/cli/test/integration/cmd/csharp"}, | ||
| {"Go", "github.com/open-feature/cli/test/integration/cmd/go"}, | ||
| {"NodeJS", "github.com/open-feature/cli/test/integration/cmd/nodejs"}, | ||
| {"Angular", "github.com/open-feature/cli/test/integration/cmd/angular"}, | ||
| {"Java", "github.com/open-feature/cli/test/integration/cmd/java"}, | ||
| } | ||
|
|
||
| // Run the Go integration test | ||
| goCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/go") | ||
| goCmd.Stdout = os.Stdout | ||
| goCmd.Stderr = os.Stderr | ||
| if err := goCmd.Run(); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error running Go integration test: %v\n", err) | ||
| os.Exit(1) | ||
| for _, test := range tests { | ||
| fmt.Printf("--- Running %s integration test ---\n", test.name) | ||
| cmd := exec.Command("go", "run", test.path) | ||
| cmd.Stdout = os.Stdout | ||
| cmd.Stderr = os.Stderr | ||
| if err := cmd.Run(); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error running %s integration test: %v\n", test.name, err) | ||
| os.Exit(1) | ||
| } | ||
| } | ||
| // Run the nodejs test | ||
| nodeCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/nodejs") | ||
| nodeCmd.Stdout = os.Stdout | ||
| nodeCmd.Stderr = os.Stderr | ||
| if err := nodeCmd.Run(); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error running nodejs integration test: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| // Run the Angular integration test | ||
| angularCmd := exec.Command("go", "run", "github.com/open-feature/cli/test/integration/cmd/angular") | ||
| angularCmd.Stdout = os.Stdout | ||
| angularCmd.Stderr = os.Stderr | ||
| if err := angularCmd.Run(); err != nil { | ||
| fmt.Fprintf(os.Stderr, "Error running Angular integration test: %v\n", err) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| // Add more tests here as they are available | ||
|
|
||
| fmt.Println("=== All integration tests passed successfully ===") | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <groupId>dev.openfeature</groupId> | ||
| <artifactId>cli-java-integration-test</artifactId> | ||
| <version>1.0-SNAPSHOT</version> | ||
|
|
||
| <properties> | ||
| <maven.compiler.source>21</maven.compiler.source> | ||
| <maven.compiler.target>21</maven.compiler.target> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <!-- OpenFeature Java SDK --> | ||
| <dependency> | ||
| <groupId>dev.openfeature</groupId> | ||
| <artifactId>sdk</artifactId> | ||
| <version>1.14.0</version> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <version>3.11.0</version> | ||
| <configuration> | ||
| <source>21</source> | ||
| <target>21</target> | ||
| </configuration> | ||
| </plugin> | ||
| <plugin> | ||
| <groupId>org.codehaus.mojo</groupId> | ||
| <artifactId>exec-maven-plugin</artifactId> | ||
| <version>3.1.0</version> | ||
| <configuration> | ||
| <mainClass>dev.openfeature.Main</mainClass> | ||
| </configuration> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| package dev.openfeature; | ||
|
|
||
| import dev.openfeature.generated.*; | ||
| import dev.openfeature.sdk.*; | ||
| import dev.openfeature.sdk.providers.memory.Flag; | ||
| import dev.openfeature.sdk.providers.memory.InMemoryProvider; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| public class Main { | ||
| public static void main(String[] args) { | ||
| try { | ||
| run(); | ||
| System.out.println("Generated Java code compiles successfully!"); | ||
| } catch (Exception e) { | ||
| System.err.println("Error: " + e.getMessage()); | ||
| e.printStackTrace(); | ||
| System.exit(1); | ||
| } | ||
| } | ||
|
|
||
| private static void run() throws Exception { | ||
| // Set up the in-memory provider with test flags | ||
| Map<String, Object> themeConfig = Map.of( | ||
| "primaryColor", "#007bff", | ||
| "secondaryColor", "#6c757d" | ||
| ); | ||
|
|
||
| Map<String, Flag<?>> flags = Map.of( | ||
| "discountPercentage", Flag.builder() | ||
| .variant("default", 0.15) | ||
| .defaultVariant("default") | ||
| .build(), | ||
| "enableFeatureA", Flag.builder() | ||
| .variant("default", false) | ||
| .defaultVariant("default") | ||
| .build(), | ||
| "greetingMessage", Flag.builder() | ||
| .variant("default", "Hello there!") | ||
| .defaultVariant("default") | ||
| .build(), | ||
| "usernameMaxLength", Flag.builder() | ||
| .variant("default", 50) | ||
| .defaultVariant("default") | ||
| .build(), | ||
| "themeCustomization", Flag.builder() | ||
| .variant("default", new Value(themeConfig)) | ||
| .defaultVariant("default") | ||
| .build() | ||
| ); | ||
|
|
||
| InMemoryProvider provider = new InMemoryProvider(flags); | ||
|
|
||
| // Set the provider | ||
| OpenFeatureAPI.getInstance().setProviderAndWait(provider); | ||
|
|
||
| Client client = OpenFeatureAPI.getInstance().getClient(); | ||
| MutableContext evalContext = new MutableContext(); | ||
|
|
||
| // Use the generated code for all flag evaluations | ||
| Boolean enableFeatureA = EnableFeatureA.value(client, evalContext); | ||
| System.out.println("enableFeatureA: " + enableFeatureA); | ||
| FlagEvaluationDetails<Boolean> enableFeatureADetails = EnableFeatureA.valueWithDetails(client, evalContext); | ||
| if (enableFeatureADetails.getErrorCode() != null) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| throw new Exception("Error evaluating boolean flag"); | ||
| } | ||
|
|
||
| Double discount = DiscountPercentage.value(client, evalContext); | ||
| System.out.printf("Discount Percentage: %.2f%n", discount); | ||
| FlagEvaluationDetails<Double> discountDetails = DiscountPercentage.valueWithDetails(client, evalContext); | ||
| if (discountDetails.getErrorCode() != null) { | ||
| throw new Exception("Failed to get discount"); | ||
| } | ||
|
|
||
| String greetingMessage = GreetingMessage.value(client, evalContext); | ||
| System.out.println("greetingMessage: " + greetingMessage); | ||
| FlagEvaluationDetails<String> greetingDetails = GreetingMessage.valueWithDetails(client, evalContext); | ||
| if (greetingDetails.getErrorCode() != null) { | ||
| throw new Exception("Error evaluating string flag"); | ||
| } | ||
|
|
||
| Integer usernameMaxLength = UsernameMaxLength.value(client, evalContext); | ||
| System.out.println("usernameMaxLength: " + usernameMaxLength); | ||
| FlagEvaluationDetails<Integer> usernameDetails = UsernameMaxLength.valueWithDetails(client, evalContext); | ||
| if (usernameDetails.getErrorCode() != null) { | ||
| throw new Exception("Error evaluating int flag"); | ||
| } | ||
|
|
||
| Value themeCustomization = ThemeCustomization.value(client, evalContext); | ||
| FlagEvaluationDetails<Value> themeDetails = ThemeCustomization.valueWithDetails(client, evalContext); | ||
| if (themeDetails.getErrorCode() != null) { | ||
| throw new Exception("Error evaluating object flag"); | ||
| } | ||
| System.out.println("themeCustomization: " + themeCustomization); | ||
|
|
||
| // Test the getKey() method functionality for all flags | ||
| System.out.println("enableFeatureA flag key: " + EnableFeatureA.getKey()); | ||
| System.out.println("discountPercentage flag key: " + DiscountPercentage.getKey()); | ||
| System.out.println("greetingMessage flag key: " + GreetingMessage.getKey()); | ||
| System.out.println("usernameMaxLength flag key: " + UsernameMaxLength.getKey()); | ||
| System.out.println("themeCustomization flag key: " + ThemeCustomization.getKey()); | ||
|
Comment on lines
+61
to
+101
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test code is incompatible with the current Java generator implementation. The generator (defined in To fix this, the test should be updated to use the generated OpenFeature.GeneratedClient generatedClient = OpenFeature.getClient();
Boolean value = generatedClient.enableFeatureA(evalContext); |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running
go mod tidyduring the integration test is unnecessary and can lead to non-reproducible builds if the environment differs from the developer's. It's better to rely ongo mod downloadto ensure the dependencies defined ingo.sumare used.