mirror of
https://gitea.com/gitea/tea.git
synced 2026-05-02 13:03:51 +02:00
Move integration tests to tests/ directory (#973)
Reviewed-on: https://gitea.com/gitea/tea/pulls/973
This commit is contained in:
@@ -12,13 +12,9 @@ jobs:
|
||||
# uses: golang/govulncheck-action@v1
|
||||
# with:
|
||||
# go-version-file: 'go.mod'
|
||||
check-and-test:
|
||||
check-and-unit:
|
||||
name: Lint Build And Unit Coverage
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HTTP_PROXY: ""
|
||||
GITEA_TEA_TEST_URL: "http://gitea:3000"
|
||||
GITEA_TEA_TEST_USERNAME: "test01"
|
||||
GITEA_TEA_TEST_PASSWORD: "test01"
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-go@v6
|
||||
@@ -32,11 +28,27 @@ jobs:
|
||||
make fmt-check
|
||||
make docs-check
|
||||
make build
|
||||
- run: curl --noproxy "*" http://gitea:3000/api/v1/version # verify connection to instance
|
||||
- name: test and coverage
|
||||
- name: unit test and coverage
|
||||
run: |
|
||||
make test
|
||||
make unit-test-coverage
|
||||
|
||||
integration-test:
|
||||
name: Integration Test
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HTTP_PROXY: ""
|
||||
GITEA_TEA_TEST_URL: "http://gitea:3000"
|
||||
GITEA_TEA_TEST_USERNAME: "test01"
|
||||
GITEA_TEA_TEST_PASSWORD: "test01"
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
- run: curl --noproxy "*" http://gitea:3000/api/v1/version # verify connection to instance
|
||||
- name: integration test
|
||||
run: |
|
||||
make integration-test
|
||||
services:
|
||||
gitea:
|
||||
image: docker.gitea.com/gitea:1.26.1
|
||||
|
||||
27
Makefile
27
Makefile
@@ -30,7 +30,10 @@ LDFLAGS := -X "code.gitea.io/tea/modules/version.Version=$(TEA_VERSION)" -X "cod
|
||||
# override to allow passing additional goflags via make CLI
|
||||
override GOFLAGS := $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)'
|
||||
|
||||
PACKAGES ?= $(shell $(GO) list ./...)
|
||||
PACKAGES ?= $(shell $(GO) list ./... | grep -v '^code.gitea.io/tea/tests')
|
||||
UNIT_PACKAGES ?= $(PACKAGES)
|
||||
INTEGRATION_PACKAGES ?= $(shell $(GO) list ./tests/... 2>/dev/null)
|
||||
INTEGRATION_TEST_TAGS ?= testtools
|
||||
SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||
|
||||
# OS specific vars.
|
||||
@@ -64,11 +67,11 @@ vet:
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run --build-tags testtools
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint-fix:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run --fix
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run --build-tags testtools --fix
|
||||
|
||||
.PHONY: fmt-check
|
||||
fmt-check:
|
||||
@@ -93,13 +96,24 @@ docs-check:
|
||||
exit 1; \
|
||||
fi;
|
||||
|
||||
.PHONY: unit-test
|
||||
unit-test:
|
||||
$(GO) test $(UNIT_PACKAGES)
|
||||
|
||||
.PHONY: integration-test
|
||||
integration-test:
|
||||
@if [ -n "$(INTEGRATION_PACKAGES)" ]; then \
|
||||
$(GO) test -tags='$(INTEGRATION_TEST_TAGS)' $(INTEGRATION_PACKAGES); \
|
||||
else \
|
||||
echo "No integration test packages found"; \
|
||||
fi
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(GO) test -tags='sqlite sqlite_unlock_notify' $(PACKAGES)
|
||||
test: unit-test integration-test
|
||||
|
||||
.PHONY: unit-test-coverage
|
||||
unit-test-coverage:
|
||||
$(GO) test -tags='sqlite sqlite_unlock_notify' -cover -coverprofile coverage.out $(PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||
$(GO) test -cover -coverprofile coverage.out $(UNIT_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
@@ -122,4 +136,3 @@ $(EXECUTABLE): $(SOURCES)
|
||||
.PHONY: build-image
|
||||
build-image:
|
||||
docker build --build-arg VERSION=$(TEA_VERSION) -t gitea/tea:$(TEA_VERSION_TAG) .
|
||||
|
||||
|
||||
13
modules/config/testtools.go
Normal file
13
modules/config/testtools.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build testtools
|
||||
|
||||
package config
|
||||
|
||||
import "time"
|
||||
|
||||
// AcquireConfigLockForTesting exposes the internal lock helper to integration tests.
|
||||
func AcquireConfigLockForTesting(lockPath string, timeout time.Duration) (func() error, error) {
|
||||
return acquireConfigLock(lockPath, timeout)
|
||||
}
|
||||
@@ -4,14 +4,9 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/tea/modules/config"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func Test_MatchLogins(t *testing.T) {
|
||||
@@ -70,47 +65,3 @@ func Test_MatchLogins(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitCommand_WithRepoSlugSkipsLocalRepoDetection(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
config.SetConfigForTesting(config.LocalConfig{
|
||||
Logins: []config.Login{{
|
||||
Name: "test-login",
|
||||
URL: "https://gitea.example.com",
|
||||
Token: "token",
|
||||
User: "login-user",
|
||||
Default: true,
|
||||
}},
|
||||
})
|
||||
|
||||
cmd := exec.Command("git", "init", "--object-format=sha256", tmpDir)
|
||||
cmd.Env = os.Environ()
|
||||
require.NoError(t, cmd.Run())
|
||||
|
||||
oldWd, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.Chdir(tmpDir))
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, os.Chdir(oldWd))
|
||||
})
|
||||
|
||||
cliCmd := cli.Command{
|
||||
Name: "branches",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "login"},
|
||||
&cli.StringFlag{Name: "repo"},
|
||||
&cli.StringFlag{Name: "remote"},
|
||||
&cli.StringFlag{Name: "output"},
|
||||
},
|
||||
}
|
||||
require.NoError(t, cliCmd.Set("repo", "owner/repo"))
|
||||
|
||||
ctx, err := InitCommand(&cliCmd)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "owner", ctx.Owner)
|
||||
require.Equal(t, "repo", ctx.Repo)
|
||||
require.Equal(t, "owner/repo", ctx.RepoSlug)
|
||||
require.Nil(t, ctx.LocalRepo)
|
||||
require.NotNil(t, ctx.Login)
|
||||
require.Equal(t, "test-login", ctx.Login.Name)
|
||||
}
|
||||
|
||||
10
tests/README.md
Normal file
10
tests/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
This directory contains integration tests that exercise tea against external services or external executables.
|
||||
|
||||
- Unit tests stay next to the packages they cover.
|
||||
- Integration tests live under `tests/` so they can be run separately.
|
||||
|
||||
Common targets:
|
||||
|
||||
- `make unit-test`
|
||||
- `make integration-test`
|
||||
- `make test`
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
//go:build unix
|
||||
|
||||
package config
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -12,10 +12,11 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/tea/modules/config"
|
||||
)
|
||||
|
||||
func TestConfigLock_CrossProcess(t *testing.T) {
|
||||
// Create a temp directory for test
|
||||
tmpDir, err := os.MkdirTemp("", "tea-lock-test")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp dir: %v", err)
|
||||
@@ -24,15 +25,16 @@ func TestConfigLock_CrossProcess(t *testing.T) {
|
||||
|
||||
lockPath := filepath.Join(tmpDir, "config.yml.lock")
|
||||
|
||||
// Acquire lock in main process
|
||||
unlock, err := acquireConfigLock(lockPath, 5*time.Second)
|
||||
unlock, err := config.AcquireConfigLockForTesting(lockPath, 5*time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to acquire lock: %v", err)
|
||||
}
|
||||
defer unlock()
|
||||
defer func() {
|
||||
if err := unlock(); err != nil {
|
||||
t.Fatalf("failed to release lock: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Spawn a subprocess that tries to acquire the same lock
|
||||
// The subprocess should fail to acquire within timeout
|
||||
script := fmt.Sprintf(`
|
||||
package main
|
||||
|
||||
@@ -48,19 +50,16 @@ func main() {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Try non-blocking lock
|
||||
err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
|
||||
if err != nil {
|
||||
// Lock is held - expected behavior
|
||||
os.Exit(0)
|
||||
}
|
||||
// Lock was acquired - unexpected
|
||||
|
||||
syscall.Flock(int(file.Fd()), syscall.LOCK_UN)
|
||||
os.Exit(1)
|
||||
}
|
||||
`, lockPath)
|
||||
|
||||
// Write and run the test script
|
||||
scriptPath := filepath.Join(tmpDir, "locktest.go")
|
||||
if err := os.WriteFile(scriptPath, []byte(script), 0o600); err != nil {
|
||||
t.Fatalf("failed to write test script: %v", err)
|
||||
@@ -78,5 +77,4 @@ func main() {
|
||||
t.Errorf("subprocess execution failed: %v", err)
|
||||
}
|
||||
}
|
||||
// Exit code 0 means lock was properly held - success
|
||||
}
|
||||
59
tests/integration/context_init_test.go
Normal file
59
tests/integration/context_init_test.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/tea/modules/config"
|
||||
teacontext "code.gitea.io/tea/modules/context"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func TestInitCommand_WithRepoSlugSkipsLocalRepoDetection(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
config.SetConfigForTesting(config.LocalConfig{
|
||||
Logins: []config.Login{{
|
||||
Name: "test-login",
|
||||
URL: "https://gitea.example.com",
|
||||
Token: "token",
|
||||
User: "login-user",
|
||||
Default: true,
|
||||
}},
|
||||
})
|
||||
|
||||
cmd := exec.Command("git", "init", "--object-format=sha256", tmpDir)
|
||||
cmd.Env = os.Environ()
|
||||
require.NoError(t, cmd.Run())
|
||||
|
||||
oldWd, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, os.Chdir(tmpDir))
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, os.Chdir(oldWd))
|
||||
})
|
||||
|
||||
cliCmd := cli.Command{
|
||||
Name: "branches",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{Name: "login"},
|
||||
&cli.StringFlag{Name: "repo"},
|
||||
&cli.StringFlag{Name: "remote"},
|
||||
&cli.StringFlag{Name: "output"},
|
||||
},
|
||||
}
|
||||
require.NoError(t, cliCmd.Set("repo", "owner/repo"))
|
||||
|
||||
ctx, err := teacontext.InitCommand(&cliCmd)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "owner", ctx.Owner)
|
||||
require.Equal(t, "repo", ctx.Repo)
|
||||
require.Equal(t, "owner/repo", ctx.RepoSlug)
|
||||
require.Nil(t, ctx.LocalRepo)
|
||||
require.NotNil(t, ctx.Login)
|
||||
require.Equal(t, "test-login", ctx.Login.Name)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
package integration
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
teagit "code.gitea.io/tea/modules/git"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRepoFromPath_Worktree(t *testing.T) {
|
||||
// Create a temporary directory for test
|
||||
tmpDir, err := os.MkdirTemp("", "tea-worktree-test-*")
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
@@ -21,21 +21,17 @@ func TestRepoFromPath_Worktree(t *testing.T) {
|
||||
mainRepoPath := filepath.Join(tmpDir, "main-repo")
|
||||
worktreePath := filepath.Join(tmpDir, "worktree")
|
||||
|
||||
// Initialize main repository
|
||||
cmd := exec.Command("git", "init", mainRepoPath)
|
||||
assert.NoError(t, cmd.Run())
|
||||
|
||||
// Configure git for the test
|
||||
cmd = exec.Command("git", "-C", mainRepoPath, "config", "user.email", "test@example.com")
|
||||
assert.NoError(t, cmd.Run())
|
||||
cmd = exec.Command("git", "-C", mainRepoPath, "config", "user.name", "Test User")
|
||||
assert.NoError(t, cmd.Run())
|
||||
|
||||
// Add a remote to the main repository
|
||||
cmd = exec.Command("git", "-C", mainRepoPath, "remote", "add", "origin", "https://gitea.com/owner/repo.git")
|
||||
assert.NoError(t, cmd.Run())
|
||||
|
||||
// Create an initial commit (required for worktree)
|
||||
readmePath := filepath.Join(mainRepoPath, "README.md")
|
||||
err = os.WriteFile(readmePath, []byte("# Test Repo\n"), 0o644)
|
||||
assert.NoError(t, err)
|
||||
@@ -44,19 +40,14 @@ func TestRepoFromPath_Worktree(t *testing.T) {
|
||||
cmd = exec.Command("git", "-C", mainRepoPath, "commit", "-m", "Initial commit")
|
||||
assert.NoError(t, cmd.Run())
|
||||
|
||||
// Create a worktree
|
||||
cmd = exec.Command("git", "-C", mainRepoPath, "worktree", "add", worktreePath, "-b", "test-branch")
|
||||
assert.NoError(t, cmd.Run())
|
||||
|
||||
// Test: Open repository from worktree path
|
||||
repo, err := RepoFromPath(worktreePath)
|
||||
repo, err := teagit.RepoFromPath(worktreePath)
|
||||
assert.NoError(t, err, "Should be able to open worktree")
|
||||
|
||||
// Test: Read config from worktree (should read from main repo's config)
|
||||
config, err := repo.Config()
|
||||
assert.NoError(t, err, "Should be able to read config")
|
||||
|
||||
// Verify that remotes are accessible from worktree
|
||||
assert.NotEmpty(t, config.Remotes, "Should be able to read remotes from worktree")
|
||||
assert.Contains(t, config.Remotes, "origin", "Should have origin remote")
|
||||
assert.Equal(t, "https://gitea.com/owner/repo.git", config.Remotes["origin"].URLs[0], "Should have correct remote URL")
|
||||
@@ -1,28 +1,66 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repos
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/cmd/repos"
|
||||
"code.gitea.io/tea/modules/config"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
func useTempConfigPath(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
configPath := filepath.Join(t.TempDir(), "config.yml")
|
||||
config.SetConfigPathForTesting(configPath)
|
||||
t.Cleanup(func() {
|
||||
config.SetConfigPathForTesting("")
|
||||
})
|
||||
|
||||
return configPath
|
||||
}
|
||||
|
||||
func createIntegrationLogin(t *testing.T, giteaURL string) *config.Login {
|
||||
t.Helper()
|
||||
|
||||
_ = useTempConfigPath(t)
|
||||
|
||||
username := os.Getenv("GITEA_TEA_TEST_USERNAME")
|
||||
password := os.Getenv("GITEA_TEA_TEST_PASSWORD")
|
||||
require.NotEmpty(t, username, "GITEA_TEA_TEST_USERNAME is required for integration tests")
|
||||
require.NotEmpty(t, password, "GITEA_TEA_TEST_PASSWORD is required for integration tests")
|
||||
|
||||
require.NoError(t, task.CreateLogin("integration", "", username, password, "", "", "", giteaURL, "", "", true, false, false, false))
|
||||
|
||||
login, err := config.GetLoginByName("integration")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, login)
|
||||
|
||||
return login
|
||||
}
|
||||
|
||||
func TestCreateRepoObjectFormat(t *testing.T) {
|
||||
giteaURL := os.Getenv("GITEA_TEA_TEST_URL")
|
||||
if giteaURL == "" {
|
||||
t.Skip("GITEA_TEA_TEST_URL is not set, skipping test")
|
||||
}
|
||||
|
||||
login := createIntegrationLogin(t, giteaURL)
|
||||
client := login.Client()
|
||||
timestamp := time.Now().Unix()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
@@ -56,22 +94,15 @@ func TestCreateRepoObjectFormat(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
giteaUserName := os.Getenv("GITEA_TEA_TEST_USERNAME")
|
||||
giteaUserPasword := os.Getenv("GITEA_TEA_TEST_PASSWORD")
|
||||
|
||||
err := task.CreateLogin("test", "", giteaUserName, giteaUserPasword, "", "", "", giteaURL, "", "", true, false, false, false)
|
||||
if err != nil && err.Error() != "login name 'test' has already been used" {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
reposCmd := &cli.Command{
|
||||
Name: "repos",
|
||||
Commands: []*cli.Command{&CmdRepoCreate},
|
||||
Commands: []*cli.Command{&repos.CmdRepoCreate},
|
||||
}
|
||||
tt.args = append(tt.args, "--login", "test")
|
||||
|
||||
args := append([]string{"repos", "create"}, tt.args...)
|
||||
args = append(args, "--login", login.Name)
|
||||
|
||||
err := reposCmd.Run(context.Background(), args)
|
||||
if tt.wantErr {
|
||||
@@ -82,7 +113,12 @@ func TestCreateRepoObjectFormat(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
if _, delErr := client.DeleteRepo(login.User, tt.wantOpts.Name); delErr != nil {
|
||||
t.Logf("failed to delete integration test repo %q: %v", tt.wantOpts.Name, delErr)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user