Skip to content

Commit f122abf

Browse files
committed
test vendor
1 parent 533b13d commit f122abf

File tree

6 files changed

+311
-66
lines changed

6 files changed

+311
-66
lines changed

assets/go-licenses.json

Lines changed: 177 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

models/unittest/fixtures.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ func loadFixtureResetSeqPgsql(e *xorm.Engine) error {
5959

6060
// InitFixtures initialize test fixtures for a test database
6161
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
62-
fixturesLoader = newFixturesLoaderInternal(util.IfZero(util.OptionalArg(engine), GetXORMEngine()), opts)
62+
xormEngine := util.IfZero(util.OptionalArg(engine), GetXORMEngine())
63+
fixturesLoader = NewFixturesLoaderInternal(xormEngine, opts)
64+
// fixturesLoader = NewFixturesLoaderVendor(xormEngine, opts)
6365

6466
// register the dummy hash algorithm function used in the test fixtures
6567
_ = hash.Register("dummy", hash.NewDummyHasher)

models/unittest/fixtures_loader_internal.go

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"fmt"
1010
"os"
1111
"path/filepath"
12+
"slices"
1213
"strings"
1314

1415
"code.gitea.io/gitea/modules/util"
@@ -19,20 +20,11 @@ import (
1920
)
2021

2122
type fixturesLoaderInternal struct {
22-
engine *xorm.Engine
23-
opts FixturesOptions
24-
quoteObject func(string) string
25-
paramPlaceholder func(idx int) string
26-
}
27-
28-
func (f *fixturesLoaderInternal) prepareFieldValue(v any) any {
29-
if s, ok := v.(string); ok {
30-
if strings.HasPrefix(s, "0x") {
31-
b, _ := hex.DecodeString(s[2:])
32-
return b
33-
}
34-
}
35-
return v
23+
engine *xorm.Engine
24+
files []string
25+
cachedFixtureItems map[string][]map[string]any
26+
quoteObject func(string) string
27+
paramPlaceholder func(idx int) string
3628
}
3729

3830
func (f *fixturesLoaderInternal) mssqlTableHasIdentityColumn(q *sql.Tx, tableName string) (bool, error) {
@@ -44,20 +36,39 @@ func (f *fixturesLoaderInternal) mssqlTableHasIdentityColumn(q *sql.Tx, tableNam
4436
return count > 0, nil
4537
}
4638

47-
func (f *fixturesLoaderInternal) loadFixtures(tx *sql.Tx, file string) error {
48-
data, err := os.ReadFile(file)
49-
if err != nil {
50-
return fmt.Errorf("failed to read file %q: %w", file, err)
39+
func (f *fixturesLoaderInternal) preprocessFixtureItems(items []map[string]any) (err error) {
40+
for _, m := range items {
41+
for k, v := range m {
42+
if s, ok := v.(string); ok {
43+
if strings.HasPrefix(s, "0x") {
44+
if m[k], err = hex.DecodeString(s[2:]); err != nil {
45+
return err
46+
}
47+
}
48+
}
49+
}
5150
}
51+
return nil
52+
}
5253

53-
var fixtureItems []map[string]any
54-
if err := yaml.Unmarshal(data, &fixtureItems); err != nil {
55-
return fmt.Errorf("failed to unmarshal yaml data from %q: %w", file, err)
54+
func (f *fixturesLoaderInternal) loadFixtures(tx *sql.Tx, file string) error {
55+
fixtureItems, ok := f.cachedFixtureItems[file]
56+
if !ok {
57+
data, err := os.ReadFile(file)
58+
if err != nil {
59+
return fmt.Errorf("failed to read file %q: %w", file, err)
60+
}
61+
if err = yaml.Unmarshal(data, &fixtureItems); err != nil {
62+
return fmt.Errorf("failed to unmarshal yaml data from %q: %w", file, err)
63+
}
64+
if err = f.preprocessFixtureItems(fixtureItems); err != nil {
65+
return fmt.Errorf("failed to preprocess fixture items from %q: %w", file, err)
66+
}
67+
f.cachedFixtureItems[file] = fixtureItems
5668
}
57-
5869
tableName, _, _ := strings.Cut(filepath.Base(file), ".")
5970
tableNameQuoted := f.quoteObject(tableName)
60-
_, err = tx.Exec(fmt.Sprintf("DELETE FROM %s", tableNameQuoted)) // sqlite3 doesn't support truncate
71+
_, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", tableNameQuoted)) // sqlite3 doesn't support truncate
6172
if err != nil {
6273
return err
6374
}
@@ -84,7 +95,7 @@ func (f *fixturesLoaderInternal) loadFixtures(tx *sql.Tx, file string) error {
8495
for k, v := range item {
8596
sqlBuf = append(sqlBuf, f.quoteObject(k)...)
8697
sqlBuf = append(sqlBuf, ","...)
87-
sqlArguments = append(sqlArguments, f.prepareFieldValue(v))
98+
sqlArguments = append(sqlArguments, v)
8899
}
89100
sqlBuf = sqlBuf[:len(sqlBuf)-1]
90101
sqlBuf = append(sqlBuf, ") VALUES ("...)
@@ -112,10 +123,6 @@ func (f *fixturesLoaderInternal) Load() error {
112123
case schemas.SQLITE:
113124
f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) }
114125
f.paramPlaceholder = func(idx int) string { return "?" }
115-
if _, err := goDB.Exec("PRAGMA defer_foreign_keys = ON"); err != nil {
116-
return err
117-
}
118-
defer func() { _, _ = goDB.Exec("PRAGMA defer_foreign_keys = OFF") }()
119126
case schemas.POSTGRES:
120127
f.quoteObject = func(s string) string { return fmt.Sprintf(`"%s"`, s) }
121128
f.paramPlaceholder = func(idx int) string { return fmt.Sprintf(`$%d`, idx) }
@@ -126,33 +133,36 @@ func (f *fixturesLoaderInternal) Load() error {
126133
f.quoteObject = func(s string) string { return fmt.Sprintf("[%s]", s) }
127134
f.paramPlaceholder = func(idx int) string { return "?" }
128135
}
129-
if len(f.opts.Files) == 0 {
130-
entries, err := os.ReadDir(f.opts.Dir)
131-
if err != nil {
132-
return err
133-
}
134-
for _, e := range entries {
135-
f.opts.Files = append(f.opts.Files, e.Name())
136-
}
137-
}
138136

139137
tx, err := goDB.Begin()
140138
if err != nil {
141139
return err
142140
}
143141
defer func() { _ = tx.Rollback() }()
144142

145-
for _, file := range f.opts.Files {
146-
if !filepath.IsAbs(file) {
147-
file = filepath.Join(f.opts.Dir, file)
148-
}
143+
for _, file := range f.files {
149144
if err := f.loadFixtures(tx, file); err != nil {
150145
return fmt.Errorf("failed to load fixtures from %s: %w", file, err)
151146
}
152147
}
153148
return tx.Commit()
154149
}
155150

156-
func newFixturesLoaderInternal(x *xorm.Engine, opts FixturesOptions) *fixturesLoaderInternal {
157-
return &fixturesLoaderInternal{engine: x, opts: opts}
151+
func NewFixturesLoaderInternal(x *xorm.Engine, opts FixturesOptions) FixturesLoader {
152+
files := slices.Clone(opts.Files)
153+
if len(files) == 0 {
154+
entries, err := os.ReadDir(opts.Dir)
155+
if err != nil {
156+
panic(fmt.Errorf("failed to read dir %q: %w", opts.Dir, err))
157+
}
158+
for _, e := range entries {
159+
files = append(files, e.Name())
160+
}
161+
}
162+
for i, file := range files {
163+
if !filepath.IsAbs(file) {
164+
files[i] = filepath.Join(opts.Dir, file)
165+
}
166+
}
167+
return &fixturesLoaderInternal{engine: x, files: files, cachedFixtureItems: map[string][]map[string]any{}}
158168
}

models/unittest/fixtures_loader_vendor.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,31 @@
44
package unittest
55

66
import (
7-
"code.gitea.io/gitea/modules/auth/password/hash"
8-
"code.gitea.io/gitea/modules/setting"
97
"fmt"
8+
"os"
9+
"path/filepath"
1010

1111
"github.com/go-testfixtures/testfixtures/v3"
1212
"xorm.io/xorm"
1313
"xorm.io/xorm/schemas"
1414
)
1515

16-
// InitFixtures initialize test fixtures for a test database
17-
func newFixturesLoaderVendor(e *xorm.Engine, opts FixturesOptions) *testfixtures.Loader {
18-
var fixtureOptionFiles func(*testfixtures.Loader) error
19-
if opts.Dir != "" {
20-
fixtureOptionFiles = testfixtures.Directory(opts.Dir)
21-
} else {
22-
fixtureOptionFiles = testfixtures.Files(opts.Files...)
16+
func NewFixturesLoaderVendor(e *xorm.Engine, opts FixturesOptions) *testfixtures.Loader {
17+
if len(opts.Files) == 0 {
18+
entries, err := os.ReadDir(opts.Dir)
19+
if err != nil {
20+
panic(fmt.Errorf("failed to read directory %q: %w", opts.Dir, err))
21+
}
22+
for _, e := range entries {
23+
opts.Files = append(opts.Files, e.Name())
24+
}
2325
}
26+
for i, file := range opts.Files {
27+
if !filepath.IsAbs(file) {
28+
opts.Files[i] = filepath.Join(opts.Dir, file)
29+
}
30+
}
31+
2432
var dialect string
2533
switch e.Dialect().URI().DBType {
2634
case schemas.POSTGRES:
@@ -38,17 +46,13 @@ func newFixturesLoaderVendor(e *xorm.Engine, opts FixturesOptions) *testfixtures
3846
testfixtures.Database(e.DB().DB),
3947
testfixtures.Dialect(dialect),
4048
testfixtures.DangerousSkipTestDatabaseCheck(),
41-
fixtureOptionFiles,
49+
testfixtures.Files(opts.Files...),
4250
}
4351

4452
if e.Dialect().URI().DBType == schemas.POSTGRES {
4553
loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
4654
}
4755

48-
// register the dummy hash algorithm function used in the test fixtures
49-
_ = hash.Register("dummy", hash.NewDummyHasher)
50-
setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
51-
5256
loader, err := testfixtures.New(loaderOptions...)
5357
if err != nil {
5458
panic(fmt.Errorf("failed to create fixtures loader: %w", err))

models/unittest/fixtures_test.go

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,59 @@
1-
package unittest
1+
package unittest_test
2+
3+
import (
4+
"code.gitea.io/gitea/models/git"
5+
"code.gitea.io/gitea/models/unittest"
6+
user_model "code.gitea.io/gitea/models/user"
7+
"code.gitea.io/gitea/modules/test"
8+
"github.com/stretchr/testify/require"
9+
"path/filepath"
10+
"testing"
11+
)
12+
13+
func prepareTestFixturesLoaders(t testing.TB) unittest.FixturesOptions {
14+
_ = user_model.User{}
15+
_ = git.CommitStatusIndex{}
16+
opts := unittest.FixturesOptions{Dir: filepath.Join(test.SetupGiteaRoot(), "models", "fixtures"), Files: []string{
17+
"commit_status_index.yml",
18+
}}
19+
require.NoError(t, unittest.CreateTestEngine(opts))
20+
return opts
21+
}
22+
23+
func TestFixturesLoader(t *testing.T) {
24+
opts := prepareTestFixturesLoaders(t)
25+
loaderInternal := unittest.NewFixturesLoaderInternal(unittest.GetXORMEngine(), opts)
26+
loaderVendor := unittest.NewFixturesLoaderVendor(unittest.GetXORMEngine(), opts)
27+
t.Run("Internal", func(t *testing.T) {
28+
require.NoError(t, loaderInternal.Load())
29+
require.NoError(t, loaderInternal.Load())
30+
})
31+
t.Run("Vendor", func(t *testing.T) {
32+
require.NoError(t, loaderVendor.Load())
33+
require.NoError(t, loaderVendor.Load())
34+
})
35+
}
36+
37+
func BenchmarkFixturesLoader(b *testing.B) {
38+
opts := prepareTestFixturesLoaders(b)
39+
require.NoError(b, unittest.CreateTestEngine(opts))
40+
loaderInternal := unittest.NewFixturesLoaderInternal(unittest.GetXORMEngine(), opts)
41+
loaderVendor := unittest.NewFixturesLoaderVendor(unittest.GetXORMEngine(), opts)
42+
43+
for i := 0; i < 10; i++ {
44+
require.NoError(b, loaderVendor.Load())
45+
require.NoError(b, loaderInternal.Load())
46+
}
47+
48+
b.Run("Vendor", func(b *testing.B) {
49+
for i := 0; i < b.N; i++ {
50+
require.NoError(b, loaderVendor.Load())
51+
}
52+
})
53+
54+
b.Run("Internal", func(b *testing.B) {
55+
for i := 0; i < b.N; i++ {
56+
require.NoError(b, loaderInternal.Load())
57+
}
58+
})
59+
}

models/unittest/testdb.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,7 @@ import (
2828
"xorm.io/xorm/names"
2929
)
3030

31-
// giteaRoot a path to the gitea root
32-
var (
33-
giteaRoot string
34-
fixturesDir string
35-
)
31+
var giteaRoot string
3632

3733
func fatalTestError(fmtStr string, args ...any) {
3834
_, _ = fmt.Fprintf(os.Stderr, fmtStr, args...)

0 commit comments

Comments
 (0)