summaryrefslogtreecommitdiff
path: root/internal/errors/errors.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-19 20:29:21 +0300
committerPaul Buetow <paul@buetow.org>2025-06-19 20:29:21 +0300
commit2f20d0eacfbc16111fa273f4d6cac339cc61ef51 (patch)
tree43057356276c3971e410d21c909de69eaee0f605 /internal/errors/errors.go
parent1a9259eb9a10202c28dbd959e6cfa2e2fcf3e064 (diff)
Implement Phase 1: Foundation for improved maintainability and testability
- Add standardized error handling package (internal/errors) - Sentinel errors for common conditions - Error wrapping and chaining support - MultiError for batch operations - Add comprehensive test utilities package (internal/testutil) - File/directory test helpers - Assertion functions for common test patterns - Mock SSH server for integration testing - Test data generators - Add unit tests for core packages - Protocol package: delimiter validation and usage tests - Config package: comprehensive configuration tests - Discovery package: server discovery method tests - IO/FS package: stats tracking and grep processor tests All tests passing. This establishes a solid foundation for further improvements. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'internal/errors/errors.go')
-rw-r--r--internal/errors/errors.go137
1 files changed, 137 insertions, 0 deletions
diff --git a/internal/errors/errors.go b/internal/errors/errors.go
new file mode 100644
index 0000000..bb53efd
--- /dev/null
+++ b/internal/errors/errors.go
@@ -0,0 +1,137 @@
+package errors
+
+import (
+ "errors"
+ "fmt"
+)
+
+// Sentinel errors for common error conditions
+var (
+ // Connection errors
+ ErrConnectionFailed = errors.New("connection failed")
+ ErrConnectionTimeout = errors.New("connection timeout")
+ ErrConnectionRefused = errors.New("connection refused")
+ ErrTooManyConnections = errors.New("too many connections")
+
+ // Authentication/Permission errors
+ ErrPermissionDenied = errors.New("permission denied")
+ ErrAuthenticationFailed = errors.New("authentication failed")
+ ErrUnauthorized = errors.New("unauthorized")
+ ErrInvalidCredentials = errors.New("invalid credentials")
+
+ // Configuration errors
+ ErrInvalidConfig = errors.New("invalid configuration")
+ ErrMissingConfig = errors.New("missing configuration")
+ ErrConfigValidation = errors.New("configuration validation failed")
+
+ // File/IO errors
+ ErrFileNotFound = errors.New("file not found")
+ ErrFileAccessDenied = errors.New("file access denied")
+ ErrInvalidPath = errors.New("invalid path")
+ ErrReadFailed = errors.New("read failed")
+ ErrWriteFailed = errors.New("write failed")
+
+ // Protocol errors
+ ErrInvalidProtocol = errors.New("invalid protocol")
+ ErrProtocolMismatch = errors.New("protocol version mismatch")
+ ErrInvalidCommand = errors.New("invalid command")
+ ErrInvalidQuery = errors.New("invalid query")
+
+ // Resource errors
+ ErrResourceExhausted = errors.New("resource exhausted")
+ ErrBufferFull = errors.New("buffer full")
+ ErrTimeout = errors.New("operation timeout")
+
+ // General errors
+ ErrInvalidArgument = errors.New("invalid argument")
+ ErrNotImplemented = errors.New("not implemented")
+ ErrInternal = errors.New("internal error")
+)
+
+// Error wrapping functions
+
+// Wrap wraps an error with additional context
+func Wrap(err error, msg string) error {
+ if err == nil {
+ return nil
+ }
+ return fmt.Errorf("%s: %w", msg, err)
+}
+
+// Wrapf wraps an error with formatted context
+func Wrapf(err error, format string, args ...interface{}) error {
+ if err == nil {
+ return nil
+ }
+ return fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)
+}
+
+// New creates a new error with formatted message
+func New(format string, args ...interface{}) error {
+ return fmt.Errorf(format, args...)
+}
+
+// Is checks if an error is of a specific type
+func Is(err, target error) bool {
+ return errors.Is(err, target)
+}
+
+// As attempts to extract a specific error type
+func As(err error, target interface{}) bool {
+ return errors.As(err, target)
+}
+
+// Unwrap returns the wrapped error
+func Unwrap(err error) error {
+ return errors.Unwrap(err)
+}
+
+// Multi-error support for operations that can have multiple failures
+
+// MultiError represents multiple errors
+type MultiError struct {
+ errors []error
+}
+
+// NewMultiError creates a new MultiError
+func NewMultiError() *MultiError {
+ return &MultiError{
+ errors: make([]error, 0),
+ }
+}
+
+// Add adds an error to the MultiError
+func (m *MultiError) Add(err error) {
+ if err != nil {
+ m.errors = append(m.errors, err)
+ }
+}
+
+// HasErrors returns true if there are any errors
+func (m *MultiError) HasErrors() bool {
+ return len(m.errors) > 0
+}
+
+// Error implements the error interface
+func (m *MultiError) Error() string {
+ if len(m.errors) == 0 {
+ return ""
+ }
+ if len(m.errors) == 1 {
+ return m.errors[0].Error()
+ }
+ return fmt.Sprintf("multiple errors occurred: %v", m.errors)
+}
+
+// Errors returns all collected errors
+func (m *MultiError) Errors() []error {
+ return m.errors
+}
+
+// ErrorOrNil returns nil if no errors, otherwise returns the MultiError
+func (m *MultiError) ErrorOrNil() error {
+ if m.HasErrors() {
+ return m
+ }
+ return nil
+} \ No newline at end of file