| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- // Copyright 2022 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package db_test
-
- import (
- "context"
- "testing"
-
- "code.gitea.io/gitea/models/db"
- "code.gitea.io/gitea/models/unittest"
-
- "github.com/stretchr/testify/assert"
- )
-
- func TestInTransaction(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
- assert.False(t, db.InTransaction(t.Context()))
- assert.NoError(t, db.WithTx(t.Context(), func(ctx context.Context) error {
- assert.True(t, db.InTransaction(ctx))
- return nil
- }))
-
- ctx, committer, err := db.TxContext(t.Context())
- assert.NoError(t, err)
- defer committer.Close()
- assert.True(t, db.InTransaction(ctx))
- assert.NoError(t, db.WithTx(ctx, func(ctx context.Context) error {
- assert.True(t, db.InTransaction(ctx))
- return nil
- }))
- }
-
- func TestTxContext(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
-
- { // create new transaction
- ctx, committer, err := db.TxContext(t.Context())
- assert.NoError(t, err)
- assert.True(t, db.InTransaction(ctx))
- assert.NoError(t, committer.Commit())
- }
-
- { // reuse the transaction created by TxContext and commit it
- ctx, committer, err := db.TxContext(t.Context())
- engine := db.GetEngine(ctx)
- assert.NoError(t, err)
- assert.True(t, db.InTransaction(ctx))
- {
- ctx, committer, err := db.TxContext(ctx)
- assert.NoError(t, err)
- assert.True(t, db.InTransaction(ctx))
- assert.Equal(t, engine, db.GetEngine(ctx))
- assert.NoError(t, committer.Commit())
- }
- assert.NoError(t, committer.Commit())
- }
-
- { // reuse the transaction created by TxContext and close it
- ctx, committer, err := db.TxContext(t.Context())
- engine := db.GetEngine(ctx)
- assert.NoError(t, err)
- assert.True(t, db.InTransaction(ctx))
- {
- ctx, committer, err := db.TxContext(ctx)
- assert.NoError(t, err)
- assert.True(t, db.InTransaction(ctx))
- assert.Equal(t, engine, db.GetEngine(ctx))
- assert.NoError(t, committer.Close())
- }
- assert.NoError(t, committer.Close())
- }
-
- { // reuse the transaction created by WithTx
- assert.NoError(t, db.WithTx(t.Context(), func(ctx context.Context) error {
- assert.True(t, db.InTransaction(ctx))
- {
- ctx, committer, err := db.TxContext(ctx)
- assert.NoError(t, err)
- assert.True(t, db.InTransaction(ctx))
- assert.NoError(t, committer.Commit())
- }
- return nil
- }))
- }
- }
-
- func TestContextSafety(t *testing.T) {
- type TestModel1 struct {
- ID int64
- }
- type TestModel2 struct {
- ID int64
- }
- assert.NoError(t, unittest.GetXORMEngine().Sync(&TestModel1{}, &TestModel2{}))
- assert.NoError(t, db.TruncateBeans(t.Context(), &TestModel1{}, &TestModel2{}))
- testCount := 10
- for i := 1; i <= testCount; i++ {
- assert.NoError(t, db.Insert(t.Context(), &TestModel1{ID: int64(i)}))
- assert.NoError(t, db.Insert(t.Context(), &TestModel2{ID: int64(-i)}))
- }
-
- t.Run("Show-XORM-Bug", func(t *testing.T) {
- actualCount := 0
- // here: db.GetEngine(t.Context()) is a new *Session created from *Engine
- _ = db.WithTx(t.Context(), func(ctx context.Context) error {
- _ = db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error {
- // here: db.GetEngine(ctx) is always the unclosed "Iterate" *Session with autoResetStatement=false,
- // and the internal states (including "cond" and others) are always there and not be reset in this callback.
- m1 := bean.(*TestModel1)
- assert.EqualValues(t, i+1, m1.ID)
-
- // here: XORM bug, it fails because the SQL becomes "WHERE id=-1", "WHERE id=-1 AND id=-2", "WHERE id=-1 AND id=-2 AND id=-3" ...
- // and it conflicts with the "Iterate"'s internal states.
- // has, err := db.GetEngine(ctx).Get(&TestModel2{ID: -m1.ID})
-
- actualCount++
- return nil
- })
- return nil
- })
- assert.Equal(t, testCount, actualCount)
- })
-
- t.Run("DenyBadUsage", func(t *testing.T) {
- assert.PanicsWithError(t, "using session context in an iterator would cause corrupted results", func() {
- _ = db.WithTx(t.Context(), func(ctx context.Context) error {
- return db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error {
- _ = db.GetEngine(ctx)
- return nil
- })
- })
- })
- })
- }
|