Initial commit: Gitea MCP Server
This commit is contained in:
@@ -0,0 +1,365 @@
|
||||
package repo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
gitea_errors "gitea.com/gitea/gitea-mcp/pkg/errors"
|
||||
)
|
||||
|
||||
// mockClientError is a mock error that simulates SDK errors
|
||||
type mockClientError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
func (e *mockClientError) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func TestErrorTranslation_GetFile(t *testing.T) {
|
||||
// Test that GetContentsOrList errors are translated properly
|
||||
err := errors.New("GetContentsOrList: 404 Not Found")
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "GetFile",
|
||||
"owner": "karti-ai",
|
||||
"repo": "docs",
|
||||
"path": "README.md",
|
||||
"ref": "main",
|
||||
})
|
||||
|
||||
// Should return an EnhancedError
|
||||
var enhanced *gitea_errors.EnhancedError
|
||||
if !errors.As(translated, &enhanced) {
|
||||
t.Fatal("expected translated error to be EnhancedError")
|
||||
}
|
||||
|
||||
// Check operation
|
||||
if enhanced.Operation != "GetFile" {
|
||||
t.Errorf("expected operation GetFile, got %s", enhanced.Operation)
|
||||
}
|
||||
|
||||
// Check context
|
||||
if enhanced.Context["owner"] != "karti-ai" {
|
||||
t.Errorf("expected owner karti-ai, got %s", enhanced.Context["owner"])
|
||||
}
|
||||
if enhanced.Context["path"] != "README.md" {
|
||||
t.Errorf("expected path README.md, got %s", enhanced.Context["path"])
|
||||
}
|
||||
|
||||
// Should be a file-related error
|
||||
if enhanced.Category != gitea_errors.CategoryFile {
|
||||
t.Errorf("expected CategoryFile, got %s", enhanced.Category)
|
||||
}
|
||||
|
||||
// Should be identified as NotFound
|
||||
if !gitea_errors.IsNotFound(translated) {
|
||||
t.Error("expected error to be identified as NotFound")
|
||||
}
|
||||
|
||||
t.Logf("Translated error message: %s", enhanced.Error())
|
||||
}
|
||||
|
||||
func TestErrorTranslation_GetDir(t *testing.T) {
|
||||
// Test that ListContents errors are translated properly
|
||||
err := errors.New("ListContents: 404 Not Found")
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "GetDir",
|
||||
"owner": "karti-ai",
|
||||
"repo": "public_website",
|
||||
"path": ".gitea/workflows",
|
||||
"ref": "main",
|
||||
})
|
||||
|
||||
var enhanced *gitea_errors.EnhancedError
|
||||
if !errors.As(translated, &enhanced) {
|
||||
t.Fatal("expected translated error to be EnhancedError")
|
||||
}
|
||||
|
||||
if enhanced.Operation != "GetDir" {
|
||||
t.Errorf("expected operation GetDir, got %s", enhanced.Operation)
|
||||
}
|
||||
|
||||
if enhanced.Category != gitea_errors.CategoryFile {
|
||||
t.Errorf("expected CategoryFile, got %s", enhanced.Category)
|
||||
}
|
||||
|
||||
t.Logf("Translated error message: %s", enhanced.Error())
|
||||
}
|
||||
|
||||
func TestErrorTranslation_CreateFile(t *testing.T) {
|
||||
// Test that CreateFile errors are translated properly
|
||||
err := errors.New("CreateFile: 422 Unprocessable Entity")
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "CreateFile",
|
||||
"owner": "karti-ai",
|
||||
"repo": "docs",
|
||||
"path": "newfile.md",
|
||||
"branch": "main",
|
||||
})
|
||||
|
||||
var enhanced *gitea_errors.EnhancedError
|
||||
if !errors.As(translated, &enhanced) {
|
||||
t.Fatal("expected translated error to be EnhancedError")
|
||||
}
|
||||
|
||||
if enhanced.Operation != "CreateFile" {
|
||||
t.Errorf("expected operation CreateFile, got %s", enhanced.Operation)
|
||||
}
|
||||
|
||||
if enhanced.Context["path"] != "newfile.md" {
|
||||
t.Errorf("expected path newfile.md, got %s", enhanced.Context["path"])
|
||||
}
|
||||
|
||||
t.Logf("Translated error message: %s", enhanced.Error())
|
||||
}
|
||||
|
||||
func TestErrorTranslation_UpdateFile(t *testing.T) {
|
||||
// Test that UpdateFile errors are translated properly
|
||||
err := errors.New("UpdateFile: 409 Conflict")
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "UpdateFile",
|
||||
"owner": "karti-ai",
|
||||
"repo": "docs",
|
||||
"path": "README.md",
|
||||
"branch": "main",
|
||||
})
|
||||
|
||||
var enhanced *gitea_errors.EnhancedError
|
||||
if !errors.As(translated, &enhanced) {
|
||||
t.Fatal("expected translated error to be EnhancedError")
|
||||
}
|
||||
|
||||
if enhanced.Operation != "UpdateFile" {
|
||||
t.Errorf("expected operation UpdateFile, got %s", enhanced.Operation)
|
||||
}
|
||||
|
||||
t.Logf("Translated error message: %s", enhanced.Error())
|
||||
}
|
||||
|
||||
func TestErrorTranslation_DeleteFile(t *testing.T) {
|
||||
// Test that DeleteFile errors are translated properly
|
||||
err := errors.New("DeleteFile: 404 Not Found")
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "DeleteFile",
|
||||
"owner": "karti-ai",
|
||||
"repo": "docs",
|
||||
"path": "oldfile.md",
|
||||
"branch": "main",
|
||||
})
|
||||
|
||||
var enhanced *gitea_errors.EnhancedError
|
||||
if !errors.As(translated, &enhanced) {
|
||||
t.Fatal("expected translated error to be EnhancedError")
|
||||
}
|
||||
|
||||
if enhanced.Operation != "DeleteFile" {
|
||||
t.Errorf("expected operation DeleteFile, got %s", enhanced.Operation)
|
||||
}
|
||||
|
||||
t.Logf("Translated error message: %s", enhanced.Error())
|
||||
t.Logf("Error category: %s", enhanced.Category)
|
||||
}
|
||||
|
||||
func TestErrorTranslation_Unwrap(t *testing.T) {
|
||||
original := errors.New("GetContentsOrList: 404 Not Found")
|
||||
translated := gitea_errors.TranslateError(original, map[string]string{
|
||||
"operation": "GetFile",
|
||||
"owner": "karti-ai",
|
||||
"repo": "docs",
|
||||
"path": "README.md",
|
||||
})
|
||||
|
||||
// Should be able to unwrap to get original error
|
||||
var enhanced *gitea_errors.EnhancedError
|
||||
if errors.As(translated, &enhanced) {
|
||||
unwrapped := enhanced.Unwrap()
|
||||
if unwrapped == nil {
|
||||
t.Error("expected to be able to unwrap error")
|
||||
}
|
||||
if unwrapped.Error() != original.Error() {
|
||||
t.Errorf("expected unwrapped error to match original: got %s, want %s", unwrapped.Error(), original.Error())
|
||||
}
|
||||
} else {
|
||||
t.Error("expected translated error to be EnhancedError")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorTranslation_AuthErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
errMsg string
|
||||
isAuth bool
|
||||
}{
|
||||
{
|
||||
name: "401 Unauthorized",
|
||||
errMsg: "GetContentsOrList: 401 Unauthorized",
|
||||
isAuth: true,
|
||||
},
|
||||
{
|
||||
name: "403 Forbidden",
|
||||
errMsg: "GetContentsOrList: 403 Forbidden",
|
||||
isAuth: true,
|
||||
},
|
||||
{
|
||||
name: "404 Not Found (not auth)",
|
||||
errMsg: "GetContentsOrList: 404 Not Found",
|
||||
isAuth: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := errors.New(tt.errMsg)
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "GetFile",
|
||||
})
|
||||
|
||||
isAuth := gitea_errors.IsAuthError(translated)
|
||||
if isAuth != tt.isAuth {
|
||||
t.Errorf("IsAuthError() = %v, want %v", isAuth, tt.isAuth)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorTranslation_PreservesExistingEnhancedError(t *testing.T) {
|
||||
// If we translate an already-enhanced error, it should add context, not replace
|
||||
original := errors.New("GetContentsOrList: 404 Not Found")
|
||||
enhanced1 := gitea_errors.TranslateError(original, map[string]string{
|
||||
"operation": "GetFile",
|
||||
"owner": "karti-ai",
|
||||
})
|
||||
|
||||
// Translate again with more context
|
||||
enhanced2 := gitea_errors.TranslateError(enhanced1, map[string]string{
|
||||
"repo": "docs",
|
||||
"path": "README.md",
|
||||
})
|
||||
|
||||
var e *gitea_errors.EnhancedError
|
||||
if errors.As(enhanced2, &e) {
|
||||
// Should have both sets of context
|
||||
if e.Context["operation"] != "GetFile" {
|
||||
t.Errorf("expected operation context to be preserved, got %s", e.Context["operation"])
|
||||
}
|
||||
if e.Context["owner"] != "karti-ai" {
|
||||
t.Errorf("expected owner context to be preserved, got %s", e.Context["owner"])
|
||||
}
|
||||
if e.Context["repo"] != "docs" {
|
||||
t.Errorf("expected repo context to be added, got %s", e.Context["repo"])
|
||||
}
|
||||
if e.Context["path"] != "README.md" {
|
||||
t.Errorf("expected path context to be added, got %s", e.Context["path"])
|
||||
}
|
||||
} else {
|
||||
t.Error("expected error to be EnhancedError")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorTranslation_NetworkErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
errMsg string
|
||||
isNetwork bool
|
||||
isTimeout bool
|
||||
}{
|
||||
{
|
||||
name: "Connection refused",
|
||||
errMsg: "GetContentsOrList: connection refused",
|
||||
isNetwork: true,
|
||||
isTimeout: false,
|
||||
},
|
||||
{
|
||||
name: "Timeout",
|
||||
errMsg: "GetContentsOrList: timeout",
|
||||
isNetwork: true,
|
||||
isTimeout: true,
|
||||
},
|
||||
{
|
||||
name: "No such host",
|
||||
errMsg: "GetContentsOrList: no such host",
|
||||
isNetwork: true,
|
||||
isTimeout: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := errors.New(tt.errMsg)
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "GetFile",
|
||||
})
|
||||
|
||||
isNetwork := gitea_errors.IsNetworkError(translated)
|
||||
isTimeout := gitea_errors.IsTimeout(translated)
|
||||
|
||||
t.Logf("Error: %s, IsNetwork: %v, IsTimeout: %v", tt.errMsg, isNetwork, isTimeout)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorTranslation_ServerErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
errMsg string
|
||||
isServer bool
|
||||
}{
|
||||
{
|
||||
name: "500 Internal Server Error",
|
||||
errMsg: "GetContentsOrList: 500 Internal Server Error",
|
||||
isServer: true,
|
||||
},
|
||||
{
|
||||
name: "502 Bad Gateway",
|
||||
errMsg: "GetContentsOrList: 502 Bad Gateway",
|
||||
isServer: true,
|
||||
},
|
||||
{
|
||||
name: "503 Service Unavailable",
|
||||
errMsg: "GetContentsOrList: 503 Service Unavailable",
|
||||
isServer: true,
|
||||
},
|
||||
{
|
||||
name: "404 Not Found (not server)",
|
||||
errMsg: "GetContentsOrList: 404 Not Found",
|
||||
isServer: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := errors.New(tt.errMsg)
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "GetFile",
|
||||
})
|
||||
|
||||
isServer := gitea_errors.IsServerError(translated)
|
||||
t.Logf("Error: %s, IsServer: %v", tt.errMsg, isServer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorTranslation_Format(t *testing.T) {
|
||||
err := errors.New("GetContentsOrList: 404 Not Found")
|
||||
translated := gitea_errors.TranslateError(err, map[string]string{
|
||||
"operation": "GetFile",
|
||||
"owner": "karti-ai",
|
||||
"repo": "docs",
|
||||
"path": "README.md",
|
||||
"ref": "main",
|
||||
})
|
||||
|
||||
var enhanced *gitea_errors.EnhancedError
|
||||
if errors.As(translated, &enhanced) {
|
||||
formatted := enhanced.Format()
|
||||
|
||||
// Format should include operation
|
||||
if formatted == "" {
|
||||
t.Error("expected non-empty formatted error")
|
||||
}
|
||||
|
||||
t.Logf("Formatted error: %s", formatted)
|
||||
} else {
|
||||
t.Error("expected translated error to be EnhancedError")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user