mirror of
https://github.com/shokinn/hosts-go.git
synced 2025-08-23 08:33:02 +00:00
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.
This commit is contained in:
commit
d66ec51ebd
12 changed files with 1747 additions and 0 deletions
398
tests/models_test.go
Normal file
398
tests/models_test.go
Normal file
|
@ -0,0 +1,398 @@
|
|||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue