summaryrefslogtreecommitdiffstats
path: root/models/db/context_committer_test.go
blob: 38e91f22edb4148f80c2d4ebfd50e3feb1af0d10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package db // it's not db_test, because this file is for testing the private type halfCommitter

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
)

type MockCommitter struct {
	wants []string
	gots  []string
}

func NewMockCommitter(wants ...string) *MockCommitter {
	return &MockCommitter{
		wants: wants,
	}
}

func (c *MockCommitter) Commit() error {
	c.gots = append(c.gots, "commit")
	return nil
}

func (c *MockCommitter) Close() error {
	c.gots = append(c.gots, "close")
	return nil
}

func (c *MockCommitter) Assert(t *testing.T) {
	assert.Equal(t, c.wants, c.gots, "want operations %v, but got %v", c.wants, c.gots)
}

func Test_halfCommitter(t *testing.T) {
	/*
		Do something like:

		ctx, committer, err := db.TxContext(db.DefaultContext)
		if err != nil {
			return nil
		}
		defer committer.Close()

		// ...

		if err != nil {
			return nil
		}

		// ...

		return committer.Commit()
	*/

	testWithCommitter := func(committer Committer, f func(committer Committer) error) {
		if err := f(&halfCommitter{committer: committer}); err == nil {
			committer.Commit()
		}
		committer.Close()
	}

	t.Run("commit and close", func(t *testing.T) {
		mockCommitter := NewMockCommitter("commit", "close")

		testWithCommitter(mockCommitter, func(committer Committer) error {
			defer committer.Close()
			return committer.Commit()
		})

		mockCommitter.Assert(t)
	})

	t.Run("rollback and close", func(t *testing.T) {
		mockCommitter := NewMockCommitter("close", "close")

		testWithCommitter(mockCommitter, func(committer Committer) error {
			defer committer.Close()
			if true {
				return fmt.Errorf("error")
			}
			return committer.Commit()
		})

		mockCommitter.Assert(t)
	})

	t.Run("close and commit", func(t *testing.T) {
		mockCommitter := NewMockCommitter("close", "close")

		testWithCommitter(mockCommitter, func(committer Committer) error {
			committer.Close()
			committer.Commit()
			return fmt.Errorf("error")
		})

		mockCommitter.Assert(t)
	})
}