mirror of
				https://github.com/shokinn/hosts-go.git
				synced 2025-11-04 04:28:34 +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