mirror of
https://github.com/shokinn/hosts-go.git
synced 2025-08-23 08:33:02 +00:00
- 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.
398 lines
9.1 KiB
Go
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)
|
|
}
|
|
})
|
|
}
|
|
}
|