Move integration tests to tests/ directory (#973)

Reviewed-on: https://gitea.com/gitea/tea/pulls/973
This commit is contained in:
Lunny Xiao
2026-05-02 04:18:45 +00:00
parent 1f6fd97fc1
commit 83b718ac34
9 changed files with 184 additions and 101 deletions

10
tests/README.md Normal file
View 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`

View File

@@ -0,0 +1,80 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build unix
package integration
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
"code.gitea.io/tea/modules/config"
)
func TestConfigLock_CrossProcess(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "tea-lock-test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
lockPath := filepath.Join(tmpDir, "config.yml.lock")
unlock, err := config.AcquireConfigLockForTesting(lockPath, 5*time.Second)
if err != nil {
t.Fatalf("failed to acquire lock: %v", err)
}
defer func() {
if err := unlock(); err != nil {
t.Fatalf("failed to release lock: %v", err)
}
}()
script := fmt.Sprintf(`
package main
import (
"os"
"syscall"
)
func main() {
file, err := os.OpenFile(%q, os.O_CREATE|os.O_RDWR, 0o600)
if err != nil {
os.Exit(2)
}
defer file.Close()
err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
if err != nil {
os.Exit(0)
}
syscall.Flock(int(file.Fd()), syscall.LOCK_UN)
os.Exit(1)
}
`, lockPath)
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)
}
cmd := exec.Command("go", "run", scriptPath)
if err := cmd.Run(); err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
if exitErr.ExitCode() == 1 {
t.Error("subprocess acquired lock when it should have been held")
} else if exitErr.ExitCode() == 2 {
t.Errorf("subprocess failed to open lock file: %v", err)
}
} else {
t.Errorf("subprocess execution failed: %v", err)
}
}
}

View 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)
}

View File

@@ -0,0 +1,54 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"os"
"os/exec"
"path/filepath"
"testing"
teagit "code.gitea.io/tea/modules/git"
"github.com/stretchr/testify/assert"
)
func TestRepoFromPath_Worktree(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "tea-worktree-test-*")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
mainRepoPath := filepath.Join(tmpDir, "main-repo")
worktreePath := filepath.Join(tmpDir, "worktree")
cmd := exec.Command("git", "init", mainRepoPath)
assert.NoError(t, cmd.Run())
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())
cmd = exec.Command("git", "-C", mainRepoPath, "remote", "add", "origin", "https://gitea.com/owner/repo.git")
assert.NoError(t, cmd.Run())
readmePath := filepath.Join(mainRepoPath, "README.md")
err = os.WriteFile(readmePath, []byte("# Test Repo\n"), 0o644)
assert.NoError(t, err)
cmd = exec.Command("git", "-C", mainRepoPath, "add", "README.md")
assert.NoError(t, cmd.Run())
cmd = exec.Command("git", "-C", mainRepoPath, "commit", "-m", "Initial commit")
assert.NoError(t, cmd.Run())
cmd = exec.Command("git", "-C", mainRepoPath, "worktree", "add", worktreePath, "-b", "test-branch")
assert.NoError(t, cmd.Run())
repo, err := teagit.RepoFromPath(worktreePath)
assert.NoError(t, err, "Should be able to open worktree")
config, err := repo.Config()
assert.NoError(t, err, "Should be able to read config")
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")
}

View File

@@ -0,0 +1,124 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
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
wantOpts gitea.CreateRepoOption
wantErr bool
errContains string
}{
{
name: "create repo with sha1 object format",
args: []string{"--name", fmt.Sprintf("test-sha1-%d", timestamp), "--object-format", "sha1"},
wantOpts: gitea.CreateRepoOption{
Name: fmt.Sprintf("test-sha1-%d", timestamp),
ObjectFormatName: "sha1",
},
wantErr: false,
},
{
name: "create repo with sha256 object format",
args: []string{"--name", fmt.Sprintf("test-sha256-%d", timestamp), "--object-format", "sha256"},
wantOpts: gitea.CreateRepoOption{
Name: fmt.Sprintf("test-sha256-%d", timestamp),
ObjectFormatName: "sha256",
},
wantErr: false,
},
{
name: "create repo with invalid object format",
args: []string{"--name", fmt.Sprintf("test-invalid-%d", timestamp), "--object-format", "invalid"},
wantErr: true,
errContains: "invalid object format",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reposCmd := &cli.Command{
Name: "repos",
Commands: []*cli.Command{&repos.CmdRepoCreate},
}
args := append([]string{"repos", "create"}, tt.args...)
args = append(args, "--login", login.Name)
err := reposCmd.Run(context.Background(), args)
if tt.wantErr {
assert.Error(t, err)
if tt.errContains != "" {
assert.Contains(t, err.Error(), tt.errContains)
}
return
}
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)
}
})
})
}
}