8000 feat(redis): use testcontainers in rueidis and valkey by mdelapenya · Pull Request #1723 · gofiber/storage · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(redis): use testcontainers in rueidis and valkey #1723

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

Merged
merged 25 commits into from
May 23, 2025

Conversation

mdelapenya
Copy link
Contributor
@mdelapenya mdelapenya commented Apr 30, 2025

What does this PR do?

It creates a testhelpers/redis test module, abstracting the current test implementation for running Redis with testcontainers. This test module has been applied to redis, rueidis and valkey, as they all start a redis/valkey container for testing.

Why is it important?

Do not repeat the same code for starting redis/valkey across three different modules.

Other concerns

Please let me know if this is too over-engineered 🙏 so I can step back and provide a simpler solution. I chose this way because there are multiple combinations for creating redis in the current tests: with/out TLS, using secure/unsecure schema, using/not using MTLS, using URL, using HostPort...

Summary by CodeRabbit

  • New Features

    • Introduced a reusable helper for running Redis containers in tests, supporting flexible configuration (TLS, connection modes, image selection).
  • Refactor

    • Updated Redis, Rueidis, and Valkey test suites to use containerized Redis instances for improved test isolation and cleanup.
    • Replaced static and local Redis configurations with dynamic, per-test containers.
    • Expanded and parameterized TLS-related tests for broader coverage.
  • Chores

    • Removed obsolete test certificate generation script.

Summary by CodeRabbit

  • New Features
    • Introduced a new helper package for running Redis containers in tests, supporting flexible configuration including TLS, image selection, and connection modes.
  • Refactor
    • Updated Redis-based test suites to use isolated, containerized Redis instances for improved test isolation and resource management.
    • Replaced static and manual Redis test setups with reusable container-based helpers.
    • Expanded TLS and connection option test coverage using parameterized subtests.
    • Improved benchmark tests by using a singleton reusable containerized Redis store.
  • Chores
    • Removed an obsolete script for generating test TLS certificates.

@mdelapenya mdelapenya requested a review from a team as a code owner April 30, 2025 08:52
@mdelapenya mdelapenya requested review from gaby, sixcolors, ReneWerner87 and efectn and removed request for a team April 30, 2025 08:52
Copy link
Contributor
coderabbitai bot commented Apr 30, 2025
## Walkthrough

This set of changes introduces a new `testredis` helper package to centralize and simplify the management of Redis containers for integration tests across the codebase. Test suites for `redis`, `valkey`, and `rueidis` storage backends are refactored to use this helper, replacing previous custom container setup logic with standardized options for connection mode, TLS, and image selection. The `.github/scripts/gen-test-certs.sh` script, previously used for generating test TLS certificates, is deleted as its functionality is now encapsulated within the new helper and associated test resources. Test logic remains unchanged, but setup and cleanup are streamlined and isolated per test.

## Changes

| Files / Areas Changed                                 | Summary                                                                                                                        |
|------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
| .github/scripts/gen-test-certs.sh                    | Deleted Bash script for generating test TLS certificates for regression tests.                                                 |
| testhelpers/redis/redis.go                            | Introduced new `testredis` Go package to manage Redis containers for testing with flexible options for TLS, URL, and image.    |
| testhelpers/redis/redis_test.go                       | Added comprehensive unit tests for `testredis` package covering container startup and configuration options.                   |
| redis/redis_test.go                                   | Refactored to use `testredis` for container setup; removed custom container logic and updated option handling.                  |
| valkey/valkey_test.go                                 | Refactored to use `testredis` for Redis container setup; removed global store, improved test isolation and TLS test coverage.   |
| rueidis/rueidis_test.go                               | Refactored to use `testredis` for containerized Redis setup; added helpers, improved TLS and connection option testing.         |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Test as Test Case
    participant testredis as testredis Package
    participant RedisContainer as Redis Container

    Test->>testredis: Start(opts)
    testredis->>RedisContainer: Launch with options (TLS, address, image)
    RedisContainer-->>testredis: Provide connection details (URL, TLS config)
    testredis-->>Test: Return Container info
    Test->>Test: Run storage tests using container info
    Test->>testredis: Cleanup (on test end)

Possibly related PRs

Suggested reviewers

  • gaby
  • sixcolors
  • efectn
  • ReneWerner87

Poem

In the warren where tests once sprawled,
A helper named testredis now is called.
No more scripts with bash and keys,
Just containers spun up with ease.
Each test now hops in its own fresh bed,
While certificates rest, their duties shed.
🐇✨ The code is clean, the rabbits are pleased!


<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 331a84b6c54942d529b036aac4f5a830481205bb and bf7c3091006b457bbd38a76bd039a9ff2535db2d.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `redis/redis_test.go` (10 hunks)
* `rueidis/rueidis_test.go` (10 hunks)
* `testhelpers/redis/redis.go` (1 hunks)
* `valkey/valkey_test.go` (8 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* testhelpers/redis/redis.go

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>rueidis/rueidis_test.go (1)</summary><blockquote>

<details>
<summary>testhelpers/redis/redis.go (6)</summary>

* `Option` (31-31)
* `Start` (83-168)
* `WithTLS` (34-40)
* `WithHostPort` (50-54)
* `WithAddress` (43-47)
* `WithURL` (57-61)

</details>

</blockquote></details>
<details>
<summary>redis/redis_test.go (1)</summary><blockquote>

<details>
<summary>testhelpers/redis/redis.go (8)</summary>

* `Option` (31-31)
* `Config` (19-28)
* `Start` (83-168)
* `Port` (15-15)
* `WithHostPort` (50-54)
* `WithTLS` (34-40)
* `WithAddress` (43-47)
* `WithURL` (57-61)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Tests (1.24.x, 7)

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>redis/redis_test.go (4)</summary>

`10-11`: **LGTM! Clean import of the centralized test helper.**

The import follows the project's naming convention and correctly uses an alias for clarity.

---

`19-43`: **Well-structured refactoring to use the centralized test helper.**

The function correctly delegates container management to `testredis.Start` and properly maps all required fields from the container to the Config struct. The container lifecycle is now managed by the testredis package, which improves consistency across test suites.

---

`228-270`: **Excellent expansion of TLS test coverage with parameterized subtests.**

The refactored test now comprehensively covers all combinations of secure/insecure URLs and mTLS enabled/disabled configurations, significantly improving test coverage.

---

`400-401`: **Proper test skip implementation with clear rationale.**

Using `t.Skip` with an explanatory message is the correct approach for tests awaiting infrastructure support.

</details>
<details>
<summary>rueidis/rueidis_test.go (2)</summary>

`23-41`: **Correctly adapted helper function for rueidis-specific configuration.**

The function properly maps container fields to rueidis Config, using `InitAddress` instead of `Addrs` as required by the rueidis package.

---

`182-220`: **Well-structured TLS test with comprehensive coverage.**

The parameterized subtests effectively cover all TLS configuration combinations, matching the pattern used in redis_test.go.

</details>
<details>
<summary>valkey/valkey_test.go (2)</summary>

`20-36`: **Excellent solution to the benchmark performance regression!**

The singleton pattern with `sync.Once` ensures thread-safe initialization while the container reuse feature (`WithReuse("valkey-benchmark")`) prevents repeated container lifecycle operations. This effectively addresses the performance issues observed in benchmarks.

---

`334-346`: **Benchmarks properly utilize the singleton store pattern.**

All benchmark functions correctly initialize the singleton store once and reuse it across iterations, eliminating the performance overhead from repeated container lifecycle operations.



Also applies to: 348-362, 364-377

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [Link
8000
edIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=gofiber/storage&utm_content=1723):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` or `@coderabbitai title` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@github-actions github-actions bot added ☢️ Bug Something isn't working ✏️ Feature labels Apr 30, 2025
@mdelapenya mdelapenya changed the title fix(benchmarks): re-add redis install for ruedis and valkey feat(redis): use testcontainers in rueidis and valkey Apr 30, 2025
Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (2)
rueidis/rueidis_test.go (1)

92-100: ⚠️ Potential issue

Test_Rueidis_Set_Expiration doesn’t assert that the key expired

The test only sleeps after setting a TTL but never checks that the value is gone, so it can’t detect a regression in expiration logic.

 	err := testStore.Set(key, val, exp)
 	require.NoError(t, err)

 	time.Sleep(1100 * time.Millisecond)
+
+	// New assertions: key should have expired
+	result, err := testStore.Get(key)
+	require.NoError(t, err)
+	require.Zero(t, len(result), "expected value to expire after TTL")
valkey/valkey_test.go (1)

107-115: ⚠️ Potential issue

Test_Valkey_Set_Expiration lacks post-TTL assertion

Like its Rueidis counterpart, this test doesn’t verify that the value actually expires.

 	err := testStore.Set(key, val, exp)
 	require.NoError(t, err)

 	time.Sleep(1100 * time.Millisecond)
+
+	result, err := testStore.Get(key)
+	require.NoError(t, err)
+	require.Zero(t, len(result), "expected value to expire after TTL")
🧹 Nitpick comments (2)
testhelpers/redis/redis.go (1)

159-165: Ambiguous TLS URL handling may lead to mismatched schemes

When UseTLS is true but SecureURL is false, the helper deliberately rewrites rediss:// to redis://, while still returning a non-nil TLSConfig.
Although Rueidis & Valkey drivers work today, the mismatch is surprising and may break other callers that rely on the scheme to determine TLS.

Consider:

  • Documenting the intended behaviour clearly, or
  • Introducing an explicit WithInsecureSchemeOverTLS() option to avoid conflating concerns.

No code change is strictly required, but clarifying intent will prevent future confusion.

redis/redis_test.go (1)

387-420: Consider refactoring cluster test in the future

The Redis cluster test is currently not utilizing the new testredis helper package. This is appropriately explained by the TODO comment indicating that testcontainers-go Redis module doesn't yet support clustering. Consider refactoring this test when clustering support becomes available.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6d622b and 7866e27.

⛔ Files ignored due to path filters (11)
  • .github/workflows/benchmark.yml is excluded by !**/*.yml
  • .github/workflows/test-rueidis.yml is excluded by !**/*.yml
  • .github/workflows/test-valkey.yml is excluded by !**/*.yml
  • redis/go.mod is excluded by !**/*.mod
  • redis/go.sum is excluded by !**/*.sum, !**/*.sum
  • rueidis/go.mod is excluded by !**/*.mod
  • rueidis/go.sum is excluded by !**/*.sum, !**/*.sum
  • testhelpers/redis/go.mod is excluded by !**/*.mod
  • testhelpers/redis/go.sum is excluded by !**/*.sum, !**/*.sum
  • valkey/go.mod is excluded by !**/*.mod
  • valkey/go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (5)
  • .github/scripts/gen-test-certs.sh (0 hunks)
  • redis/redis_test.go (9 hunks)
  • rueidis/rueidis_test.go (11 hunks)
  • testhelpers/redis/redis.go (1 hunks)
  • valkey/valkey_test.go (11 hunks)
💤 Files with no reviewable changes (1)
  • .github/scripts/gen-test-certs.sh
🧰 Additional context used
🧬 Code Graph Analysis (2)
redis/redis_test.go (2)
testhelpers/redis/redis.go (7)
  • Option (38-38)
  • Start (87-168)
  • Port (19-19)
  • WithHostPort (57-61)
  • WithTLS (41-47)
  • WithAddress (50-54)
  • WithURL (64-68)
redis/redis.go (1)
  • Storage (12-14)
rueidis/rueidis_test.go (1)
testhelpers/redis/redis.go (6)
  • Option (38-38)
  • Start (87-168)
  • WithTLS (41-47)
  • WithHostPort (57-61)
  • WithAddress (50-54)
  • WithURL (64-68)
🔇 Additional comments (13)
testhelpers/redis/redis.go (1)

130-133: ⚠️ Potential issue

Crash-on-error: CleanupContainer is executed even when redis.Run fails

redis.Run can return a non-nil error together with a nil container.
Calling testcontainers.CleanupContainer(t, c) before asserting err therefore risks a nil-pointer dereference and will panic instead of producing a clean test failure.

-	c, err := redis.Run(ctx, img, tcOpts...)
-	testcontainers.CleanupContainer(t, c)
-	require.NoError(t, err)
+	c, err := redis.Run(ctx, img, tcOpts...)
+	require.NoError(t, err)
+	testcontainers.CleanupContainer(t, c)
⛔ Skipped due to learnings
Learnt from: mdelapenya
PR: gofiber/storage#1665
File: cassandra/cassandra_test.go:35-38
Timestamp: 2025-04-20T23:52:03.362Z
Learning: In testcontainers-go, calling `testcontainers.CleanupContainer(t, c)` before checking the error from container creation is safe due to the implementation details of the library. The CleanupContainer function handles nil or partially initialized containers gracefully.
rueidis/rueidis_test.go (1)

280-308: Cluster test depends on a locally running 6-node cluster

The cluster test still targets fixed ports on localhost. On CI or contributor machines without a Valkey/Rueidis cluster, it will fail.
Until testcontainers-go supports Redis cluster, consider guarding the test with t.Skip() (as done in the Valkey suite) or wiring it through the new helper.

redis/redis_test.go (11)

9-9: Good addition of the testredis package import

The test helper package import is correctly added, which enables the refactoring of Redis container management to use the centralized helper.


12-16: Documentation updated to reflect new implementation

The function documentation has been properly updated to reflect that it now uses the testredis helper package for container management, while maintaining its purpose of creating a Redis configuration for tests.


16-30: Good refactoring of container setup logic

The container setup logic has been successfully refactored to delegate the responsibility to the testredis.Start helper function, simplifying this code while maintaining the same functionality. The Config struct is properly populated from the container attributes.


37-39: Function signature updated to use new option type

The function signature has been correctly updated to use the new testredis.Option type, maintaining compatibility with all test cases.


202-202: Test case updated to use new option helper

The test case has been updated to use the testredis.WithHostPort() option, maintaining the same behavior as before but with a cleaner interface.


220-220: TLS test cases updated to use new option helper

The TLS test cases have been updated to use the testredis.WithTLS() option with the appropriate parameters, maintaining the same test coverage for both secure/insecure URL and MTLS configurations.


262-262: Universal Addrs test updated with new option helper

The test for address-based connections now uses the testredis.WithAddress() option, maintaining the same test behavior.


288-288: URL undefined test updated with combination of options

This test now correctly uses a combination of testredis.WithAddress() and testredis.WithURL(false) options to test the behavior when URL is explicitly undefined.


313-313: URL defined test updated with appropriate options

The test for defined URL connections now correctly uses a combination of testredis.WithAddress() and testredis.WithURL(true) options.


339-339: Host/Port with Address test updated with appropriate options

The test now correctly uses a combination of testredis.WithAddress(), testredis.WithHostPort(), and testredis.WithURL(false) options to test the precedence of connection methods.


364-364: Host/Port with URL test updated with appropriate options

The test for Host/Port with URL now correctly uses a combination of all three options: testredis.WithAddress(), testredis.WithHostPort(), and testredis.WithURL(true).

@gaby
Copy link
Member
gaby commented Apr 30, 2025

@mdelapenya Only question I had is, does the testhelpers have to be a module? Other than that, looks fine to me. Less boilerplate.

@gaby gaby requested a review from Copilot April 30, 2025 11:55
@gaby gaby removed the ☢️ Bug Something isn't working label Apr 30, 2025
Copy link
Contributor
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a reusable test helper module for running Redis containers with Testcontainers, which is then integrated into the test suites for Valkey, Rueidis, and Redis. This improves test isolation, reduces duplicated setup code, and updates workflow configurations to support the new testing approach.

  • Introduced new helper functions (newConfigFromContainer and newTestStore) in the testhelpers/redis module.
  • Updated test files in valkey, rueidis, and redis packages to use the new helper module.
  • Adjusted GitHub workflow files for test image and filter configuration.

Reviewed Changes

Copilot reviewed 13 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
valkey/valkey_test.go Replaced static Redis setup with container-based configuration via newTestStore
testhelpers/redis/redis.go Added reusable Redis container helper functions using Testcontainers
rueidis/rueidis_test.go Integrated new test container API for consistent configuration across tests
redis/redis_test.go Migrated tests to use the shared testcontainers abstraction, eliminating custom container logic
.github/workflows/*.yml Updated workflow configurations to use updated image tags and filter patterns
Files not reviewed (5)
  • .github/scripts/gen-test-certs.sh: Language not supported
  • redis/go.mod: Language not supported
  • rueidis/go.mod: Language not supported
  • testhelpers/redis/go.mod: Language not supported
  • valkey/go.mod: Language not supported
Comments suppressed due to low confidence (2)

valkey/valkey_test.go:189

  • [nitpick] Use require.NotNil(t, testStore.Conn()) instead of comparing to nil for improved readability and consistency with testify standards.
require.True(t, testStore.Conn() != nil)

valkey/valkey_test.go:250

  • In tests where testStore is already being closed using a deferred call, the explicit call to testStore.Close() can be redundant. Consider removing one of these calls to avoid potential double closure.
require.Nil(t, testStore.Close())

@mdelapenya
Copy link
Contributor Author

@gaby I started with a module to avoid pushing the dependencies to the root package. Probably by my lack of knowledge about who is importing this root module. If it's fine to push them to the root, then I'm more than happy to convert it into a package, maybe internal: ./internal/testhelpers/redis?, and update the references in the redis and friends modules.

@gaby
Copy link
Member
gaby commented Apr 30, 2025

@ga 8000 by I started with a module to avoid pushing the dependencies to the root package. Probably by my lack of knowledge about who is importing this root module. If it's fine to push them to the root, then I'm more than happy to convert it into a package, maybe internal: ./internal/testhelpers/redis?, and update the references in the redis and friends modules.

I honestly don't know how the root go.mod is used. @ReneWerner87 probably remembers.

Another note, redis-go 9.8.0 came out a few minutes ago with full support for Redis 8.0

@ReneWerner87
Copy link
Member

@gaby @mdelapenya
the root go.mod is for the storage interface and all files in the root directory
theoretically you could also use the other sub folders via this package, but nobody should actually do that
so basically for the general parts of the storage repos

* main:
  chore: make sure the client gets the variable locally
  fix(coherence): set coherence log level to ERROR in benchmarks
  Update coherence storage to v2.2.0
  chore(deps): bump dependabot/fetch-metadata from 2.3.0 to 2.4.0
  chore(deps): bump github.com/microsoft/go-mssqldb in /mssql
@ReneWerner87
Copy link
Member

can we refresh this PR
benchmark is the last task here or ?

* main:
  chore(deps): bump github.com/ClickHouse/clickhouse-go/v2 in /clickhouse
  chore(deps): bump github.com/minio/minio-go/v7 in /minio
  chore(deps): bump github.com/valkey-io/valkey-go in /valkey
  chore(deps): bump github.com/jackc/pgx/v5 in /postgres
Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
testhelpers/redis/redis_test.go (2)

21-41: Consider cleaning up environment variables after test

The environment variable test at line 33 uses t.Setenv() which is good, but be aware that in older Go versions this might not automatically clean up after the test. In Go 1.17+ this is handled automatically.


43-55: Inconsistent parallelization in TLS test cases

Some of the TLS test subtests use t.Parallel() while others don't. Consider making all subtests parallel for consistency and improved test performance.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7866e27 and b85c022.

⛔ Files ignored due to path filters (8)
  • .github/workflows/benchmark.yml is excluded by !**/*.yml
  • .github/workflows/golangci-lint.yml is excluded by !**/*.yml
  • .github/workflows/release-drafter.yml is excluded by !**/*.yml
  • .github/workflows/test-teshelpers-redis.yml is excluded by !**/*.yml
  • redis/go.mod is excluded by !**/*.mod
  • redis/go.sum is excluded by !**/*.sum, !**/*.sum
  • valkey/go.mod is excluded by !**/*.mod
  • valkey/go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (1)
  • testhelpers/redis/redis_test.go (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
testhelpers/redis/redis_test.go (1)
testhelpers/redis/redis.go (9)
  • Start (87-168)
  • Port (19-19)
  • WithImage (71-75)
  • ImageEnvVar (18-18)
  • WithTLS (41-47)
  • WithHostPort (57-61)
  • WithAddress (50-54)
  • WithURL (64-68)
  • Image (17-17)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: lint (rueidis)
  • GitHub Check: Tests (1.24.x, 7)
  • GitHub Check: Tests (1.23.x, 7)
  • GitHub Check: Tests (1.23.x, 7)
🔇 Additional comments (6)
testhelpers/redis/redis_test.go (6)

1-9: Well-structured package and imports

The package name and imports are clear and focused, using only what's needed for the tests.


10-19: LGTM: Good baseline test for default configuration

The default configuration test establishes a clear baseline by verifying all expected container properties.


80-90: Parameter values don't match test name

Similar to the previous issue, there's a mismatch between the test name "mtls-enabled" and the parameter passed to WithTLS(false, false). If mTLS should be enabled, the second parameter should be false (not disabled).


94-113: Good isolation of host/port and address configuration options

These tests properly verify that the host/port and address options work as expected and populate the correct fields in the container.


115-157: Well-structured combination tests

The tests with multiple options are thorough and verify that options can be combined correctly, including the important URL/address and TLS combinations.


159-192: Good unit tests for configuration options

These unit tests for the configuration option functions are clean, concise, and verify that each option correctly modifies the Config struct.

@mdelapenya
Copy link
Contributor Author

I refreshed this PR. If you find the helper go module as a non good-practice here, I'm fine in moving to any other place, like an internal/helpers. I wanted to have a common structure to start redis-like containers, like redis and valkey, avoiding pushing all the dependencies in the root module.

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
valkey/valkey_test.go (1)

131-140: 🛠️ Refactor suggestion

Test still doesn't verify actual key expiration behavior.

The Test_Valkey_Get_Expired test continues to check for a non-existent key rather than testing actual expiration. This duplicates the "not-exist" scenario instead of validating TTL behavior.

Consider fixing this test to actually verify expiration:

 func Test_Valkey_Get_Expired(t *testing.T) {
-	key := "john"
+	var (
+		key = "john"
+		val = []byte("doe")
+		exp = 100 * time.Millisecond
+	)
 
 	testStore := newTestStore(t)
 	defer testStore.Close()
 
+	err := testStore.Set(key, val, exp)
+	require.NoError(t, err)
+
+	time.Sleep(150 * time.Millisecond)
+
 	result, err := testStore.Get(key)
 	require.NoError(t, err)
 	require.Zero(t, len(result))
 }
🧹 Nitpick comments (1)
testhelpers/redis/redis.go (1)

93-95: Consider improving error message clarity.

The panic message mentions "using WithImage()" but there's no such function in the current API. The image is passed directly as a parameter to Start().

-		panic("Redis image is not set: callers must provide an image using WithImage()")
+		panic("Redis image is not set: callers must provide a non-empty image parameter")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b85c022 and 331a84b.

⛔ Files ignored due to path filters (2)
  • testhelpers/redis/go.mod is excluded by !**/*.mod
  • testhelpers/redis/go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (4)
  • redis/redis_test.go (9 hunks)
  • testhelpers/redis/redis.go (1 hunks)
  • testhelpers/redis/redis_test.go (1 hunks)
  • valkey/valkey_test.go (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • redis/redis_test.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
testhelpers/redis/redis_test.go (1)
testhelpers/redis/redis.go (7)
  • Start (83-168)
  • Port (15-15)
  • WithTLS (34-40)
  • WithHostPort (50-54)
  • WithAddress (43-47)
  • WithURL (57-61)
  • Config (19-28)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Tests (1.24.x, 7)
  • GitHub Check: Tests (1.23.x, 6)
  • GitHub Check: Tests (1.23.x, 8)
🔇 Additional comments (14)
testhelpers/redis/redis_test.go (4)

1-11: Well-structured test package with appropriate imports.

The package declaration and imports are clean and include all necessary dependencies for comprehensive testing of the Redis container helper.


16-193: Comprehensive test coverage with good use of parallel execution.

The TestStart function provides excellent test coverage for various Redis container configurations:

  • Validates panic behavior for missing image
  • Tests default configuration
  • Covers TLS scenarios with proper parameter combinations
  • Tests different connection modes (host/port, address, URL)
  • Includes a real connectivity test with go-redis client

The parallel execution of subtests is well-implemented to improve test efficiency.


170-192: Integration test properly addresses previous feedback.

The connectivity test effectively validates that the Redis container actually works end-to-end by:

  • Parsing the connection URL
  • Creating a go-redis client with proper configuration
  • Performing a ping operation
  • Asserting the expected "PONG" response

This addresses the previous review suggestion for adding integration testing beyond configuration validation.


195-231: Clean unit tests for configuration options.

The TestConfig function provides focused unit tests for each configuration option function, ensuring they correctly modify the Config struct fields. The parallel execution and clear test structure are good practices.

valkey/valkey_test.go (5)

3-12: Clean imports and dependencies for containerized testing.

The new imports properly include the testredis helper package and necessary sync primitives for the singleton benchmark store pattern.


27-67: Well-designed helper functions for test isolation.

The helper functions provide excellent abstractions:

  • initBenchmarkStore: Implements singleton pattern with proper sync.Once usage for benchmarks
  • newConfigFromContainer: Creates Redis config from container with environment variable override support
  • newTestStore: Provides clean interface for creating isolated test stores

The documentation clearly explains container lifecycle and caller responsibilities.


207-245: Excellent parameterized TLS testing with comprehensive coverage.

The refactored TLS tests provide thorough coverage of all TLS scenarios:

  • Secure/insecure URL combinations
  • mTLS enabled/disabled scenarios
  • Proper parameter passing to the testredis helper

This is a significant improvement over previous static TLS testing approaches.


310-339: Appropriate handling of cluster testing limitations.

The test is properly skipped with a clear TODO comment explaining the dependency on testcontainers-go Valkey module cluster support. This is a reasonable approach until the upstream dependency provides the required functionality.


341-384: Efficient benchmark implementation with singleton pattern.

The benchmarks correctly use the singleton store pattern to avoid container startup overhead during performance testing. The initBenchmarkStore ensures the container is created once and reused across all benchmark iterations.

testhelpers/redis/redis.go (5)

1-16: Clean package structure with clear constants.

The package declaration and port constant are well-defined. The testcontainers and Redis module imports are appropriate for the functionality provided.


18-31: Well-designed configuration structure using functional options pattern.

The Config struct clearly separates different aspects of Redis container configuration:

  • TLS settings (UseTLS, SecureURL, MTLSDisabled)
  • Connection modes (UseAddress, UseHostPort, UseURL)
  • Container lifecycle (name for reuse)

The functional options pattern with the Option type provides a clean, extensible API.


33-70: Comprehensive option functions with clear semantics.

All option functions are well-implemented:

  • WithTLS: Properly handles both URL security and mTLS configuration
  • WithAddress, WithHostPort, WithURL: Provide different connection mode options
  • WithReuse: Enables container reuse for performance optimization

The function signatures and parameter names clearly indicate their purpose.


72-80: Container struct provides comprehensive connection information.

The Container struct exposes all necessary connection details for different client libraries and usage patterns:

  • URL for simple connections
  • Addrs for cluster/sentinel scenarios
  • Host/Port for direct connection
  • TLSConfig for secure connections
  • cmds for debugging/testing purposes

This flexibility supports various Redis client libraries and connection approaches.


82-168: Robust Start function with proper error handling and lifecycle management.

The Start function implementation is well-structured:

  • Proper helper marking and default configuration
  • Panic for missing image (fail-fast approach)
  • Correct TLS command construction for Redis server
  • Proper container lifecycle management with cleanup
  • Flexible connection information extraction based on options

The logic correctly handles the different URL schemes and TLS configurations.

@mdelapenya
Copy link
Contributor Author

@ReneWerner87 @gaby I did a deep research on why the valkey module suffered a huge regression after the changes in this PR (before the singleton container applied to the valkey benchmarks, see 331a84b). Let me explain why I chose to initialise the container just once for the valkey benchmarks and let's validate if this is a valid concern. Thanks Cursor for the support 🤖 :

Root Cause Analysis

The performance regression in the benchmarks was caused by the interaction between Go's benchmark framework and testcontainers-go's container lifecycle management. Here's what was happening:

1. Benchmark Framework Behavior:

  • I noticed that, when the store was initialised inside a benchmark function, Go's benchmark framework runs each that function multiple times. I added a fmt.Print to verify that it was call multiple times 🤯
  • On the other hand, with the singleton pattern, that print happened just once. 🤯
  • The framework performs multiple iterations to establish statistical significance
  • This means the setup code (before b.ResetTimer()) can be executed multiple times ⬅️

2. Original Implementation Issues:

  • I started with each benchmark creating a new container via newTestStore(b)
  • The container was created before b.ReportAllocs() and b.ResetTimer()
  • However, the benchmark framework was still running this setup code multiple times.
  • This resulted in multiple container starts/cleanups per benchmark. E.g., Benchmark_Valkey_SetAndDelete was run 5 times.
  • Each container start/cleanup cycle caused:
    • New container creation
    • New connection establishment
    • Resource allocation and cleanup

3. Impact on Performance:

  • The Valkey Module showed severe impact:
    • Set operation: 387 allocs/op (vs 1 in main branch)
    • SetAndDelete operation: 1590 allocs/op (vs 1 in main branch)
    • High memory usage: 128,374 B/op for Set (vs 39 B/op in main)
  • This could be due to the overhead of repeated container lifecycle operations

Interesting discovery

So in the Redis module:

  • A new container is created for each benchmark
  • The container is cleaned up after each benchmark
  • There is no container reuse
  • Yet it maintains good performance

This makes the situation even more interesting:

  • Both modules create new containers for each benchmark. Actually, any other storage in the repo.
  • Both modules, redis and valkey, use the same testcontainers-go code
  • Both modules have identical benchmark structure
  • But only the Valkey module shows performance degradation
  • In the Main Branch, with a Direct Docker run for valkey, and redis:
    • Valkey client performs excellently
      • Set: 1 alloc/op, 39 B/op
      • Get: 11 allocs/op, 609 B/op
      • SetAndDelete: 1 alloc/op, 108 B/op
  • In the fix-ruedis-benchmarks Branch, this PR:
    • Redis module: performs well (same as main)
    • Valkey module: shows performance regression
    • But when we add container reuse, Valkey performs well again

Solution

The solution implemented a singleton pattern with container reuse:

1. Container Reuse:

  • Uses testcontainers-go's reuse feature
  • Container is started once and reused across benchmarks
  • Avoids repeated container lifecycle operations

2. Thread-Safe Singleton:

  • Ensures container is initialized only once
  • Thread-safe initialization across benchmark goroutines
  • Maintains a single connection throughout the benchmark suite

3. Removed Cleanup Overhead:

  • Removed defer testStore.Close() from benchmarks
  • Container cleanup happens at the end of the test session
  • Eliminates repeated connection teardown

Results

The changes restored performance to optimal levels:

  • Set: 1 alloc/op, 39 B/op (vs 387 allocs/op, 128,374 B/op before)
  • Get: 11 allocs/op, 583 B/op (slightly better than before)
  • SetAndDelete: 1 alloc/op, 70 B/op (vs 1590 allocs/op, 528,947 B/op before)

This solution aligns with the main branch's approach of using a singleton store while leveraging testcontainers-go's container reuse capabilities for efficient testing.

Key Takeaways:

  • Benchmark setup code can run multiple times
  • Container lifecycle operations are expensive
  • Container reuse can be crucial for benchmark performance
  • Thread-safe singleton pattern ensures proper resource management
  • The performance regression was not in the client implementation but in the test infrastructure

@@ -28,7 +28,7 @@ jobs:
- name: Generate filters
id: filter-setup
run: |
filters=$(find . -maxdepth 1 -type d ! -path ./.git ! -path . -exec basename {} \; | grep -v '^\.' | awk '{printf "%s: \"%s/**\"\n", $1, $1}')
filters=$(find . -maxdepth 1 -type d ! -path ./.git ! -path . ! -path ./testhelpers -exec basename {} \; | grep -v '^\.' | awk '{printf "%s: \"%s/**\"\n", $1, $1}')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: the helper tests won't be executed because of this. Have you considered moving to go.work so that it's easier to identify the module paths?

@ReneWerner87 ReneWerner87 merged commit f19bcd6 into gofiber:main May 23, 2025
28 checks passed
@mdelapenya mdelapenya deleted the fix-ruedis-benchmarks branch May 23, 2025 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0