Skip to content

Commit

Permalink
Java: Add IT framework (valkey-io#863)
Browse files Browse the repository at this point in the history
* Add IT framework (#63)

Signed-off-by: Yury-Fridlyand <[email protected]>
  • Loading branch information
Yury-Fridlyand authored Jan 31, 2024
1 parent 96adb91 commit 7348be1
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 9 deletions.
9 changes: 3 additions & 6 deletions .github/workflows/java.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ jobs:
with:
redis-version: ${{ matrix.redis }}

- name: Build rust part
working-directory: java
run: cargo build --release

- name: Build java part
- name: Build java client
working-directory: java
run: ./gradlew --continue build

Expand All @@ -77,10 +73,11 @@ jobs:
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: test-reports-${{ matrix.java }}
name: test-reports-java-${{ matrix.java }}-redis-${{ matrix.redis }}-${{ matrix.os }}
path: |
java/client/build/reports/**
java/integTest/build/reports/**
utils/clusters/**
build-amazonlinux-latest:
if: github.repository_owner == 'aws'
Expand Down
3 changes: 1 addition & 2 deletions java/client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ tasks.register('buildAll') {
finalizedBy 'build'
}

compileJava.dependsOn('protobuf', 'buildRustRelease')
compileJava.dependsOn('protobuf')
clean.dependsOn('cleanProtobuf', 'cleanRust')
test.dependsOn('buildRust')
testFfi.dependsOn('buildRust')
Expand All @@ -127,4 +127,3 @@ tasks.withType(Test) {
}
jvmArgs "-Djava.library.path=${projectDir}/../target/debug"
}

107 changes: 107 additions & 0 deletions java/integTest/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
plugins {
id 'java-library'
}

repositories {
mavenCentral()
}

dependencies {
// client
implementation project(':client')

// lombok
testCompileOnly 'org.projectlombok:lombok:1.18.30'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.30'

// junit
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
testImplementation 'org.mockito:mockito-junit-jupiter:3.12.4'
}

def standaloneRedisPorts = []
def clusterRedisPorts = []

ext {
extractPortsFromClusterManagerOutput = { String output, ArrayList dest ->
for (def line : output.split("\n")) {
if (!line.startsWith("CLUSTER_NODES="))
continue

def addresses = line.split("=")[1].split(",")
for (def address : addresses)
dest << address.split(":")[1]
}
}
}

tasks.register('stopAllAfterTests', Exec) {
workingDir "${project.rootDir}/../utils"
commandLine 'python3', 'cluster_manager.py', 'stop', '--prefix', 'redis-cluster', '--keep-folder'
}

// We need to call for stop before and after the test, but gradle doesn't support executing a task
// twice. So there are two identical tasks with different names.
// We need to call for stop in case if previous test run was interrupted/crashed and didn't stop.
tasks.register('stopAllBeforeTests', Exec) {
workingDir "${project.rootDir}/../utils"
commandLine 'python3', 'cluster_manager.py', 'stop', '--prefix', 'redis-cluster'
ignoreExitValue true // ignore fail if servers are stopped before
}

// delete dirs if stop failed due to https://github.com/aws/glide-for-redis/issues/849
tasks.register('clearDirs', Delete) {
delete "${project.rootDir}/../utils/clusters"
}

tasks.register('startCluster') {
doLast {
new ByteArrayOutputStream().withStream { os ->
exec {
workingDir "${project.rootDir}/../utils"
commandLine 'python3', 'cluster_manager.py', 'start', '--cluster-mode'
standardOutput = os
}
extractPortsFromClusterManagerOutput(os.toString(), clusterRedisPorts)
}
}
}

tasks.register('startStandalone') {
doLast {
new ByteArrayOutputStream().withStream { os ->
exec {
workingDir "${project.rootDir}/../utils"
commandLine 'python3', 'cluster_manager.py', 'start', '-r', '0'
standardOutput = os
}
extractPortsFromClusterManagerOutput(os.toString(), standaloneRedisPorts)
}
}
}

test.dependsOn 'stopAllBeforeTests'
stopAllBeforeTests.finalizedBy 'clearDirs'
clearDirs.finalizedBy 'startStandalone'
clearDirs.finalizedBy 'startCluster'
test.finalizedBy 'stopAllAfterTests'
test.dependsOn ':client:buildRustRelease'

tasks.withType(Test) {
doFirst {
println "Cluster ports = ${clusterRedisPorts}"
println "Standalone ports = ${standaloneRedisPorts}"
systemProperty 'test.redis.standalone.ports', standaloneRedisPorts.join(',')
systemProperty 'test.redis.cluster.ports', clusterRedisPorts.join(',')
}

testLogging {
exceptionFormat "full"
events "started", "skipped", "passed", "failed"
showStandardStreams true
}
jvmArgs "-Djava.library.path=${project.rootDir}/target/release"
afterTest { desc, result ->
logger.quiet "${desc.className}.${desc.name}: ${result.resultType} ${(result.getEndTime() - result.getStartTime())/1000}s"
}
}
42 changes: 42 additions & 0 deletions java/integTest/src/test/java/glide/CommandTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package glide;

import static org.junit.jupiter.api.Assertions.assertTrue;

import glide.api.RedisClient;
import glide.api.models.configuration.NodeAddress;
import glide.api.models.configuration.RedisClientConfiguration;
import java.util.concurrent.TimeUnit;
import lombok.SneakyThrows;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

public class CommandTests {

private static RedisClient regularClient = null;

@BeforeAll
@SneakyThrows
public static void init() {
regularClient =
RedisClient.CreateClient(
RedisClientConfiguration.builder()
.address(
NodeAddress.builder().port(TestConfiguration.STANDALONE_PORTS[0]).build())
.build())
.get(10, TimeUnit.SECONDS);
}

@AfterAll
@SneakyThrows
public static void deinit() {
regularClient.close();
}

@Test
@SneakyThrows
public void custom_command_info() {
var data = regularClient.customCommand(new String[] {"info"}).get(10, TimeUnit.SECONDS);
assertTrue(((String) data).contains("# Stats"));
}
}
26 changes: 26 additions & 0 deletions java/integTest/src/test/java/glide/ConnectionTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package glide;

import glide.api.RedisClient;
import glide.api.models.configuration.NodeAddress;
import glide.api.models.configuration.RedisClientConfiguration;
import java.util.concurrent.TimeUnit;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;

public class ConnectionTests {

@Test
@SneakyThrows
public void basic_client() {
var regularClient =
RedisClient.CreateClient(
RedisClientConfiguration.builder()
.address(
NodeAddress.builder().port(TestConfiguration.STANDALONE_PORTS[0]).build())
.build())
.get(10, TimeUnit.SECONDS);
regularClient.close();
}

// TODO cluster client once implemented
}
15 changes: 15 additions & 0 deletions java/integTest/src/test/java/glide/TestConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package glide;

import java.util.Arrays;

public final class TestConfiguration {
// All redis servers are hosted on localhost
public static final int[] STANDALONE_PORTS = getPortsFromProperty("test.redis.standalone.ports");
public static final int[] CLUSTER_PORTS = getPortsFromProperty("test.redis.cluster.ports");

private static int[] getPortsFromProperty(String propName) {
return Arrays.stream(System.getProperty(propName).split(","))
.mapToInt(Integer::parseInt)
.toArray();
}
}
2 changes: 2 additions & 0 deletions java/integTest/src/test/resources/junit-platform.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
junit.jupiter.displayname.generator.default = \
org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores
4 changes: 3 additions & 1 deletion utils/cluster_manager.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/python3

# Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0

import argparse
Expand Down Expand Up @@ -260,7 +262,7 @@ def create_cluster_folder(path: str, prefix: str) -> str:
str: The full path of the cluster folder
"""
time = datetime.now(timezone.utc)
time_str = time.strftime("%Y-%m-%dT%H:%M:%SZ")
time_str = time.strftime("%Y-%m-%dT%H-%M-%SZ")
cluster_folder = f"{path}/{prefix}-{time_str}-{get_random_string(6)}"
logging.debug(f"## Creating cluster folder in {cluster_folder}")
Path(cluster_folder).mkdir(exist_ok=True)
Expand Down

0 comments on commit 7348be1

Please sign in to comment.