Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: switch to CheckType enum #7

Merged
merged 1 commit into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/portpatrol/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/containeroo/portpatrol/internal/runner"
)

const version = "0.4.4"
const version = "0.4.5"

// run is the main function of the application
func run(ctx context.Context, getEnv func(string) string, output io.Writer) error {
Expand Down
4 changes: 2 additions & 2 deletions cmd/portpatrol/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func TestRun(t *testing.T) {
t.Error("Expected error, got none")
}

expected := "configuration error: unsupported check type: invalid"
expected := "configuration error: invalid check type from environment: unsupported check type: invalid"
if err.Error() != expected {
t.Errorf("Expected error to contain %q, got %q", expected, err.Error())
}
Expand Down Expand Up @@ -237,7 +237,7 @@ func TestRun(t *testing.T) {
t.Error("Expected error, got none")
}

expected := "configuration error: could not infer check type for address htp://localhost:8080: unsupported scheme: htp"
expected := "configuration error: could not infer check type from address htp://localhost:8080: unsupported check type: htp"
if err.Error() != expected {
t.Errorf("Expected error to contain %q, got %q", expected, err.Error())
}
Expand Down
67 changes: 28 additions & 39 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ import (
"time"
)

// SupportedCheckTypes maps check types to their supported schemes.
var SupportedCheckTypes = map[string][]string{
"http": {"http", "https"},
"tcp": {"tcp"},
"icmp": {"icmp"},
// CheckType is an enumeration that represents the type of check being performed.
type CheckType int

const (
TCP CheckType = iota // TCP represents a check over the TCP protocol.
HTTP // HTTP represents a check over the HTTP protocol.
ICMP // ICMP represents a check using the ICMP protocol (ping).
)

// String returns the string representation of the CheckType.
func (c CheckType) String() string {
return [...]string{"TCP", "HTTP", "ICMP"}[c]
}

// Checker is an interface that defines methods to perform a check.
Expand All @@ -21,47 +28,29 @@ type Checker interface {
}

// Factory function that returns the appropriate Checker based on checkType
func NewChecker(checkType, name, address string, timeout time.Duration, getEnv func(string) string) (Checker, error) {
func NewChecker(checkType CheckType, name, address string, timeout time.Duration, getEnv func(string) string) (Checker, error) {
switch checkType {
case "http", "https":
// HTTP and HTTPS checkers may need environment variables for proxy settings, etc.
case HTTP: // HTTP and HTTPS checkers may need environment variables for proxy settings, etc.
return NewHTTPChecker(name, address, timeout, getEnv)
case "tcp":
// TCP checkers may not need environment variables
case TCP: // TCP checkers may not need environment variables
return NewTCPChecker(name, address, timeout)
case "icmp":
// ICMP checkers may have a different timeout logic
case ICMP: // ICMP checkers may have a different timeout logic
return NewICMPChecker(name, address, timeout, getEnv)
default:
return nil, fmt.Errorf("unsupported check type: %s", checkType)
return nil, fmt.Errorf("unsupported check type: %d", checkType)
}
}

// IsValidCheckType validates if the check type is supported.
func IsValidCheckType(checkType string) bool {
_, exists := SupportedCheckTypes[checkType]

return exists
}

// InferCheckType infers the check type based on the scheme of the target address.
// It returns an empty string and no error if no scheme is provided.
// If an unsupported scheme is provided, it returns an error.
func InferCheckType(address string) (string, error) {
scheme, _ := extractScheme(address)
if scheme == "" {
return "", nil
}

scheme = strings.ToLower(scheme) // Normalize the scheme to lowercase

for checkType, schemes := range SupportedCheckTypes {
for _, s := range schemes {
if s == scheme {
return checkType, nil
}
}
// GetCheckTypeFromString converts a string to a CheckType enum.
func GetCheckTypeFromString(checkTypeStr string) (CheckType, error) {
switch strings.ToLower(checkTypeStr) {
case "http", "https":
return HTTP, nil
case "tcp":
return TCP, nil
case "icmp":
return ICMP, nil
default:
return -1, fmt.Errorf("unsupported check type: %s", checkTypeStr)
}

return "", fmt.Errorf("unsupported scheme: %s", scheme)
}
117 changes: 28 additions & 89 deletions internal/checker/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
t.Run("Valid HTTP checker", func(t *testing.T) {
t.Parallel()

check, err := NewChecker("http", "example", "http://example.com", 5*time.Second, func(s string) string {
check, err := NewChecker(HTTP, "example", "http://example.com", 5*time.Second, func(s string) string {
return ""
})
if err != nil {
Expand All @@ -27,7 +27,7 @@
t.Run("Valid TCP checker", func(t *testing.T) {
t.Parallel()

check, err := NewChecker("tcp", "example", "example.com:80", 5*time.Second, func(s string) string {
check, err := NewChecker(TCP, "example", "example.com:80", 5*time.Second, func(s string) string {
return ""
})
if err != nil {
Expand All @@ -43,7 +43,7 @@
t.Run("Valid ICMP checker", func(t *testing.T) {
t.Parallel()

check, err := NewChecker("icmp", "example", "example.com", 5*time.Second, func(s string) string {
check, err := NewChecker(ICMP, "example", "example.com", 5*time.Second, func(s string) string {
return ""
})
if err != nil {
Expand All @@ -59,130 +59,69 @@
t.Run("Invalid checker type", func(t *testing.T) {
t.Parallel()

_, err := NewChecker("invalid", "example", "example.com", 5*time.Second, func(s string) string {
_, err := NewChecker(8, "example", "example.com", 5*time.Second, func(s string) string {
return ""
})
if err == nil {
t.Fatal("expected an error, got none")
}

expected := "unsupported check type: invalid"
expected := "unsupported check type: 8"
if err.Error() != expected {
t.Errorf("expected error to be %q, got %q", expected, err.Error())
}
})
}

func TestIsValidCheckType(t *testing.T) {
func TestGetCheckTypeString(t *testing.T) {
t.Parallel()

t.Run("Valid TCP Check Type", func(t *testing.T) {
t.Run("Check type string (enum)", func(t *testing.T) {
t.Parallel()

if isValid := IsValidCheckType("tcp"); !isValid {
t.Errorf("expected true for check type 'tcp', got false")
if HTTP.String() != "HTTP" {
t.Fatalf("expected 'HTTP', got %q", HTTP.String())
}
})

t.Run("Valid HTTP Check Type", func(t *testing.T) {
t.Parallel()

if isValid := IsValidCheckType("http"); !isValid {
t.Errorf("expected true for check type 'http', got false")
}
})

t.Run("Invalid Check Type", func(t *testing.T) {
t.Parallel()

if isValid := IsValidCheckType("invalid"); isValid {
t.Errorf("expected false for check type 'invalid', got true")
}
})

t.Run("Empty Check Type", func(t *testing.T) {
t.Parallel()

if isValid := IsValidCheckType(""); isValid {
t.Errorf("expected false for empty check type, got true")
}
})

t.Run("Random String Check Type", func(t *testing.T) {
t.Parallel()

if isValid := IsValidCheckType("random"); isValid {
t.Errorf("expected false for check type 'random', got true")
}
})
}

func TestInferCheckType(t *testing.T) {
t.Parallel()

t.Run("HTTP scheme", func(t *testing.T) {
t.Parallel()

checkType, err := InferCheckType("http://example.com")
if err != nil {
t.Fatalf("expected no error, got %q", err)
if TCP.String() != "TCP" {
t.Fatalf("expected 'TCP', got %q", TCP.String())
}

if checkType != "http" {
t.Fatalf("expected 'http', got %q", checkType)
if ICMP.String() != "ICMP" {
t.Fatalf("expected 'ICMP', got %q", ICMP.String())
}
})

t.Run("TCP scheme", func(t *testing.T) {
t.Parallel()

checkType, err := InferCheckType("tcp://example.com")
t.Run("Check type string (func)", func(t *testing.T) {
want := HTTP
got, err := GetCheckTypeFromString("http")
if err != nil {
t.Fatalf("expected no error, got %q", err)
}

if checkType != "tcp" {
t.Fatalf("expected 'tcp', got %q", checkType)
if want != got {
t.Fatalf("expected %q, got %q", want, got)
}
})

t.Run("ICMP scheme", func(t *testing.T) {
t.Parallel()

checkType, err := InferCheckType("icmp://host.example.com")
want = TCP
got, err = GetCheckTypeFromString("tcp")
if err != nil {
t.Fatalf("expected no error, got %q", err)
}

if checkType != "icmp" {
t.Fatalf("expected 'http', got %q", checkType)
if want != got {
t.Fatalf("expected %q, got %q", want, got)
}
})

t.Run("No scheme", func(t *testing.T) {
t.Parallel()

checkType, err := InferCheckType("example.com:80")
want = ICMP
got, err = GetCheckTypeFromString("icmp")
if err != nil {
t.Fatalf("expected no error, got %q", err)
}

if checkType != "" {
t.Fatalf("expected 'tcp', got %q", checkType)
if want != got {
t.Fatalf("expected %q, got %q", want, got)
}
})

t.Run("Unsupported scheme", func(t *testing.T) {
t.Parallel()

_, err := InferCheckType("ftp://example.com")
want = -1

Check failure on line 121 in internal/checker/checker_test.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to want (ineffassign)
got, err = GetCheckTypeFromString("invalid")

Check failure on line 122 in internal/checker/checker_test.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to got (ineffassign)
if err == nil {
t.Fatal("expected an error, got none")
}

expected := "unsupported scheme: ftp"
if err.Error() != expected {
t.Errorf("expected error to be %q, got %q", expected, err.Error())
}
})
}
17 changes: 0 additions & 17 deletions internal/checker/utils.go

This file was deleted.

77 changes: 0 additions & 77 deletions internal/checker/utils_test.go

This file was deleted.

Loading