jojo/modules/queue/base_redis_test.go
Mathieu Fenniak 37412e6a00 feat: cache OIDC metadata & JWKS when read by authorized integration (#12275)
Enhances authorized integrations (#12261) with a cache of the remote OpenID Connect descriptor file and JSON Web Key Set (JWKS), improving runtime performance and reducing intermittent reliability risks.  By default a 10 minute cache is used, configurable through `[authorized_integration].CACHE_TTL`.

To mock the cache for testing, mockery code generation is added, and a previous manually generated mock for `AuthorizationReducer` was replaced with the code generation.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
    - Authorized integrations are not yet exposed to end-users.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12275
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-04-28 02:13:06 +02:00

144 lines
3.8 KiB
Go

// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package queue
import (
"context"
"testing"
"forgejo.org/modules/nosql"
queue_mock "forgejo.org/modules/queue/mock"
"forgejo.org/modules/setting"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
)
type baseRedisUnitTestSuite struct {
suite.Suite
}
func TestBaseRedis(t *testing.T) {
suite.Run(t, &baseRedisUnitTestSuite{})
}
func (suite *baseRedisUnitTestSuite) SetupSuite() {
}
func (suite *baseRedisUnitTestSuite) TestBasic() {
queueName := "test-queue"
testCases := []struct {
Name string
ConnectionString string
QueueName string
Unique bool
}{
{
Name: "unique",
ConnectionString: "redis://127.0.0.1/0",
QueueName: queueName,
Unique: true,
},
{
Name: "non-unique",
ConnectionString: "redis://127.0.0.1/0",
QueueName: queueName,
Unique: false,
},
{
Name: "unique with prefix",
ConnectionString: "redis://127.0.0.1/0?prefix=forgejo:queue:",
QueueName: "forgejo:queue:" + queueName,
Unique: true,
},
{
Name: "non-unique with prefix",
ConnectionString: "redis://127.0.0.1/0?prefix=forgejo:queue:",
QueueName: "forgejo:queue:" + queueName,
Unique: false,
},
}
for _, testCase := range testCases {
suite.Run(testCase.Name, func() {
queueSettings := setting.QueueSettings{
Length: 10,
ConnStr: testCase.ConnectionString,
}
// Configure expectations.
mockRedisStore := queue_mock.NewInMemoryMockRedis()
redisClient := nosql.NewMockRedisClient(suite.T())
redisClient.EXPECT().
Ping(mock.Anything).
Return(&redis.StatusCmd{}).
Times(1)
redisClient.EXPECT().
LLen(mock.Anything, testCase.QueueName).
RunAndReturn(mockRedisStore.LLen).
Times(1)
redisClient.EXPECT().
LPop(mock.Anything, testCase.QueueName).
RunAndReturn(mockRedisStore.LPop).
Times(1)
redisClient.EXPECT().
RPush(mock.Anything, testCase.QueueName, mock.Anything).
RunAndReturn(func(ctx context.Context, key string, values ...any) *redis.IntCmd {
return mockRedisStore.RPush(ctx, key, values[0].([]byte))
}).
Times(1)
if testCase.Unique {
redisClient.EXPECT().
SAdd(mock.Anything, testCase.QueueName+"_unique", mock.Anything).
RunAndReturn(func(ctx context.Context, key string, members ...any) *redis.IntCmd {
return mockRedisStore.SAdd(ctx, key, members[0].([]byte))
}).
Times(1)
redisClient.EXPECT().
SRem(mock.Anything, testCase.QueueName+"_unique", mock.Anything).
RunAndReturn(func(ctx context.Context, key string, members ...any) *redis.IntCmd {
return mockRedisStore.SRem(ctx, key, members[0].([]byte))
}).
Times(1)
redisClient.EXPECT().
SIsMember(mock.Anything, testCase.QueueName+"_unique", mock.Anything).
RunAndReturn(func(ctx context.Context, key string, member any) *redis.BoolCmd {
return mockRedisStore.SIsMember(ctx, key, member.([]byte))
}).
Times(2)
}
client, err := newBaseRedisGeneric(
toBaseConfig(queueName, queueSettings),
testCase.Unique,
redisClient,
)
suite.Require().NoError(err)
ctx := context.Background()
expectedContent := []byte("test")
suite.Require().NoError(client.PushItem(ctx, expectedContent))
found, err := client.HasItem(ctx, expectedContent)
suite.Require().NoError(err)
if testCase.Unique {
suite.True(found)
} else {
suite.False(found)
}
found, err = client.HasItem(ctx, []byte("not found content"))
suite.Require().NoError(err)
suite.False(found)
content, err := client.PopItem(ctx)
suite.Require().NoError(err)
suite.Equal(expectedContent, content)
})
}
}