diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 80a807f64..a129e7a7c 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -15,23 +15,35 @@ on: schedule: - cron: '0 1 * * *' # nightly build workflow_dispatch: - inputs: - redis_version: - description: "Redis stack version to use for testing" - required: false - default: "8.0-M04-pre" - type: choice - options: - - "8.0-M04-pre" - - "rs-7.4.0-v1" - - "rs-7.2.0-v13" jobs: - build: name: Build and Test runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + redis_version: + - "unstable" + - "8.0" + - "7.4" + - "7.2" + steps: + - name: Test Redis Server Version + id: map-tags + run: | + # Map requested version to github or tag + case "${{ matrix.redis_version }}" in + "unstable") redis_branch="unstable" stack_version="8.0-M03-pre" ;; + "8.0") redis_branch="8.0" stack_version="8.0-M04-pre" ;; + "7.4") redis_branch="7.4" stack_version="rs-7.4.0-v2" ;; + "7.2") redis_branch="7.2" stack_version="rs-7.2.0-v14" ;; + *) echo "Unsupported version: ${{ matrix.redis_version }}" && exit 1 ;; + esac + # Save them as outputs for later use + echo "redis_branch=$redis_branch" >> $GITHUB_OUTPUT + echo "redis_stack_version=$stack_version" >> $GITHUB_OUTPUT - name: Checkout project uses: actions/checkout@v4 - name: Set Java up in the runner @@ -61,7 +73,8 @@ jobs: run: | make test-coverage env: - REDIS_STACK_VERSION: ${{ inputs.redis_version || '8.0-M04-pre' }} + REDIS: ${{ steps.map-tags.outputs.redis_branch }} + REDIS_STACK_VERSION: ${{ steps.map-tags.outputs.redis_stack_version }} JVM_OPTS: -Xmx3200m TERM: dumb - name: Upload coverage reports to Codecov diff --git a/src/test/java/io/lettuce/core/ScanIteratorIntegrationTests.java b/src/test/java/io/lettuce/core/ScanIteratorIntegrationTests.java index da3e12145..2b12d7443 100644 --- a/src/test/java/io/lettuce/core/ScanIteratorIntegrationTests.java +++ b/src/test/java/io/lettuce/core/ScanIteratorIntegrationTests.java @@ -22,6 +22,7 @@ import static io.lettuce.TestTags.INTEGRATION_TEST; import static org.assertj.core.api.AssertionsForClassTypes.*; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.util.ArrayList; import java.util.List; @@ -30,6 +31,7 @@ import javax.inject.Inject; +import io.lettuce.test.condition.RedisConditions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -161,6 +163,8 @@ void hashSinglePass() { @Test void hashNoValuesSinglePass() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); redis.hmset(key, KeysAndValues.MAP); @@ -194,6 +198,8 @@ void hashMultiPass() { @Test void hashNoValuesMultiPass() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); redis.hmset(key, KeysAndValues.MAP); diff --git a/src/test/java/io/lettuce/core/ScanStreamIntegrationTests.java b/src/test/java/io/lettuce/core/ScanStreamIntegrationTests.java index dfa4078db..54172130b 100644 --- a/src/test/java/io/lettuce/core/ScanStreamIntegrationTests.java +++ b/src/test/java/io/lettuce/core/ScanStreamIntegrationTests.java @@ -21,12 +21,14 @@ import static io.lettuce.TestTags.INTEGRATION_TEST; import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.util.List; import java.util.stream.IntStream; import javax.inject.Inject; +import io.lettuce.test.condition.RedisConditions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -95,6 +97,8 @@ void shouldHscanIteratively() { @Test void shouldHscanNovaluesIteratively() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); for (int i = 0; i < 1000; i++) { redis.hset(key, "field-" + i, "value-" + i); @@ -160,6 +164,8 @@ void shouldCorrectlyEmitItemsWithConcurrentPoll() { @Test void shouldCorrectlyEmitKeysWithConcurrentPoll() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); RedisReactiveCommands commands = connection.reactive(); diff --git a/src/test/java/io/lettuce/core/cluster/ScanIteratorIntegrationTests.java b/src/test/java/io/lettuce/core/cluster/ScanIteratorIntegrationTests.java index 068353517..8a5ca15d9 100644 --- a/src/test/java/io/lettuce/core/cluster/ScanIteratorIntegrationTests.java +++ b/src/test/java/io/lettuce/core/cluster/ScanIteratorIntegrationTests.java @@ -22,6 +22,7 @@ import static io.lettuce.TestTags.INTEGRATION_TEST; import static org.assertj.core.api.AssertionsForClassTypes.*; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.util.ArrayList; import java.util.List; @@ -30,6 +31,7 @@ import javax.inject.Inject; +import io.lettuce.test.condition.RedisConditions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -185,6 +187,8 @@ void hashSinglePass() { @Test void hashNovaluesSinglePass() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); redis.hmset(key, KeysAndValues.MAP); @@ -215,6 +219,8 @@ void hashMultiPass() { @Test void hashNovaluesMultiPass() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); redis.hmset(key, KeysAndValues.MAP); diff --git a/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java index 45ee95eb8..149f61e6a 100644 --- a/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java @@ -32,6 +32,7 @@ import io.lettuce.test.LettuceExtension; import io.lettuce.test.ListStreamingAdapter; import io.lettuce.test.condition.EnabledOnCommand; +import io.lettuce.test.condition.RedisConditions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -54,6 +55,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.offset; import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** * Integration tests for {@link io.lettuce.core.api.sync.RedisHashCommands}. @@ -340,6 +342,9 @@ void hscan() { @Test void hscanNovalues() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.hset(key, key, value); KeyScanCursor cursor = redis.hscanNovalues(key); @@ -361,6 +366,9 @@ void hscanWithCursor() { @Test void hscanNoValuesWithCursor() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.hset(key, key, value); KeyScanCursor cursor = redis.hscanNovalues(key, ScanCursor.INITIAL); @@ -383,6 +391,9 @@ void hscanWithCursorAndArgs() { @Test void hscanNoValuesWithCursorAndArgs() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.hset(key, key, value); KeyScanCursor cursor = redis.hscanNovalues(key, ScanCursor.INITIAL, ScanArgs.Builder.limit(2)); @@ -407,6 +418,9 @@ void hscanStreaming() { @Test void hscanNoValuesStreaming() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.hset(key, key, value); ListStreamingAdapter adapter = new ListStreamingAdapter<>(); @@ -432,6 +446,9 @@ void hscanStreamingWithCursor() { @Test void hscanNoValuesStreamingWithCursor() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.hset(key, key, value); ListStreamingAdapter adapter = new ListStreamingAdapter<>(); @@ -457,6 +474,9 @@ void hscanStreamingWithCursorAndArgs() { @Test void hscanNoValuesStreamingWithCursorAndArgs() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.hset(key, key, value); ListStreamingAdapter adapter = new ListStreamingAdapter<>(); @@ -482,6 +502,9 @@ void hscanStreamingWithArgs() { @Test void hscanNoValuesStreamingWithArgs() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.hset(key, key, value); ListStreamingAdapter adapter = new ListStreamingAdapter<>(); @@ -520,6 +543,8 @@ void hscanMultiple() { @Test void hscanNoValuesMultiple() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); Map expect = new LinkedHashMap<>(); setup100KeyValues(expect); @@ -558,6 +583,8 @@ void hscanMatch() { @Test void hscanNoValuesMatch() { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); Map expect = new LinkedHashMap<>(); setup100KeyValues(expect); diff --git a/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java index 1816d3f48..57d613f82 100644 --- a/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java @@ -30,6 +30,7 @@ import io.lettuce.core.protocol.CommandArgs; import io.lettuce.test.LettuceExtension; import io.lettuce.test.condition.EnabledOnCommand; +import io.lettuce.test.condition.RedisConditions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -49,6 +50,7 @@ import static io.lettuce.TestTags.INTEGRATION_TEST; import static io.lettuce.core.protocol.CommandType.XINFO; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** * Integration tests for {@link io.lettuce.core.api.sync.RedisStreamCommands}. @@ -340,6 +342,9 @@ public void xreadTransactional() { @Test public void xreadLastVsLatest() { + // Redis 7.4 - you can use the + sign as a special ID to read the last message in the stream. + assumeTrue(RedisConditions.of(redis).hasVersionGreaterOrEqualsTo("7.4")); + redis.xadd("stream-1", Collections.singletonMap("key1", "value1")); redis.xadd("stream-1", Collections.singletonMap("key2", "value2")); diff --git a/src/test/kotlin/io/lettuce/core/ScanFlowIntegrationTests.kt b/src/test/kotlin/io/lettuce/core/ScanFlowIntegrationTests.kt index ad83fd5fc..464b8253c 100644 --- a/src/test/kotlin/io/lettuce/core/ScanFlowIntegrationTests.kt +++ b/src/test/kotlin/io/lettuce/core/ScanFlowIntegrationTests.kt @@ -23,11 +23,13 @@ import io.lettuce.TestTags import io.lettuce.core.api.StatefulRedisConnection import io.lettuce.core.api.coroutines import io.lettuce.test.LettuceExtension +import io.lettuce.test.condition.RedisConditions import kotlinx.coroutines.flow.count import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Assumptions.assumeTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test @@ -78,6 +80,9 @@ internal class ScanFlowIntegrationTests @Inject constructor(private val connecti @Test fun `should hscanNovalues iteratively`() = runBlocking { + // NOVALUES flag (since Redis 7.4) + assumeTrue(RedisConditions.of(connection).hasVersionGreaterOrEqualsTo("7.4")); + with(connection.coroutines()) { repeat(iterations) { hset(key, "field-$it", "value-$it")