package home import ( "net" "os" "testing" "time" "github.com/AdguardTeam/AdGuardHome/internal/dhcpd" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestClients(t *testing.T) { clients := clientsContainer{} clients.testing = true clients.Init(nil, nil, nil) t.Run("add_success", func(t *testing.T) { c := &Client{ IDs: []string{"1.1.1.1", "1:2:3::4", "aa:aa:aa:aa:aa:aa"}, Name: "client1", } ok, err := clients.Add(c) require.Nil(t, err) assert.True(t, ok) c = &Client{ IDs: []string{"2.2.2.2"}, Name: "client2", } ok, err = clients.Add(c) require.Nil(t, err) assert.True(t, ok) c, ok = clients.Find("1.1.1.1") require.True(t, ok) assert.Equal(t, "client1", c.Name) c, ok = clients.Find("1:2:3::4") require.True(t, ok) assert.Equal(t, "client1", c.Name) c, ok = clients.Find("2.2.2.2") require.True(t, ok) assert.Equal(t, "client2", c.Name) assert.False(t, clients.Exists("1.2.3.4", ClientSourceHostsFile)) assert.True(t, clients.Exists("1.1.1.1", ClientSourceHostsFile)) assert.True(t, clients.Exists("2.2.2.2", ClientSourceHostsFile)) }) t.Run("add_fail_name", func(t *testing.T) { ok, err := clients.Add(&Client{ IDs: []string{"1.2.3.5"}, Name: "client1", }) require.Nil(t, err) assert.False(t, ok) }) t.Run("add_fail_ip", func(t *testing.T) { ok, err := clients.Add(&Client{ IDs: []string{"2.2.2.2"}, Name: "client3", }) require.NotNil(t, err) assert.False(t, ok) }) t.Run("update_fail_name", func(t *testing.T) { err := clients.Update("client3", &Client{ IDs: []string{"1.2.3.0"}, Name: "client3", }) require.NotNil(t, err) err = clients.Update("client3", &Client{ IDs: []string{"1.2.3.0"}, Name: "client2", }) assert.NotNil(t, err) }) t.Run("update_fail_ip", func(t *testing.T) { err := clients.Update("client1", &Client{ IDs: []string{"2.2.2.2"}, Name: "client1", }) assert.NotNil(t, err) }) t.Run("update_success", func(t *testing.T) { err := clients.Update("client1", &Client{ IDs: []string{"1.1.1.2"}, Name: "client1", }) require.Nil(t, err) assert.False(t, clients.Exists("1.1.1.1", ClientSourceHostsFile)) assert.True(t, clients.Exists("1.1.1.2", ClientSourceHostsFile)) err = clients.Update("client1", &Client{ IDs: []string{"1.1.1.2"}, Name: "client1-renamed", UseOwnSettings: true, }) require.Nil(t, err) c, ok := clients.Find("1.1.1.2") require.True(t, ok) assert.Equal(t, "client1-renamed", c.Name) assert.True(t, c.UseOwnSettings) nilCli, ok := clients.list["client1"] require.False(t, ok) assert.Nil(t, nilCli) require.Len(t, c.IDs, 1) assert.Equal(t, "1.1.1.2", c.IDs[0]) }) t.Run("del_success", func(t *testing.T) { ok := clients.Del("client1-renamed") require.True(t, ok) assert.False(t, clients.Exists("1.1.1.2", ClientSourceHostsFile)) }) t.Run("del_fail", func(t *testing.T) { ok := clients.Del("client3") assert.False(t, ok) }) t.Run("addhost_success", func(t *testing.T) { ok, err := clients.AddHost("1.1.1.1", "host", ClientSourceARP) require.Nil(t, err) assert.True(t, ok) ok, err = clients.AddHost("1.1.1.1", "host2", ClientSourceARP) require.Nil(t, err) assert.True(t, ok) ok, err = clients.AddHost("1.1.1.1", "host3", ClientSourceHostsFile) require.Nil(t, err) assert.True(t, ok) assert.True(t, clients.Exists("1.1.1.1", ClientSourceHostsFile)) }) t.Run("addhost_fail", func(t *testing.T) { ok, err := clients.AddHost("1.1.1.1", "host1", ClientSourceRDNS) require.Nil(t, err) assert.False(t, ok) }) } func TestClientsWhois(t *testing.T) { clients := clientsContainer{ testing: true, } clients.Init(nil, nil, nil) whois := &RuntimeClientWhoisInfo{ Country: "AU", Orgname: "Example Org", } t.Run("new_client", func(t *testing.T) { clients.SetWhoisInfo("1.1.1.255", whois) require.NotNil(t, clients.ipToRC["1.1.1.255"]) h := clients.ipToRC["1.1.1.255"] require.NotNil(t, h) assert.Equal(t, h.WhoisInfo, whois) }) t.Run("existing_auto-client", func(t *testing.T) { ok, err := clients.AddHost("1.1.1.1", "host", ClientSourceRDNS) require.Nil(t, err) assert.True(t, ok) clients.SetWhoisInfo("1.1.1.1", whois) require.NotNil(t, clients.ipToRC["1.1.1.1"]) h := clients.ipToRC["1.1.1.1"] require.NotNil(t, h) assert.Equal(t, h.WhoisInfo, whois) }) t.Run("can't_set_manually-added", func(t *testing.T) { ok, err := clients.Add(&Client{ IDs: []string{"1.1.1.2"}, Name: "client1", }) require.Nil(t, err) assert.True(t, ok) clients.SetWhoisInfo("1.1.1.2", whois) require.Nil(t, clients.ipToRC["1.1.1.2"]) assert.True(t, clients.Del("client1")) }) } func TestClientsAddExisting(t *testing.T) { clients := clientsContainer{ testing: true, } clients.Init(nil, nil, nil) t.Run("simple", func(t *testing.T) { // Add a client. ok, err := clients.Add(&Client{ IDs: []string{"1.1.1.1", "1:2:3::4", "aa:aa:aa:aa:aa:aa", "2.2.2.0/24"}, Name: "client1", }) require.Nil(t, err) assert.True(t, ok) // Now add an auto-client with the same IP. ok, err = clients.AddHost("1.1.1.1", "test", ClientSourceRDNS) require.Nil(t, err) assert.True(t, ok) }) t.Run("complicated", func(t *testing.T) { testIP := net.IP{1, 2, 3, 4} // First, init a DHCP server with a single static lease. config := dhcpd.ServerConfig{ Enabled: true, DBFilePath: "leases.db", Conf4: dhcpd.V4ServerConf{ Enabled: true, GatewayIP: net.IP{1, 2, 3, 1}, SubnetMask: net.IP{255, 255, 255, 0}, RangeStart: net.IP{1, 2, 3, 2}, RangeEnd: net.IP{1, 2, 3, 10}, }, } clients.dhcpServer = dhcpd.Create(config) t.Cleanup(func() { _ = os.Remove("leases.db") }) err := clients.dhcpServer.AddStaticLease(dhcpd.Lease{ HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, IP: testIP, Hostname: "testhost", Expiry: time.Now().Add(time.Hour), }) require.Nil(t, err) // Add a new client with the same IP as for a client with MAC. ok, err := clients.Add(&Client{ IDs: []string{testIP.String()}, Name: "client2", }) require.Nil(t, err) assert.True(t, ok) // Add a new client with the IP from the first client's IP // range. ok, err = clients.Add(&Client{ IDs: []string{"2.2.2.2"}, Name: "client3", }) require.Nil(t, err) assert.True(t, ok) }) } func TestClientsCustomUpstream(t *testing.T) { clients := clientsContainer{ testing: true, } clients.Init(nil, nil, nil) // Add client with upstreams. ok, err := clients.Add(&Client{ IDs: []string{"1.1.1.1", "1:2:3::4", "aa:aa:aa:aa:aa:aa"}, Name: "client1", Upstreams: []string{ "1.1.1.1", "[/example.org/]8.8.8.8", }, }) require.Nil(t, err) assert.True(t, ok) config := clients.FindUpstreams("1.2.3.4") assert.Nil(t, config) config = clients.FindUpstreams("1.1.1.1") require.NotNil(t, config) assert.Len(t, config.Upstreams, 1) assert.Len(t, config.DomainReservedUpstreams, 1) }