hosts-go/tests/models_test.go
phg d66ec51ebd feat: Initialize hosts-go project with foundational structure and core functionality
- Created activeContext.md and productContext.md to outline project goals and current focus.
- Established progress.md to track project milestones and tasks.
- Developed projectbrief.md detailing application overview, requirements, and directory structure.
- Documented systemPatterns.md to describe architecture and design patterns used.
- Compiled techContext.md to specify technologies and development setup.
- Implemented comprehensive unit tests in models_test.go for HostEntry and HostsFile functionalities.
2025-08-12 22:41:33 +02:00

398 lines
9.1 KiB
Go

package tests
import (
"testing"
"hosts-go/internal/core"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewHostEntry(t *testing.T) {
tests := []struct {
name string
ip string
hostname string
expectError bool
errorMsg string
}{
{
name: "valid IPv4 entry",
ip: "192.168.1.1",
hostname: "example.com",
expectError: false,
},
{
name: "valid IPv6 entry",
ip: "2001:db8::1",
hostname: "example.com",
expectError: false,
},
{
name: "empty IP",
ip: "",
hostname: "example.com",
expectError: true,
errorMsg: "IP address cannot be empty",
},
{
name: "empty hostname",
ip: "192.168.1.1",
hostname: "",
expectError: true,
errorMsg: "hostname cannot be empty",
},
{
name: "invalid IP",
ip: "999.999.999.999",
hostname: "example.com",
expectError: true,
errorMsg: "invalid IP address",
},
{
name: "invalid hostname",
ip: "192.168.1.1",
hostname: "-invalid.com",
expectError: true,
errorMsg: "hostname cannot start or end with hyphen",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
entry, err := core.NewHostEntry(tt.ip, tt.hostname)
if tt.expectError {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.errorMsg)
assert.Nil(t, entry)
} else {
assert.NoError(t, err)
assert.NotNil(t, entry)
assert.Equal(t, tt.ip, entry.IP)
assert.Equal(t, tt.hostname, entry.Hostname)
assert.True(t, entry.Active)
assert.Empty(t, entry.Aliases)
assert.Empty(t, entry.Comment)
}
})
}
}
func TestHostEntry_AddAlias(t *testing.T) {
entry, err := core.NewHostEntry("192.168.1.1", "example.com")
require.NoError(t, err)
tests := []struct {
name string
alias string
expectError bool
errorMsg string
}{
{
name: "valid alias",
alias: "www.example.com",
expectError: false,
},
{
name: "another valid alias",
alias: "api.example.com",
expectError: false,
},
{
name: "duplicate alias",
alias: "www.example.com",
expectError: true,
errorMsg: "alias 'www.example.com' already exists",
},
{
name: "invalid alias",
alias: "-invalid.com",
expectError: true,
errorMsg: "invalid alias",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := entry.AddAlias(tt.alias)
if tt.expectError {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.errorMsg)
} else {
assert.NoError(t, err)
assert.Contains(t, entry.Aliases, tt.alias)
}
})
}
}
func TestHostEntry_AllHostnames(t *testing.T) {
entry, err := core.NewHostEntry("192.168.1.1", "example.com")
require.NoError(t, err)
// Test with no aliases
hostnames := entry.AllHostnames()
assert.Equal(t, []string{"example.com"}, hostnames)
// Add aliases and test
require.NoError(t, entry.AddAlias("www.example.com"))
require.NoError(t, entry.AddAlias("api.example.com"))
hostnames = entry.AllHostnames()
expected := []string{"example.com", "www.example.com", "api.example.com"}
assert.Equal(t, expected, hostnames)
}
func TestHostEntry_String(t *testing.T) {
tests := []struct {
name string
setup func() *core.HostEntry
expected string
}{
{
name: "basic entry",
setup: func() *core.HostEntry {
entry, _ := core.NewHostEntry("192.168.1.1", "example.com")
return entry
},
expected: "192.168.1.1\texample.com",
},
{
name: "entry with comment",
setup: func() *core.HostEntry {
entry, _ := core.NewHostEntry("192.168.1.1", "example.com")
entry.Comment = "development server"
return entry
},
expected: "192.168.1.1\texample.com\t# development server",
},
{
name: "entry with aliases",
setup: func() *core.HostEntry {
entry, _ := core.NewHostEntry("192.168.1.1", "example.com")
entry.AddAlias("www.example.com")
entry.AddAlias("api.example.com")
return entry
},
expected: "192.168.1.1\texample.com\twww.example.com\tapi.example.com",
},
{
name: "inactive entry",
setup: func() *core.HostEntry {
entry, _ := core.NewHostEntry("192.168.1.1", "example.com")
entry.Active = false
return entry
},
expected: "# 192.168.1.1\texample.com",
},
{
name: "complete entry",
setup: func() *core.HostEntry {
entry, _ := core.NewHostEntry("192.168.1.1", "example.com")
entry.AddAlias("www.example.com")
entry.Comment = "test server"
return entry
},
expected: "192.168.1.1\texample.com\twww.example.com\t# test server",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
entry := tt.setup()
result := entry.String()
assert.Equal(t, tt.expected, result)
})
}
}
func TestHostsFile_AddEntry(t *testing.T) {
hostsFile := core.NewHostsFile()
entry, err := core.NewHostEntry("192.168.1.1", "example.com")
require.NoError(t, err)
err = hostsFile.AddEntry(entry)
assert.NoError(t, err)
assert.Len(t, hostsFile.Entries, 1)
assert.Equal(t, entry, hostsFile.Entries[0])
}
func TestHostsFile_FindEntry(t *testing.T) {
hostsFile := core.NewHostsFile()
entry1, _ := core.NewHostEntry("192.168.1.1", "example.com")
entry1.AddAlias("www.example.com")
entry2, _ := core.NewHostEntry("192.168.1.2", "test.com")
hostsFile.AddEntry(entry1)
hostsFile.AddEntry(entry2)
tests := []struct {
name string
hostname string
expected *core.HostEntry
}{
{
name: "find by primary hostname",
hostname: "example.com",
expected: entry1,
},
{
name: "find by alias",
hostname: "www.example.com",
expected: entry1,
},
{
name: "find second entry",
hostname: "test.com",
expected: entry2,
},
{
name: "not found",
hostname: "notfound.com",
expected: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := hostsFile.FindEntry(tt.hostname)
assert.Equal(t, tt.expected, result)
})
}
}
func TestHostsFile_RemoveEntry(t *testing.T) {
hostsFile := core.NewHostsFile()
entry1, _ := core.NewHostEntry("192.168.1.1", "example.com")
entry1.AddAlias("www.example.com")
entry2, _ := core.NewHostEntry("192.168.1.2", "test.com")
hostsFile.AddEntry(entry1)
hostsFile.AddEntry(entry2)
tests := []struct {
name string
hostname string
expectedResult bool
remainingCount int
}{
{
name: "remove by primary hostname",
hostname: "example.com",
expectedResult: true,
remainingCount: 1,
},
{
name: "remove non-existent",
hostname: "notfound.com",
expectedResult: false,
remainingCount: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := hostsFile.RemoveEntry(tt.hostname)
assert.Equal(t, tt.expectedResult, result)
assert.Len(t, hostsFile.Entries, tt.remainingCount)
})
}
}
func TestHostsFile_ActiveEntries(t *testing.T) {
hostsFile := core.NewHostsFile()
entry1, _ := core.NewHostEntry("192.168.1.1", "example.com")
entry2, _ := core.NewHostEntry("192.168.1.2", "test.com")
entry2.Active = false // Inactive entry
entry3, _ := core.NewHostEntry("192.168.1.3", "active.com")
hostsFile.AddEntry(entry1)
hostsFile.AddEntry(entry2)
hostsFile.AddEntry(entry3)
activeEntries := hostsFile.ActiveEntries()
assert.Len(t, activeEntries, 2)
assert.Contains(t, activeEntries, entry1)
assert.Contains(t, activeEntries, entry3)
assert.NotContains(t, activeEntries, entry2)
}
func TestValidateHostname(t *testing.T) {
tests := []struct {
name string
hostname string
expectError bool
errorMsg string
}{
{
name: "valid simple hostname",
hostname: "example",
expectError: false,
},
{
name: "valid domain",
hostname: "example.com",
expectError: false,
},
{
name: "valid subdomain",
hostname: "www.example.com",
expectError: false,
},
{
name: "valid with numbers",
hostname: "server1.example.com",
expectError: false,
},
{
name: "valid with hyphens",
hostname: "api-server.example.com",
expectError: false,
},
{
name: "empty hostname",
hostname: "",
expectError: true,
errorMsg: "hostname cannot be empty",
},
{
name: "starts with hyphen",
hostname: "-invalid.com",
expectError: true,
errorMsg: "hostname cannot start or end with hyphen",
},
{
name: "ends with hyphen",
hostname: "invalid-.com",
expectError: true,
errorMsg: "hostname cannot start or end with hyphen",
},
{
name: "too long hostname",
hostname: string(make([]byte, 255)), // 255 characters
expectError: true,
errorMsg: "hostname too long",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test through NewHostEntry which calls validateHostname
_, err := core.NewHostEntry("192.168.1.1", tt.hostname)
if tt.expectError {
assert.Error(t, err)
assert.Contains(t, err.Error(), tt.errorMsg)
} else {
assert.NoError(t, err)
}
})
}
}