[v11.0/forgejo] fix: package_blob.has_blake2b may be null (#7521)
Some checks failed
testing / backend-checks (push) Has been skipped
testing / frontend-checks (push) Has been skipped
testing / test-unit (push) Has been skipped
testing / test-e2e (push) Has been skipped
testing / test-mysql (push) Has been skipped
testing / test-pgsql (push) Has been skipped
testing / test-sqlite (push) Has been skipped
testing / test-remote-cacher (redis) (push) Has been skipped
testing / test-remote-cacher (valkey) (push) Has been skipped
testing / test-remote-cacher (garnet) (push) Has been skipped
testing / test-remote-cacher (redict) (push) Has been skipped
testing / security-check (push) Has been skipped
/ release (push) Has been cancelled

**Backport:** https://codeberg.org/forgejo/forgejo/pulls/7520

- When looking for an existing blob, has_blake2b will be null when it was created prior to v26 migration in v11, when the field was introduced.
- Add unit test and minimal refactoring to load fixtures. The AddFixture function should not be where it currently is because it cannot be used by some packages (circular import). But that's a refactor that needs to be elsewhere for backporting purposes.

Fixes https://codeberg.org/forgejo/forgejo/issues/7519

When the fix is missing, the test fails like so:

```
--- FAIL: TestPackagesGetOrInsertBlob (0.03s)
    --- FAIL: TestPackagesGetOrInsertBlob/exists_and_blake2b_is_null_in_the_database (0.00s)
        package_blob_test.go:55:
            	Error Trace:	/home/earl-warren/software/forgejo/models/packages/package_blob_test.go:55
            	Error:      	Not equal:
            	            	expected: true
            	            	actual  : false
            	Test:       	TestPackagesGetOrInsertBlob/exists_and_blake2b_is_null_in_the_database
        package_blob_test.go:56:
            	Error Trace:	/home/earl-warren/software/forgejo/models/packages/package_blob_test.go:56
            	Error:      	Expected value not to be nil.
            	Test:       	TestPackagesGetOrInsertBlob/exists_and_blake2b_is_null_in_the_database
```

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. 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

- 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 added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### 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

- [x] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7521
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
This commit is contained in:
forgejo-backport-action 2025-04-11 13:08:56 +00:00 committed by Earl Warren
parent 7bc4f4976e
commit 6bcdfd6efb
5 changed files with 125 additions and 17 deletions

View file

@ -0,0 +1,17 @@
-
id: 1
size: 10
hash_md5: HASHMD5_1
hash_sha1: HASHSHA1_1
hash_sha256: HASHSHA256_1
hash_sha512: HASHSHA512_1
hash_blake2b: HASHBLAKE2B_1
created_unix: 946687980
-
id: 2
size: 20
hash_md5: HASHMD5_2
hash_sha1: HASHSHA1_2
hash_sha256: HASHSHA256_2
hash_sha512: HASHSHA512_2
created_unix: 946687980

View file

@ -0,0 +1,31 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package packages
import (
"path/filepath"
"testing"
"forgejo.org/models/unittest"
"forgejo.org/modules/setting"
_ "forgejo.org/models"
_ "forgejo.org/models/actions"
_ "forgejo.org/models/activities"
_ "forgejo.org/models/forgefed"
)
func AddFixtures(dirs ...string) func() {
return unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: dirs,
},
)
}
func TestMain(m *testing.M) {
unittest.MainTest(m)
}

View file

@ -44,14 +44,19 @@ func GetOrInsertBlob(ctx context.Context, pb *PackageBlob) (*PackageBlob, bool,
existing := &PackageBlob{} existing := &PackageBlob{}
has, err := e.Where(builder.Eq{ has, err := e.Where(builder.And(
builder.Eq{
"size": pb.Size, "size": pb.Size,
"hash_md5": pb.HashMD5, "hash_md5": pb.HashMD5,
"hash_sha1": pb.HashSHA1, "hash_sha1": pb.HashSHA1,
"hash_sha256": pb.HashSHA256, "hash_sha256": pb.HashSHA256,
"hash_sha512": pb.HashSHA512, "hash_sha512": pb.HashSHA512,
"hash_blake2b": pb.HashBlake2b, },
}).Get(existing) builder.Or(
builder.Eq{"hash_blake2b": pb.HashBlake2b},
builder.IsNull{"hash_blake2b"},
),
)).Get(existing)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }

View file

@ -0,0 +1,64 @@
// Copyright 2025 The Forgejo Authors.
// SPDX-License-Identifier: GPL-3.0-or-later
package packages
import (
"testing"
"forgejo.org/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPackagesGetOrInsertBlob(t *testing.T) {
defer AddFixtures("models/fixtures/TestPackagesGetOrInsertBlob/")()
require.NoError(t, unittest.PrepareTestDatabase())
blake2bIsSet := unittest.AssertExistsAndLoadBean(t, &PackageBlob{ID: 1})
blake2bNotSet := unittest.AssertExistsAndLoadBean(t, &PackageBlob{ID: 2})
blake2bSetToRandom := *blake2bNotSet
blake2bSetToRandom.HashBlake2b = "SOMETHING RANDOM"
for _, testCase := range []struct {
name string
exists bool
packageBlob *PackageBlob
}{
{
name: "exists and blake2b is not null in the database",
exists: true,
packageBlob: blake2bIsSet,
},
{
name: "exists and blake2b is null in the database",
exists: true,
packageBlob: &blake2bSetToRandom,
},
{
name: "does not exists",
exists: false,
packageBlob: &PackageBlob{
Size: 30,
HashMD5: "HASHMD5_3",
HashSHA1: "HASHSHA1_3",
HashSHA256: "HASHSHA256_3",
HashSHA512: "HASHSHA512_3",
HashBlake2b: "HASHBLAKE2B_3",
},
},
} {
t.Run(testCase.name, func(t *testing.T) {
found, has, _ := GetOrInsertBlob(t.Context(), testCase.packageBlob)
assert.Equal(t, testCase.exists, has)
require.NotNil(t, found)
if testCase.exists {
assert.Equal(t, found.ID, testCase.packageBlob.ID)
} else {
unittest.BeanExists(t, &PackageBlob{ID: found.ID})
}
})
}
}

View file

@ -13,18 +13,9 @@ import (
"forgejo.org/models/unittest" "forgejo.org/models/unittest"
user_model "forgejo.org/models/user" user_model "forgejo.org/models/user"
_ "forgejo.org/models"
_ "forgejo.org/models/actions"
_ "forgejo.org/models/activities"
_ "forgejo.org/models/forgefed"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestMain(m *testing.M) {
unittest.MainTest(m)
}
func prepareExamplePackage(t *testing.T) *packages_model.Package { func prepareExamplePackage(t *testing.T) *packages_model.Package {
require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, unittest.PrepareTestDatabase())