From 1031e3498712cc1efc1de0507017f2ee21f5493a Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 18 Oct 2026 14:56:04 +0200 Subject: [PATCH] test: run integration tests on random ports and speed up slow tests (#39842) Integration test processes now get their own work directory, config file and random ports, so several runs can execute in parallel on one machine. The slowest tests also lose fixed sleeps and needlessly expensive setup, with their assertions kept. - Batch PostgreSQL sequence resets, the main per-test fixture cost there - Cheap hashing params in hash and OAuth2 fixture tests, full-cost vectors stay - Single fetch for negative Actions runner assertions instead of 1s polls - Queue flushes and backdated timestamps instead of sleeps - In-memory SQLite test journal, tmpfs for PostgreSQL in CI - E2E instance writes SSH keys into its work directory instead of `~/.ssh/authorized_keys` --- .github/workflows/pull-db-tests.yml | 4 ++ docs/testing.md | 4 ++ modelmigration/migrationtest/tests.go | 8 ++- models/fixtures/oauth2_application.yml | 4 +- models/unittest/fixtures.go | 15 +++--- models/unittest/testdb.go | 2 +- modules/auth/password/hash/hash_test.go | 15 +++++- .../indexer/issues/internal/tests/tests.go | 4 ++ modules/migration/retry_downloader_test.go | 22 ++++++++ modules/setting/testenv.go | 50 +++++++++++++------ modules/util/path.go | 2 +- modules/zstd/zstd_test.go | 16 +++--- routers/web/admin/users_test.go | 10 ++-- routers/web/repo/issue_label_test.go | 4 +- routers/web/repo/issue_page_meta_test.go | 2 +- routers/web/repo/middlewares_test.go | 2 +- routers/web/repo/setting/settings_test.go | 14 +++--- routers/web/repo/view_home_test.go | 2 +- services/org/team_test.go | 42 ---------------- services/repository/archiver/archiver_test.go | 4 -- services/repository/delete_test.go | 9 ++-- services/wiki/wiki_test.go | 2 - tests/integration/actions_concurrency_test.go | 6 ++- .../actions_dynamic_matrix_test.go | 2 +- tests/integration/actions_job_test.go | 3 +- tests/integration/actions_runner_test.go | 4 +- tests/integration/api_repo_languages_test.go | 5 +- tests/integration/api_repo_license_test.go | 8 +-- tests/integration/git_general_test.go | 4 +- tests/integration/git_push_test.go | 18 +++---- tests/integration/integration_test.go | 13 ++--- tests/integration/issue_test.go | 7 ++- tests/integration/migrate_test.go | 4 +- .../migration-test/migration_test.go | 8 ++- tests/integration/pull_merge_test.go | 20 +++++--- tests/integration/repo_webhook_test.go | 9 ++-- tests/mssql.ini.tmpl | 8 +-- tests/mysql.ini.tmpl | 8 +-- tests/pgsql.ini.tmpl | 8 +-- tests/sqlite.ini.tmpl | 11 ++-- tests/test_utils.go | 14 +++--- tools/test-e2e.sh | 1 + 42 files changed, 219 insertions(+), 179 deletions(-) create mode 100644 modules/migration/retry_downloader_test.go diff --git a/.github/workflows/pull-db-tests.yml b/.github/workflows/pull-db-tests.yml index af2d149e67b..244bacc7c2f 100644 --- a/.github/workflows/pull-db-tests.yml +++ b/.github/workflows/pull-db-tests.yml @@ -25,6 +25,8 @@ jobs: env: POSTGRES_DB: test POSTGRES_PASSWORD: postgres + options: >- + --mount type=tmpfs,destination=/var/lib/postgresql/data ports: - "5432:5432" ldap: @@ -61,6 +63,8 @@ jobs: env: POSTGRES_DB: test POSTGRES_PASSWORD: postgres + options: >- + --mount type=tmpfs,destination=/var/lib/postgresql/data ports: - "5432:5432" ldap: diff --git a/docs/testing.md b/docs/testing.md index 8ed9613f3ef..0ccce0fcd0c 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -48,6 +48,10 @@ Run a single integration test with the `#` selector: make test-integration#TestName ``` +Each run gets its own work directory under `tests/integration/` and random ports, so SQLite runs +can execute in parallel. Runs against other databases still share the database and object storage. +The work directory is removed after a passing run and kept after a failure. + If you hit errors such as a mismatched database version or SSH push failures, try a clean rebuild first: diff --git a/modelmigration/migrationtest/tests.go b/modelmigration/migrationtest/tests.go index 9b82e944304..086faf36d83 100644 --- a/modelmigration/migrationtest/tests.go +++ b/modelmigration/migrationtest/tests.go @@ -105,7 +105,7 @@ func LoadTableSchemasMap(t *testing.T, x base.EngineMigration) map[string]*schem func mainTest(m *testing.M) int { testlogger.Init() - err := setting.PrepareIntegrationTestConfig() + workPath, err := setting.PrepareIntegrationTestConfig() if err != nil { return testlogger.MainErrorf("Unable to prepare integration test config: %v", err) } @@ -117,7 +117,11 @@ func mainTest(m *testing.M) int { setting.Database.SlowQueryThreshold = 0 setting.LoadDBSetting() setting.InitLoggersForTest() - return m.Run() + exitCode := m.Run() + if exitCode == 0 { + _ = os.RemoveAll(workPath) + } + return exitCode } func MainTest(m *testing.M) { diff --git a/models/fixtures/oauth2_application.yml b/models/fixtures/oauth2_application.yml index 3426ccffac4..645a833e9c3 100644 --- a/models/fixtures/oauth2_application.yml +++ b/models/fixtures/oauth2_application.yml @@ -3,7 +3,7 @@ uid: 1 name: "Test" client_id: "da7da3ba-9a13-4167-856f-3899de0b0138" - client_secret: "$2a$10$UYRgUSgekzBp6hYe8pAdc.cgB4Gn06QRKsORUnIYTYQADs.YR/uvi" # bcrypt of "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA= + client_secret: "$2a$04$fk.C0LyaUcmxOFLcfcXUDO084yIA9o0nRwkSHSZb/tvZkCzLZjRea" # bcrypt of "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA= redirect_uris: '["https://example.com"]' created_unix: 1546869730 updated_unix: 1546869730 @@ -13,7 +13,7 @@ uid: 2 name: "Test native app" client_id: "ce5a1322-42a7-11ed-b878-0242ac120002" - client_secret: "$2a$10$UYRgUSgekzBp6hYe8pAdc.cgB4Gn06QRKsORUnIYTYQADs.YR/uvi" # bcrypt of "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA= + client_secret: "$2a$04$VvPoNpflYJB94T8seLcZnOCTtQtB3Q2wXw7ZgrWIi2Oix3VWL8s7i" # bcrypt of "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA= redirect_uris: '["http://127.0.0.1"]' created_unix: 1546869730 updated_unix: 1546869730 diff --git a/models/unittest/fixtures.go b/models/unittest/fixtures.go index 19882de96e6..cf52ad68faa 100644 --- a/models/unittest/fixtures.go +++ b/models/unittest/fixtures.go @@ -51,12 +51,15 @@ func loadFixtureResetSeqPgsql(e *xorm.Engine) error { if err != nil { return fmt.Errorf("failed to generate sequence update: %w", err) } - for _, r := range results { - for _, value := range r { - _, err = e.Exec(value) - if err != nil { - return fmt.Errorf("failed to update sequence: %s, error: %w", value, err) - } + var statements []string + for _, result := range results { + for _, statement := range result { + statements = append(statements, statement) + } + } + if len(statements) > 0 { + if _, err := e.Exec(strings.Join(statements, "\n")); err != nil { + return fmt.Errorf("loadFixtureResetSeqPgsql: %w", err) } } return nil diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index 2b00980df02..c995999aa2b 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -206,7 +206,7 @@ type FixturesOptions struct { // CreateTestEngine creates a test database and loads the fixture data from fixturesDir func CreateTestEngine(testSQLiteFile string, opts FixturesOptions) error { - driver, connStr, err := db.ConnStr(db.ConnOptions{Type: setting.DatabaseTypeSQLite3, SQLitePath: testSQLiteFile, SQLiteBusyTimeout: setting.DefaultSQLiteBusyTimeout}) + driver, connStr, err := db.ConnStr(db.ConnOptions{Type: setting.DatabaseTypeSQLite3, SQLitePath: testSQLiteFile, SQLiteBusyTimeout: setting.DefaultSQLiteBusyTimeout, SQLiteJournalMode: "MEMORY"}) if err != nil { return err } diff --git a/modules/auth/password/hash/hash_test.go b/modules/auth/password/hash/hash_test.go index 4b459778de5..3fb454db897 100644 --- a/modules/auth/password/hash/hash_test.go +++ b/modules/auth/password/hash/hash_test.go @@ -75,7 +75,18 @@ func TestHashing(t *testing.T) { for _, algorithmName := range hashAlgorithmsToTest { t.Run(algorithmName, func(t *testing.T) { t.Parallel() // CPU-bound; these subtests only read the shared hasher registry - output, err := Parse(algorithmName).Hash(password, salt) + algorithm := *Parse(algorithmName) + switch algorithm.PasswordSaltHasher.(type) { + case *Argon2Hasher: + algorithm.PasswordSaltHasher = NewArgon2Hasher("2$64$8$50") + case *BcryptHasher: + algorithm.PasswordSaltHasher = NewBcryptHasher("4") + case *PBKDF2Hasher: + algorithm.PasswordSaltHasher = NewPBKDF2Hasher("1$50") + case *ScryptHasher: + algorithm.PasswordSaltHasher = NewScryptHasher("16$16$2$50") + } + output, err := algorithm.Hash(password, salt) if shouldPass { assert.NoError(t, err) assert.NotEmpty(t, output, "output for %s was empty", algorithmName) @@ -83,7 +94,7 @@ func TestHashing(t *testing.T) { assert.Error(t, err) } - assert.Equal(t, Parse(algorithmName).VerifyPassword(password, output, salt), shouldPass) + assert.Equal(t, algorithm.VerifyPassword(password, output, salt), shouldPass) }) } } diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go index 83372725927..02fb332cfd7 100644 --- a/modules/indexer/issues/internal/tests/tests.go +++ b/modules/indexer/issues/internal/tests/tests.go @@ -8,6 +8,7 @@ package tests import ( + "context" "fmt" "slices" "testing" @@ -744,6 +745,9 @@ func countIndexerData(data map[int64]*internal.IndexerData, f func(v *internal.I // waitData waits for the indexer to index all data. // Some engines like Elasticsearch index data asynchronously, so we need to wait for a while. func waitData(t *testing.T, indexer internal.Indexer, total int64) { + if refresher, ok := indexer.(interface{ Refresh(context.Context) error }); ok { + require.NoError(t, refresher.Refresh(t.Context())) + } assert.Eventually(t, func() bool { result, err := indexer.Search(t.Context(), &internal.SearchOptions{Paginator: &db.ListOptions{}}) require.NoError(t, err) diff --git a/modules/migration/retry_downloader_test.go b/modules/migration/retry_downloader_test.go new file mode 100644 index 00000000000..9b003a7aa56 --- /dev/null +++ b/modules/migration/retry_downloader_test.go @@ -0,0 +1,22 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package migration + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRetryDownloaderExhaustsAttempts(t *testing.T) { + failure := errors.New("permission denied") + attempts := 0 + assert.ErrorIs(t, NewRetryDownloader(nil, 3, 0).retry(t.Context(), func(_ctx context.Context) error { + attempts++ + return failure + }), failure) + assert.Equal(t, 3, attempts) +} diff --git a/modules/setting/testenv.go b/modules/setting/testenv.go index d65954c9697..a7661805109 100644 --- a/modules/setting/testenv.go +++ b/modules/setting/testenv.go @@ -6,6 +6,7 @@ package setting import ( "errors" "fmt" + "net" "os" "path/filepath" "runtime" @@ -129,40 +130,58 @@ func SetupGiteaTestEnv() { _ = os.Setenv("GITEA_CONF", giteaConf) // test fixture git hooks use "$GITEA_ROOT/$GITEA_CONF" in their scripts } -func PrepareIntegrationTestConfig() error { +// PrepareIntegrationTestConfig isolates each process for parallel runs +func PrepareIntegrationTestConfig() (workPath string, err error) { giteaTestRoot := detectGiteaTestRoot() isInCI := os.Getenv("CI") != "" testDatabase := os.Getenv("GITEA_TEST_DATABASE") if testDatabase == "" { if isInCI { - return errors.New("GITEA_TEST_DATABASE environment variable not set") + return "", errors.New("GITEA_TEST_DATABASE environment variable not set") } // for local development, default to sqlite. CI needs to explicitly set a database to avoid unexpected results testDatabase = "sqlite" _, _ = fmt.Fprintf(os.Stderr, "Environment variable GITEA_TEST_DATABASE not set - defaulting to %s\n", testDatabase) } - _ = os.Setenv("GITEA_TEST_ROOT", giteaTestRoot) - _ = os.Setenv("GITEA_TEST_CONF", filepath.Join("tests", testDatabase+".ini")) - - workPath := filepath.Join(giteaTestRoot, "tests/integration/gitea-integration-"+testDatabase) - if err := os.MkdirAll(workPath, 0o755); err != nil { - return err - } - - confFile := filepath.Join(giteaTestRoot, "tests", testDatabase+".ini") - tmplBuf, err := os.ReadFile(confFile + ".tmpl") + workPath, err = os.MkdirTemp(filepath.Join(giteaTestRoot, "tests/integration"), "gitea-integration-"+testDatabase+"-") if err != nil { - return err + return "", err + } + confFile := filepath.Join(workPath, "app.ini") + giteaConf, err := filepath.Rel(giteaTestRoot, confFile) + if err != nil { + return "", err + } + _ = os.Setenv("GITEA_TEST_ROOT", giteaTestRoot) + _ = os.Setenv("GITEA_TEST_CONF", giteaConf) + + tmplBuf, err := os.ReadFile(filepath.Join(giteaTestRoot, "tests", testDatabase+".ini.tmpl")) + if err != nil { + return "", err } tmpl := string(tmplBuf) envVars, err := shellquote.Split(os.Getenv("MAKEFILE_VARS")) if err != nil { - return err + return "", err } + httpListener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return "", err + } + defer httpListener.Close() + sshListener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return "", err + } + defer sshListener.Close() + _, httpPort, _ := net.SplitHostPort(httpListener.Addr().String()) + _, sshPort, _ := net.SplitHostPort(sshListener.Addr().String()) envVarMap := map[string]string{ "TEST_WORK_PATH": workPath, "TEST_LOGGER": "test,file", + "TEST_HTTP_PORT": httpPort, + "TEST_SSH_PORT": sshPort, } for _, env := range append(os.Environ(), envVars...) { k, v, _ := strings.Cut(env, "=") @@ -173,6 +192,5 @@ func PrepareIntegrationTestConfig() error { for k, v := range envVarMap { tmpl = strings.ReplaceAll(tmpl, fmt.Sprintf("{{%s}}", k), v) } - err = os.WriteFile(confFile, []byte(tmpl), 0o644) - return err + return workPath, os.WriteFile(confFile, []byte(tmpl), 0o644) } diff --git a/modules/util/path.go b/modules/util/path.go index 43c2cce67a2..0883349a88e 100644 --- a/modules/util/path.go +++ b/modules/util/path.go @@ -223,7 +223,7 @@ func listDirRecursively(result *[]string, fsDir, recordParentPath string, opts * } defer dir.Close() - fis, err := dir.Readdir(0) + fis, err := dir.ReadDir(0) if err != nil { return err } diff --git a/modules/zstd/zstd_test.go b/modules/zstd/zstd_test.go index 3850521f72a..4c3f059103f 100644 --- a/modules/zstd/zstd_test.go +++ b/modules/zstd/zstd_test.go @@ -17,7 +17,7 @@ import ( ) func TestWriterReader(t *testing.T) { - testData := prepareTestData(t, 1_000_000) + testData := prepareTestData(t, 300000) result := bytes.NewBuffer(nil) @@ -73,13 +73,13 @@ func TestWriterReader(t *testing.T) { } func TestSeekableWriterReader(t *testing.T) { - testData := prepareTestData(t, 2_000_000) + testData := prepareTestData(t, 200000) result := bytes.NewBuffer(nil) t.Run("regular", func(t *testing.T) { result.Reset() - blockSize := 100_000 + blockSize := 10000 writer, err := NewSeekableWriter(result, blockSize) require.NoError(t, err) @@ -102,7 +102,7 @@ func TestSeekableWriterReader(t *testing.T) { t.Run("seek read", func(t *testing.T) { result.Reset() - blockSize := 100_000 + blockSize := 10000 writer, err := NewSeekableWriter(result, blockSize) require.NoError(t, err) @@ -118,7 +118,7 @@ func TestSeekableWriterReader(t *testing.T) { reader, err := NewSeekableReader(assertReader) require.NoError(t, err) - _, err = reader.Seek(1_000_000, io.SeekStart) + _, err = reader.Seek(100000, io.SeekStart) require.NoError(t, err) data := make([]byte, 1000) @@ -126,7 +126,7 @@ func TestSeekableWriterReader(t *testing.T) { require.NoError(t, err) require.NoError(t, reader.Close()) - assert.Equal(t, testData[1_000_000:1_000_000+1000], data) + assert.Equal(t, testData[100000:100000+1000], data) // Should seek 3 times, // the first two times are for getting the index, @@ -143,7 +143,7 @@ func TestSeekableWriterReader(t *testing.T) { testData := prepareTestData(t, 1000) // data size is less than a block result.Reset() - blockSize := 100_000 + blockSize := 10000 writer, err := NewSeekableWriter(result, blockSize) require.NoError(t, err) @@ -192,7 +192,7 @@ func TestSeekableWriterReader(t *testing.T) { t.Run("compatible reader", func(t *testing.T) { result.Reset() - blockSize := 100_000 + blockSize := 10000 writer, err := NewSeekableWriter(result, blockSize) require.NoError(t, err) diff --git a/routers/web/admin/users_test.go b/routers/web/admin/users_test.go index 31e0a76849f..9c88f34d724 100644 --- a/routers/web/admin/users_test.go +++ b/routers/web/admin/users_test.go @@ -18,7 +18,7 @@ import ( ) func TestNewUserPost_MustChangePassword(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "admin/users/new") u := unittest.AssertExistsAndLoadBean(t, &user_model.User{ @@ -55,7 +55,7 @@ func TestNewUserPost_MustChangePassword(t *testing.T) { } func TestNewUserPost_MustChangePasswordFalse(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "admin/users/new") u := unittest.AssertExistsAndLoadBean(t, &user_model.User{ @@ -92,7 +92,7 @@ func TestNewUserPost_MustChangePasswordFalse(t *testing.T) { } func TestNewUserPost_InvalidEmail(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "admin/users/new") u := unittest.AssertExistsAndLoadBean(t, &user_model.User{ @@ -122,7 +122,7 @@ func TestNewUserPost_InvalidEmail(t *testing.T) { } func TestNewUserPost_VisibilityDefaultPublic(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "admin/users/new") u := unittest.AssertExistsAndLoadBean(t, &user_model.User{ @@ -160,7 +160,7 @@ func TestNewUserPost_VisibilityDefaultPublic(t *testing.T) { } func TestNewUserPost_VisibilityPrivate(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "admin/users/new") u := unittest.AssertExistsAndLoadBean(t, &user_model.User{ diff --git a/routers/web/repo/issue_label_test.go b/routers/web/repo/issue_label_test.go index 19451a9ab95..0242c58c2b0 100644 --- a/routers/web/repo/issue_label_test.go +++ b/routers/web/repo/issue_label_test.go @@ -23,7 +23,7 @@ import ( ) func TestIssueLabel(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) t.Run("RetrieveLabels", testRetrieveLabels) t.Run("NewLabel", testNewLabel) t.Run("NewLabelInvalidColor", testNewLabelInvalidColor) @@ -199,7 +199,7 @@ func testUpdateIssueLabelToggle(t *testing.T) { {"toggle", []int64{1, 3}, 1, false}, {"toggle", []int64{1, 2}, 2, true}, } { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "user2/repo1/issues/labels") contexttest.LoadUser(t, ctx, 2) contexttest.LoadRepo(t, ctx, 1) diff --git a/routers/web/repo/issue_page_meta_test.go b/routers/web/repo/issue_page_meta_test.go index 40b82d9bc67..fee989523a9 100644 --- a/routers/web/repo/issue_page_meta_test.go +++ b/routers/web/repo/issue_page_meta_test.go @@ -23,7 +23,7 @@ import ( ) func TestRetrieveRepoIssueMetaDataWithPrefill(t *testing.T) { - unittest.PrepareTestEnv(t) + require.NoError(t, unittest.PrepareTestDatabase()) require.NoError(t, db.Insert(t.Context(), []*issues_model.Label{ {ID: 100, RepoID: 1, Name: "Bug"}, diff --git a/routers/web/repo/middlewares_test.go b/routers/web/repo/middlewares_test.go index 35cd903c96a..0a16590ded5 100644 --- a/routers/web/repo/middlewares_test.go +++ b/routers/web/repo/middlewares_test.go @@ -14,7 +14,7 @@ import ( ) func TestDiffViewStyle(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) t.Run("AnonymousUser", func(t *testing.T) { ctx, _ := contexttest.MockContext(t, "/any") diff --git a/routers/web/repo/setting/settings_test.go b/routers/web/repo/setting/settings_test.go index f8cb64e4f55..124e4066676 100644 --- a/routers/web/repo/setting/settings_test.go +++ b/routers/web/repo/setting/settings_test.go @@ -30,7 +30,7 @@ import ( ) func TestAddDeployKey(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) t.Run("ReadOnly", func(t *testing.T) { const testKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICV0MGX/W9IvLA4FXpIuUcdDcbj5KX4syHgsTy7soVgf\n" ctx, _ := contexttest.MockContext(t, "POST /user2/repo1/settings/keys") @@ -52,7 +52,7 @@ func TestAddDeployKey(t *testing.T) { } func TestCollaborationPost(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "user2/repo1/issues/labels") contexttest.LoadUser(t, ctx, 2) contexttest.LoadUser(t, ctx, 4) @@ -87,7 +87,7 @@ func TestCollaborationPost(t *testing.T) { } func TestCollaborationPost_InactiveUser(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "user2/repo1/issues/labels") contexttest.LoadUser(t, ctx, 2) contexttest.LoadUser(t, ctx, 9) @@ -110,7 +110,7 @@ func TestCollaborationPost_InactiveUser(t *testing.T) { } func TestCollaborationPost_AddCollaboratorTwice(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "user2/repo1/issues/labels") contexttest.LoadUser(t, ctx, 2) contexttest.LoadUser(t, ctx, 4) @@ -151,7 +151,7 @@ func TestCollaborationPost_AddCollaboratorTwice(t *testing.T) { } func TestCollaborationPost_NonExistentUser(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "user2/repo1/issues/labels") contexttest.LoadUser(t, ctx, 2) contexttest.LoadRepo(t, ctx, 1) @@ -173,7 +173,7 @@ func TestCollaborationPost_NonExistentUser(t *testing.T) { } func TestAddTeamPost(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 26}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 43}) team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 11}) @@ -219,7 +219,7 @@ func TestAddTeamPost(t *testing.T) { } func TestDeleteTeam(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "org3/team1/repo3") ctx.Req.Form.Set("id", "2") diff --git a/routers/web/repo/view_home_test.go b/routers/web/repo/view_home_test.go index b17c5f4f430..10595f9f903 100644 --- a/routers/web/repo/view_home_test.go +++ b/routers/web/repo/view_home_test.go @@ -15,7 +15,7 @@ import ( ) func TestViewHomeSubmoduleRedirect(t *testing.T) { - unittest.PrepareTestEnv(t) + assert.NoError(t, unittest.PrepareTestDatabase()) ctx, _ := contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule") submodule := git_module.NewCommitSubmoduleFile("/user2/repo1", "test-submodule", "../repo-other", "any-ref-id") diff --git a/services/org/team_test.go b/services/org/team_test.go index a75cca60645..630ed1db176 100644 --- a/services/org/team_test.go +++ b/services/org/team_test.go @@ -154,48 +154,6 @@ func TestDeleteTeam(t *testing.T) { assert.Less(t, accessMode, perm.AccessModeWrite) } -func TestAddTeamMember(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - test := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, AddTeamMember(t.Context(), team, user)) - unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}, &user_model.User{ID: team.OrgID}) - } - - team1 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - team3 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 3}) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - - test(team1, user2) - test(team1, user4) - test(team3, user2) -} - -func TestRemoveTeamMember(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - - testSuccess := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, RemoveTeamMember(t.Context(), team, user)) - unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) - unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) - } - - team1 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - team2 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - team3 := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 3}) - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - - testSuccess(team1, user4) - testSuccess(team2, user2) - testSuccess(team3, user2) - - err := RemoveTeamMember(t.Context(), team1, user2) - assert.True(t, organization.IsErrLastOrgOwner(err)) -} - func TestIncludesAllRepositoriesTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) diff --git a/services/repository/archiver/archiver_test.go b/services/repository/archiver/archiver_test.go index e9b2f52545b..f8fafc69af2 100644 --- a/services/repository/archiver/archiver_test.go +++ b/services/repository/archiver/archiver_test.go @@ -5,7 +5,6 @@ package archiver import ( "testing" - "time" repo_model "gitea.dev/models/repo" "gitea.dev/models/unittest" @@ -106,9 +105,6 @@ func TestArchive_Basic(t *testing.T) { // count. doArchive(t.Context(), zipReq) - // Sleep two seconds to make sure the queue doesn't change. - time.Sleep(2 * time.Second) - zipReq2, err := NewRequest(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, firstCommit+".zip", nil) assert.NoError(t, err) // This zipReq should match what's sitting in the queue, as we haven't diff --git a/services/repository/delete_test.go b/services/repository/delete_test.go index be84b549c18..bd069b5f4cc 100644 --- a/services/repository/delete_test.go +++ b/services/repository/delete_test.go @@ -52,19 +52,16 @@ func TestTeam_RemoveRepository(t *testing.T) { func TestDeleteOwnerRepositoriesDirectly(t *testing.T) { unittest.PrepareTestEnv(t) - user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - - assert.NoError(t, repo_service.DeleteOwnerRepositoriesDirectly(t.Context(), user)) - t.Run("RejectedInTransaction", func(t *testing.T) { - unittest.PrepareTestEnv(t) - err := db.WithTx(t.Context(), func(ctx context.Context) error { return repo_service.DeleteRepositoryDirectly(ctx, 1) }) assert.ErrorContains(t, err, "must not be called within a transaction") unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) }) + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + assert.NoError(t, repo_service.DeleteOwnerRepositoriesDirectly(t.Context(), user)) } func TestDeleteRepositoryDirectlyPurgesRepoScopedRows(t *testing.T) { diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go index aa9914e904a..9040164f79e 100644 --- a/services/wiki/wiki_test.go +++ b/services/wiki/wiki_test.go @@ -300,8 +300,6 @@ func TestPrepareWikiFileName(t *testing.T) { } func TestPrepareWikiFileName_FirstPage(t *testing.T) { - unittest.PrepareTestEnv(t) - // Now create a temporaryDirectory tmpDir := t.TempDir() diff --git a/tests/integration/actions_concurrency_test.go b/tests/integration/actions_concurrency_test.go index 02f46b2802f..95ae1ee38ca 100644 --- a/tests/integration/actions_concurrency_test.go +++ b/tests/integration/actions_concurrency_test.go @@ -1555,9 +1555,11 @@ jobs: // wf1-job2 is waiting but no runner will run it assert.Equal(t, actions_model.StatusWaiting, w1j2Job.Status) - time.Sleep(time.Second) now := time.Now() - time.Sleep(time.Second) + _, err := db.GetEngine(t.Context()).NoAutoTime().ID(w1j2Job.ID).Cols("updated").Update(&actions_model.ActionRunJob{ + Updated: timeutil.TimeStamp(now.Unix()).Add(-1), + }) + require.NoError(t, err) // push workflow2 opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf2TreePath, wf2FileContent) diff --git a/tests/integration/actions_dynamic_matrix_test.go b/tests/integration/actions_dynamic_matrix_test.go index 8c9cf81ed12..49009a1adbc 100644 --- a/tests/integration/actions_dynamic_matrix_test.go +++ b/tests/integration/actions_dynamic_matrix_test.go @@ -119,7 +119,7 @@ jobs: } runner.execTask(t, task, outcome) } - runner.fetchNoTask(t, 300*time.Millisecond) + runner.fetchNoTask(t) return names } diff --git a/tests/integration/actions_job_test.go b/tests/integration/actions_job_test.go index ebfae288010..b0cb85bba31 100644 --- a/tests/integration/actions_job_test.go +++ b/tests/integration/actions_job_test.go @@ -370,7 +370,7 @@ func TestRunnerDisableEnable(t *testing.T) { MakeRequest(t, req, http.StatusOK) testData.runner.execTask(t, task1, &mockTaskOutcome{result: runnerv1.Result_RESULT_SUCCESS}) - testData.runner.fetchNoTask(t, 2*time.Second) + testData.runner.fetchNoTask(t) req = newRunnerUpdateRequest(t, fmt.Sprintf("/api/v1/repos/%s/%s/actions/runners/%d", user2.Name, testData.repo.Name, testData.runnerID), false).AddTokenAuth(token) MakeRequest(t, req, http.StatusOK) @@ -398,7 +398,6 @@ func TestRunnerDisableEnable(t *testing.T) { // Trigger a second run so there is a pending job after we re-enable the runner triggerRunnerDisableEnableRun(t, user2, token, testData.repo, "second-push.txt") - time.Sleep(500 * time.Millisecond) // allow workflow run to be created req := newRunnerUpdateRequest(t, fmt.Sprintf("/api/v1/repos/%s/%s/actions/runners/%d", user2.Name, testData.repo.Name, testData.runnerID), true).AddTokenAuth(token) MakeRequest(t, req, http.StatusOK) diff --git a/tests/integration/actions_runner_test.go b/tests/integration/actions_runner_test.go index c841e2fad1b..b362d083032 100644 --- a/tests/integration/actions_runner_test.go +++ b/tests/integration/actions_runner_test.go @@ -98,8 +98,8 @@ func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1 return task } -func (r *mockRunner) fetchNoTask(t *testing.T, timeout ...time.Duration) { - task := r.tryFetchTask(t, timeout...) +func (r *mockRunner) fetchNoTask(t *testing.T) { + task, _ := r.fetchTaskOnce(t, 0) require.Nil(t, task, "a task is fetched") } diff --git a/tests/integration/api_repo_languages_test.go b/tests/integration/api_repo_languages_test.go index 7d16fe4a9da..32815a23089 100644 --- a/tests/integration/api_repo_languages_test.go +++ b/tests/integration/api_repo_languages_test.go @@ -9,9 +9,11 @@ import ( "testing" "time" + "gitea.dev/modules/queue" "gitea.dev/modules/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestRepoLanguages(t *testing.T) { @@ -36,8 +38,7 @@ func TestRepoLanguages(t *testing.T) { resp = session.MakeRequest(t, req, http.StatusOK) assert.NotEmpty(t, test.RedirectURL(resp)) - // let gitea calculate language stats - time.Sleep(time.Second) + require.NoError(t, queue.GetManager().FlushAll(t.Context(), 10*time.Second)) // Save new file to master branch req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/languages") diff --git a/tests/integration/api_repo_license_test.go b/tests/integration/api_repo_license_test.go index 33a0444a36b..bce8f7f382a 100644 --- a/tests/integration/api_repo_license_test.go +++ b/tests/integration/api_repo_license_test.go @@ -11,10 +11,12 @@ import ( "time" auth_model "gitea.dev/models/auth" + "gitea.dev/modules/queue" api "gitea.dev/modules/structs" "gitea.dev/modules/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var testLicenseContent = ` @@ -51,8 +53,7 @@ func TestAPIRepoLicense(t *testing.T) { resp = session.MakeRequest(t, req, http.StatusOK) assert.NotEmpty(t, test.RedirectURL(resp)) - // let gitea update repo license - time.Sleep(time.Second) + require.NoError(t, queue.GetManager().FlushAll(t.Context(), 10*time.Second)) checkRepoLicense(t, "user2", "repo1", []string{"BSD-2-Clause"}) // Change default branch @@ -63,8 +64,7 @@ func TestAPIRepoLicense(t *testing.T) { }).AddTokenAuth(token) session.MakeRequest(t, req, http.StatusOK) - // let gitea update repo license - time.Sleep(time.Second) + require.NoError(t, queue.GetManager().FlushAll(t.Context(), 10*time.Second)) checkRepoLicense(t, "user2", "repo1", []string{"MIT"}) }) } diff --git a/tests/integration/git_general_test.go b/tests/integration/git_general_test.go index 3ba7c138063..950c0204ac2 100644 --- a/tests/integration/git_general_test.go +++ b/tests/integration/git_general_test.go @@ -33,6 +33,7 @@ import ( "gitea.dev/modules/setting" api "gitea.dev/modules/structs" "gitea.dev/modules/test" + "gitea.dev/services/automergequeue" "gitea.dev/tests" "github.com/kballard/go-shellquote" @@ -817,8 +818,7 @@ func doAutoPRMerge(baseCtx *APITestContext, dstPath string) func(t *testing.T) { // Call API to add Success status for commit t.Run("CreateStatus", doAPICreateCommitStatusTest(ctx, commitID, commitstatus.CommitStatusSuccess, "testci")) - // wait to let gitea merge stuff - time.Sleep(time.Second) + require.NoError(t, automergequeue.AutoMergeQueue.FlushWithContext(t.Context(), 5*time.Second)) // test pr status pr, err = doAPIGetPullRequest(ctx, baseCtx.Username, baseCtx.Reponame, pr.Index)(t) diff --git a/tests/integration/git_push_test.go b/tests/integration/git_push_test.go index 934ae66e198..bfd4f7e01c0 100644 --- a/tests/integration/git_push_test.go +++ b/tests/integration/git_push_test.go @@ -31,7 +31,7 @@ func TestGitPush(t *testing.T) { func testGitPush(t *testing.T, u *url.URL) { t.Run("Push branches at once", func(t *testing.T) { runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) { - for i := range 10 { + for i := range 4 { branchName := fmt.Sprintf("branch-%d", i) pushed = append(pushed, branchName) doGitCreateBranch(gitPath, branchName)(t) @@ -44,21 +44,19 @@ func testGitPush(t *testing.T, u *url.URL) { t.Run("Push branches exists", func(t *testing.T) { runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) { - for i := range 10 { + for i := range 4 { branchName := fmt.Sprintf("branch-%d", i) - if i < 5 { + if i < 2 { pushed = append(pushed, branchName) } doGitCreateBranch(gitPath, branchName)(t) } - // only push master and the first 5 branches pushed = append(pushed, "master") args := append([]string{"origin"}, pushed...) doGitPushTestRepository(gitPath, args...)(t) pushed = pushed[:0] - // do some changes for the first 5 branches created above - for i := range 5 { + for i := range 2 { branchName := fmt.Sprintf("branch-%d", i) pushed = append(pushed, branchName) doGitCheckoutWriteFileCommit(localGitAddCommitOptions{ @@ -69,7 +67,7 @@ func testGitPush(t *testing.T, u *url.URL) { })(t) } - for i := 5; i < 10; i++ { + for i := 2; i < 4; i++ { pushed = append(pushed, fmt.Sprintf("branch-%d", i)) } pushed = append(pushed, "master") @@ -83,7 +81,7 @@ func testGitPush(t *testing.T, u *url.URL) { t.Run("Push branches one by one", func(t *testing.T) { runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) { - for i := range 10 { + for i := range 4 { branchName := fmt.Sprintf("branch-%d", i) doGitCreateBranch(gitPath, branchName)(t) doGitPushTestRepository(gitPath, "origin", branchName)(t) @@ -109,14 +107,14 @@ func testGitPush(t *testing.T, u *url.URL) { doGitPushTestRepository(gitPath, "origin", "master")(t) // make sure master is the default branch instead of a branch we are going to delete pushed = append(pushed, "master") - for i := range 10 { + for i := range 4 { branchName := fmt.Sprintf("branch-%d", i) pushed = append(pushed, branchName) doGitCreateBranch(gitPath, branchName)(t) } doGitPushTestRepository(gitPath, "origin", "--all")(t) - for i := range 5 { + for i := range 2 { branchName := fmt.Sprintf("branch-%d", i) doGitPushTestRepository(gitPath, "origin", "--delete", branchName)(t) deleted = append(deleted, branchName) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 202373dcdc9..e00dd7343f0 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -48,7 +48,7 @@ func testMain(m *testing.M) int { graceful.InitManager(managerCtx) defer cancel() - err := tests.InitIntegrationTest() + workPath, err := tests.InitIntegrationTest() if err != nil { return testlogger.MainErrorf("InitTest error: %v", err) } @@ -67,11 +67,12 @@ func testMain(m *testing.M) int { // Instead, "No tests were found", last nonsense log is "According to the configuration, subsequent logs will not be printed to the console" exitCode := m.Run() - if err = os.RemoveAll(setting.Indexer.IssuePath); err != nil { - log.Error("Failed to remove indexer path: %v", err) - } - if err = os.RemoveAll(setting.Indexer.RepoPath); err != nil { - log.Error("Failed to remove indexer path: %v", err) + if exitCode == 0 { + graceful.GetManager().DoGracefulShutdown() // let background tasks finish writing + <-graceful.GetManager().Done() + if err = os.RemoveAll(workPath); err != nil { + log.Error("Failed to remove work path: %v", err) + } } return exitCode } diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index c1a2429ce96..408d5a8d76e 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -9,6 +9,7 @@ import ( "net/http" "net/url" "path" + "slices" "strconv" "strings" "testing" @@ -29,6 +30,7 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func getIssuesSelection(t testing.TB, htmlDoc *HTMLDoc) *goquery.Selection { @@ -131,8 +133,11 @@ func TestViewIssuesKeyword(t *testing.T) { Index: 1, }) issues.UpdateIssueIndexer(t.Context(), issue.ID) - time.Sleep(time.Second * 1) const keyword = "first" + require.Eventually(t, func() bool { + issueIDs, _, err := issues.SearchIssues(t.Context(), &issues.SearchOptions{Keyword: keyword, RepoIDs: []int64{repo.ID}}) + return err == nil && slices.Contains(issueIDs, issue.ID) + }, 10*time.Second, 10*time.Millisecond) req := NewRequestf(t, "GET", "%s/issues?q=%s", repo.Link(), keyword) resp := MakeRequest(t, req, http.StatusOK) diff --git a/tests/integration/migrate_test.go b/tests/integration/migrate_test.go index a5f330e2f7f..8191a26169b 100644 --- a/tests/integration/migrate_test.go +++ b/tests/integration/migrate_test.go @@ -67,7 +67,7 @@ func TestMigrateGiteaForm(t *testing.T) { repoName := "repo1" repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: ownerName}) session := loginUser(t, ownerName) - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadMisc) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadMisc, auth_model.AccessTokenScopeReadIssue) // Step 0: verify the repo is available req := NewRequestf(t, "GET", "/%s/%s", ownerName, repoName) @@ -99,7 +99,7 @@ func TestMigrateGiteaForm(t *testing.T) { loc := *test.ParseJSONRedirect(resp.Body.Bytes()).Redirect assert.Equal(t, fmt.Sprintf("/%s/%s", ownerName, migratedRepoName), loc) // Step 6: check the repo was created - unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: migratedRepoName}) + assert.Equal(t, repo_model.RepositoryReady, unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: migratedRepoName}).Status) }) } diff --git a/tests/integration/migration-test/migration_test.go b/tests/integration/migration-test/migration_test.go index cc943bfffe6..74ea1d1e244 100644 --- a/tests/integration/migration-test/migration_test.go +++ b/tests/integration/migration-test/migration_test.go @@ -34,7 +34,13 @@ var currentEngine db.EngineMigration func initMigrationTest(t *testing.T) func() { testlogger.Init() - require.NoError(t, setting.PrepareIntegrationTestConfig()) + workPath, err := setting.PrepareIntegrationTestConfig() + require.NoError(t, err) + t.Cleanup(func() { + if !t.Failed() { + _ = os.RemoveAll(workPath) + } + }) setting.SetupGiteaTestEnv() assert.NotEmpty(t, setting.RepoRootPath) diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index 32f78cfb5ae..7d714cff3c8 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -11,6 +11,7 @@ import ( "net/url" "os" "path" + "slices" "strconv" "strings" "testing" @@ -29,8 +30,9 @@ import ( "gitea.dev/modules/commitstatus" "gitea.dev/modules/git" "gitea.dev/modules/git/gitcmd" + issue_indexer "gitea.dev/modules/indexer/issues" "gitea.dev/modules/json" - "gitea.dev/modules/queue" + "gitea.dev/modules/optional" "gitea.dev/modules/setting" api "gitea.dev/modules/structs" "gitea.dev/modules/test" @@ -746,9 +748,6 @@ func TestPullMergeIndexerNotifier(t *testing.T) { testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") createPullResp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "Indexer notifier test pull") - assert.NoError(t, queue.GetManager().FlushAll(t.Context(), 0)) - time.Sleep(time.Second) - repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ OwnerName: "user2", Name: "repo1", @@ -759,6 +758,13 @@ func TestPullMergeIndexerNotifier(t *testing.T) { IsPull: true, IsClosed: false, }) + waitIndexed := func(isClosed bool) { // elasticsearch makes documents searchable asynchronously + require.Eventually(t, func() bool { + ids, _, err := issue_indexer.SearchIssues(t.Context(), &issue_indexer.SearchOptions{Keyword: "notifier", RepoIDs: []int64{repo1.ID}, IsClosed: optional.Some(isClosed)}) + return err == nil && slices.Contains(ids, issue.ID) + }, 10*time.Second, 10*time.Millisecond) + } + waitIndexed(false) // build the request for searching issues link, _ := url.Parse("/api/v1/repos/issues/search") @@ -786,9 +792,7 @@ func TestPullMergeIndexerNotifier(t *testing.T) { ID: issue.ID, }) assert.True(t, issue.IsClosed) - - assert.NoError(t, queue.GetManager().FlushAll(t.Context(), 0)) - time.Sleep(time.Second) + waitIndexed(true) // search issues again searchIssuesResp = session.MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) @@ -937,7 +941,7 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApproval(t *testing.T) { }) assert.NoError(t, err) - time.Sleep(2 * time.Second) + require.NoError(t, automergequeue.AutoMergeQueue.FlushWithContext(t.Context(), 5*time.Second)) // reload pr again pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID}) diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go index edd8b5850b1..d9dae4b4fd2 100644 --- a/tests/integration/repo_webhook_test.go +++ b/tests/integration/repo_webhook_test.go @@ -1600,8 +1600,9 @@ jobs: } } - // Add this sleep to ensure the func can find the tasks by timestamp. - time.Sleep(time.Second) + _, err = db_model.GetEngine(ctx).Where("repo_id = ?", testRepo.ID).NoAutoTime(). + SetExpr("updated", "updated - 2").Update(new(actions_model.ActionRunJob)) + require.NoError(t, err) err = actions.CancelAbandonedJobs(ctx) assert.NoError(t, err) @@ -1685,7 +1686,9 @@ jobs: initialRunEventsLen := len(webhookData.payloads) - time.Sleep(2 * time.Second) + _, err := db_model.GetEngine(t.Context()).In("id", task1.Id, task2.Id). + SetExpr("started", "started - 3").Update(new(actions_model.ActionTask)) + require.NoError(t, err) require.NoError(t, actions.StopEndlessTasks(t.Context())) diff --git a/tests/mssql.ini.tmpl b/tests/mssql.ini.tmpl index 2b6e80ef0e0..1dbb6b4e150 100644 --- a/tests/mssql.ini.tmpl +++ b/tests/mssql.ini.tmpl @@ -33,12 +33,12 @@ SIGNING_KEY = none [server] SSH_DOMAIN = localhost -HTTP_PORT = 3003 -ROOT_URL = http://localhost:3003/ -LOCAL_ROOT_URL = http://127.0.0.1:3003/ +HTTP_PORT = {{TEST_HTTP_PORT}} +ROOT_URL = http://localhost:{{TEST_HTTP_PORT}}/ +LOCAL_ROOT_URL = http://127.0.0.1:{{TEST_HTTP_PORT}}/ DISABLE_SSH = false SSH_LISTEN_HOST = localhost -SSH_PORT = 2201 +SSH_PORT = {{TEST_SSH_PORT}} START_SSH_SERVER = true LFS_START_SERVER = true LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl index 96739da5b2f..d62259431da 100644 --- a/tests/mysql.ini.tmpl +++ b/tests/mysql.ini.tmpl @@ -35,12 +35,12 @@ SIGNING_KEY = none [server] SSH_DOMAIN = localhost -HTTP_PORT = 3001 -ROOT_URL = http://localhost:3001/ -LOCAL_ROOT_URL = http://127.0.0.1:3001/ +HTTP_PORT = {{TEST_HTTP_PORT}} +ROOT_URL = http://localhost:{{TEST_HTTP_PORT}}/ +LOCAL_ROOT_URL = http://127.0.0.1:{{TEST_HTTP_PORT}}/ DISABLE_SSH = false SSH_LISTEN_HOST = localhost -SSH_PORT = 2201 +SSH_PORT = {{TEST_SSH_PORT}} BUILTIN_SSH_SERVER_USER = git START_SSH_SERVER = true diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl index e71f5ce9ca5..130967437c5 100644 --- a/tests/pgsql.ini.tmpl +++ b/tests/pgsql.ini.tmpl @@ -34,12 +34,12 @@ SIGNING_KEY = none [server] SSH_DOMAIN = localhost -HTTP_PORT = 3002 -ROOT_URL = http://localhost:3002/ -LOCAL_ROOT_URL = http://127.0.0.1:3002/ +HTTP_PORT = {{TEST_HTTP_PORT}} +ROOT_URL = http://localhost:{{TEST_HTTP_PORT}}/ +LOCAL_ROOT_URL = http://127.0.0.1:{{TEST_HTTP_PORT}}/ DISABLE_SSH = false SSH_LISTEN_HOST = localhost -SSH_PORT = 2202 +SSH_PORT = {{TEST_SSH_PORT}} START_SSH_SERVER = true LFS_START_SERVER = true LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w diff --git a/tests/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl index 47c85f2e936..dd5fb65a9e8 100644 --- a/tests/sqlite.ini.tmpl +++ b/tests/sqlite.ini.tmpl @@ -4,7 +4,8 @@ RUN_MODE = prod [database] DB_TYPE = sqlite3 -PATH = gitea-test.db +PATH = {{TEST_WORK_PATH}}/gitea-test.db +SQLITE_JOURNAL_MODE = MEMORY [indexer] REPO_INDEXER_ENABLED = true @@ -29,12 +30,12 @@ SIGNING_KEY = none [server] SSH_DOMAIN = localhost -HTTP_PORT = 3003 -ROOT_URL = http://localhost:3003/ -LOCAL_ROOT_URL = http://127.0.0.1:3003/ +HTTP_PORT = {{TEST_HTTP_PORT}} +ROOT_URL = http://localhost:{{TEST_HTTP_PORT}}/ +LOCAL_ROOT_URL = http://127.0.0.1:{{TEST_HTTP_PORT}}/ DISABLE_SSH = false SSH_LISTEN_HOST = localhost -SSH_PORT = 2203 +SSH_PORT = {{TEST_SSH_PORT}} START_SSH_SERVER = true LFS_START_SERVER = true LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w diff --git a/tests/test_utils.go b/tests/test_utils.go index d7f520e405d..bff468bbac9 100644 --- a/tests/test_utils.go +++ b/tests/test_utils.go @@ -21,35 +21,35 @@ import ( "github.com/stretchr/testify/assert" ) -func InitIntegrationTest() error { +func InitIntegrationTest() (workPath string, err error) { testlogger.Init() - err := setting.PrepareIntegrationTestConfig() + workPath, err = setting.PrepareIntegrationTestConfig() if err != nil { - return err + return "", err } setting.SetupGiteaTestEnv() setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master" if err := git.InitFull(); err != nil { - return err + return "", err } setting.Database.SlowQueryThreshold = 0 setting.LoadDBSetting() cleanupDb, err := unittest.ResetTestDatabase() if err != nil { - return err + return "", err } _ = cleanupDb // no clean up yet (not really needed at the moment) if err := storage.Init(); err != nil { - return err + return "", err } routers.InitWebInstalled(graceful.GetManager().HammerContext()) - return nil + return workPath, nil } func PrepareAttachmentsStorage(t testing.TB) { diff --git a/tools/test-e2e.sh b/tools/test-e2e.sh index 87451097b14..0b45575274a 100755 --- a/tools/test-e2e.sh +++ b/tools/test-e2e.sh @@ -103,6 +103,7 @@ PATH = $WORK_DIR/data/gitea.db HTTP_PORT = $FREE_PORT ROOT_URL = http://localhost:$FREE_PORT STATIC_ROOT_PATH = $(pwd) +SSH_ROOT_PATH = $WORK_DIR/ssh [security] INSTALL_LOCK = true