Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
|
|
@ -0,0 +1,252 @@
|
|||
// File Path: monorepo/cloud/maplefile-backend/pkg/security/ipcountryblocker/ipcountryblocker_test.go
|
||||
package ipcountryblocker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config"
|
||||
)
|
||||
|
||||
// testProvider is a test-specific wrapper that allows access to internal fields
|
||||
// of the provider struct for verification in tests. This is a common pattern
|
||||
// when you need to test internal state while keeping the production interface clean.
|
||||
type testProvider struct {
|
||||
Provider // Embedded interface for normal operations
|
||||
internal *provider // Access to internal fields for testing
|
||||
}
|
||||
|
||||
// newTestProvider creates a test provider instance with access to internal fields.
|
||||
// This allows us to verify the internal state in our tests while maintaining
|
||||
// encapsulation in production code.
|
||||
func newTestProvider(cfg *config.Configuration, logger *zap.Logger) testProvider {
|
||||
p := NewProvider(cfg, logger)
|
||||
return testProvider{
|
||||
Provider: p,
|
||||
internal: p.(*provider), // Type assertion to get access to internal fields
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewProvider verifies that the provider is properly initialized with all
|
||||
// required components (database connection, blocked countries map, logger).
|
||||
func TestNewProvider(t *testing.T) {
|
||||
// Setup test configuration with path to test database
|
||||
cfg := &config.Configuration{
|
||||
Security: config.SecurityConfig{
|
||||
GeoLiteDBPath: "../../../static/GeoLite2-Country.mmdb",
|
||||
BannedCountries: []string{"US", "CN"},
|
||||
},
|
||||
}
|
||||
// Initialize logger with JSON output for structured test logs
|
||||
logger, _ := zap.NewDevelopment()
|
||||
|
||||
// Create test provider and verify internal components
|
||||
p := newTestProvider(cfg, logger)
|
||||
assert.NotNil(t, p.Provider, "Provider should not be nil")
|
||||
assert.NotEmpty(t, p.internal.blockedCountries, "Blocked countries map should be initialized")
|
||||
assert.NotNil(t, p.internal.logger, "Logger should be initialized")
|
||||
assert.NotNil(t, p.internal.db, "Database connection should be initialized")
|
||||
defer p.Close() // Ensure cleanup after test
|
||||
}
|
||||
|
||||
// TestProvider_IsBlockedCountry tests the country blocking functionality with
|
||||
// various country codes including edge cases like empty and invalid codes.
|
||||
func TestProvider_IsBlockedCountry(t *testing.T) {
|
||||
provider := setupTestProvider(t)
|
||||
defer provider.Close()
|
||||
|
||||
// Table-driven test cases covering various scenarios
|
||||
tests := []struct {
|
||||
name string
|
||||
country string
|
||||
expected bool
|
||||
}{
|
||||
// Positive test cases - blocked countries
|
||||
{
|
||||
name: "blocked country US",
|
||||
country: "US",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "blocked country CN",
|
||||
country: "CN",
|
||||
expected: true,
|
||||
},
|
||||
// Negative test cases - allowed countries
|
||||
{
|
||||
name: "non-blocked country GB",
|
||||
country: "GB",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "non-blocked country JP",
|
||||
country: "JP",
|
||||
expected: false,
|
||||
},
|
||||
// Edge cases
|
||||
{
|
||||
name: "empty country code",
|
||||
country: "",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "invalid country code",
|
||||
country: "XX",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "lowercase country code", // Tests case sensitivity
|
||||
country: "us",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Run each test case
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := provider.IsBlockedCountry(tt.country)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestProvider_IsBlockedIP verifies IP blocking functionality using real-world
|
||||
// IP addresses, including IPv4, IPv6, and various edge cases.
|
||||
func TestProvider_IsBlockedIP(t *testing.T) {
|
||||
provider := setupTestProvider(t)
|
||||
defer provider.Close()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ip net.IP
|
||||
expected bool
|
||||
}{
|
||||
// Known IP addresses from blocked countries
|
||||
{
|
||||
name: "blocked IP (US - Google DNS)",
|
||||
ip: net.ParseIP("8.8.8.8"), // Google's primary DNS
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "blocked IP (US - Google DNS 2)",
|
||||
ip: net.ParseIP("8.8.4.4"), // Google's secondary DNS
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "blocked IP (CN - Alibaba)",
|
||||
ip: net.ParseIP("223.5.5.5"), // Alibaba DNS
|
||||
expected: true,
|
||||
},
|
||||
// Non-blocked country IPs
|
||||
{
|
||||
name: "non-blocked IP (GB)",
|
||||
ip: net.ParseIP("178.62.1.1"),
|
||||
expected: false,
|
||||
},
|
||||
// Edge cases and special scenarios
|
||||
{
|
||||
name: "nil IP",
|
||||
ip: nil,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "invalid IP format",
|
||||
ip: net.ParseIP("invalid"),
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "IPv6 address",
|
||||
ip: net.ParseIP("2001:4860:4860::8888"), // Google's IPv6 DNS
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := provider.IsBlockedIP(ctx, tt.ip)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestProvider_GetCountryCode verifies the country code lookup functionality
|
||||
// for various IP addresses, including error cases.
|
||||
func TestProvider_GetCountryCode(t *testing.T) {
|
||||
provider := setupTestProvider(t)
|
||||
defer provider.Close()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ip net.IP
|
||||
expected string
|
||||
expectError bool
|
||||
}{
|
||||
// Valid IP addresses with known countries
|
||||
{
|
||||
name: "US IP (Google DNS)",
|
||||
ip: net.ParseIP("8.8.8.8"),
|
||||
expected: "US",
|
||||
expectError: false,
|
||||
},
|
||||
// Error cases
|
||||
{
|
||||
name: "nil IP",
|
||||
ip: nil,
|
||||
expected: "",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "private IP", // RFC 1918 address
|
||||
ip: net.ParseIP("192.168.1.1"),
|
||||
expected: "",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
code, err := provider.GetCountryCode(ctx, tt.ip)
|
||||
if tt.expectError {
|
||||
assert.Error(t, err, "Should return error for invalid IP")
|
||||
assert.Empty(t, code, "Should return empty code on error")
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err, "Should not return error for valid IP")
|
||||
assert.Equal(t, tt.expected, code, "Should return correct country code")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestProvider_Close verifies that the provider properly closes its resources
|
||||
// and subsequent operations fail as expected.
|
||||
func TestProvider_Close(t *testing.T) {
|
||||
provider := setupTestProvider(t)
|
||||
|
||||
// Verify initial close succeeds
|
||||
err := provider.Close()
|
||||
assert.NoError(t, err, "Initial close should succeed")
|
||||
|
||||
// Verify operations fail after close
|
||||
code, err := provider.GetCountryCode(context.Background(), net.ParseIP("8.8.8.8"))
|
||||
assert.Error(t, err, "Operations should fail after close")
|
||||
assert.Empty(t, code, "No data should be returned after close")
|
||||
}
|
||||
|
||||
// setupTestProvider is a helper function that creates a properly configured
|
||||
// provider instance for testing, using the test database path.
|
||||
func setupTestProvider(t *testing.T) Provider {
|
||||
cfg := &config.Configuration{
|
||||
Security: config.SecurityConfig{
|
||||
GeoLiteDBPath: "../../../static/GeoLite2-Country.mmdb",
|
||||
BannedCountries: []string{"US", "CN"},
|
||||
},
|
||||
}
|
||||
logger, _ := zap.NewDevelopment()
|
||||
return NewProvider(cfg, logger)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue