all: add tests

This commit is contained in:
Stanislav Chzhen 2024-04-24 14:21:44 +03:00
parent 1fc43cb45e
commit c6cdba7a8d
5 changed files with 294 additions and 7 deletions

View File

@ -229,9 +229,9 @@ func (c *Persistent) IDsLen() (n int) {
return len(c.IPs) + len(c.Subnets) + len(c.MACs) + len(c.ClientIDs)
}
// equalIDs returns true if the ids of the current and previous clients are the
// EqualIDs returns true if the ids of the current and previous clients are the
// same.
func (c *Persistent) equalIDs(prev *Persistent) (equal bool) {
func (c *Persistent) EqualIDs(prev *Persistent) (equal bool) {
return slices.Equal(c.IPs, prev.IPs) &&
slices.Equal(c.Subnets, prev.Subnets) &&
slices.EqualFunc(c.MACs, prev.MACs, slices.Equal[net.HardwareAddr]) &&

View File

@ -118,7 +118,7 @@ func TestPersistentClient_EqualIDs(t *testing.T) {
err = prev.SetIDs(tc.prevIDs)
require.NoError(t, err)
tc.want(t, c.equalIDs(prev))
tc.want(t, c.EqualIDs(prev))
})
}
}

View File

@ -41,7 +41,7 @@ func newClientsContainer(t *testing.T) (c *clientsContainer) {
}
dhcp := &testDHCP{
OnLeases: func() (leases []*dhcpsvc.Lease) { panic("not implemented") },
OnLeases: func() (leases []*dhcpsvc.Lease) { return nil },
OnHostBy: func(ip netip.Addr) (host string) { return "" },
OnMACBy: func(ip netip.Addr) (mac net.HardwareAddr) { return nil },
}

View File

@ -343,7 +343,9 @@ func (clients *clientsContainer) handleAddClient(w http.ResponseWriter, r *http.
return
}
onConfigModified()
if !clients.testing {
onConfigModified()
}
}
// handleDelClient is the handler for POST /control/clients/delete HTTP API.
@ -368,7 +370,9 @@ func (clients *clientsContainer) handleDelClient(w http.ResponseWriter, r *http.
return
}
onConfigModified()
if !clients.testing {
onConfigModified()
}
}
// updateJSON contains the name and data of the updated persistent client.
@ -425,7 +429,9 @@ func (clients *clientsContainer) handleUpdateClient(w http.ResponseWriter, r *ht
return
}
onConfigModified()
if !clients.testing {
onConfigModified()
}
}
// handleFindClient is the handler for GET /control/clients/find HTTP API.

View File

@ -0,0 +1,281 @@
package home
import (
"bytes"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/AdGuardHome/internal/schedule"
"github.com/stretchr/testify/require"
)
const (
testClientIP1 = "1.1.1.1"
testClientIP2 = "2.2.2.2"
)
// newPersistentClient is a helper function that returns a persistent client
// with the specified name and newly generated UID.
func newPersistentClient(name string) (c *client.Persistent) {
return &client.Persistent{
Name: name,
UID: client.MustNewUID(),
BlockedServices: &filtering.BlockedServices{
Schedule: &schedule.Weekly{},
},
}
}
// newPersistentClientWithIDs is a helper function that returns a persistent
// client with the specified name and ids.
func newPersistentClientWithIDs(tb testing.TB, name string, ids []string) (c *client.Persistent) {
tb.Helper()
c = newPersistentClient(name)
err := c.SetIDs(ids)
require.NoError(tb, err)
return c
}
// clientsCompare is a helper function that uses HTTP API to check whether want
// persistent clients are the same as the persistent clients stored in the
// clients container.
func clientsCompare(tb testing.TB, clients *clientsContainer, want []*client.Persistent) (ok bool) {
tb.Helper()
rw := httptest.NewRecorder()
clients.handleGetClients(rw, &http.Request{})
body, err := io.ReadAll(rw.Body)
require.NoError(tb, err)
clientList := &clientListJSON{}
err = json.Unmarshal(body, clientList)
require.NoError(tb, err)
got := map[string]*client.Persistent{}
for _, cj := range clientList.Clients {
var c *client.Persistent
c, err = clients.jsonToClient(*cj, nil)
require.NoError(tb, err)
got[c.Name] = c
}
require.Len(tb, want, len(got))
for _, c := range want {
var gotClient *client.Persistent
gotClient, ok = got[c.Name]
if !ok || !gotClient.EqualIDs(c) {
return false
}
}
return true
}
func TestClientsContainer_HandleAddClient(t *testing.T) {
clients := newClientsContainer(t)
clientOne := newPersistentClientWithIDs(t, "client1", []string{testClientIP1})
clientTwo := newPersistentClientWithIDs(t, "client2", []string{testClientIP2})
clientEmptyID := newPersistentClient("empty_client_id")
clientEmptyID.ClientIDs = []string{""}
testCases := []struct {
name string
client *client.Persistent
wantCode int
wantClient []*client.Persistent
}{{
name: "add_one",
client: clientOne,
wantCode: http.StatusOK,
wantClient: []*client.Persistent{clientOne},
}, {
name: "add_two",
client: clientTwo,
wantCode: http.StatusOK,
wantClient: []*client.Persistent{clientOne, clientTwo},
}, {
name: "duplicate_client",
client: clientTwo,
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientOne, clientTwo},
}, {
name: "empty_client_id",
client: clientEmptyID,
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientOne, clientTwo},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
cj := clientToJSON(tc.client)
body, err := json.Marshal(cj)
require.NoError(t, err)
rw := httptest.NewRecorder()
r, err := http.NewRequest(http.MethodPost, "", bytes.NewReader(body))
require.NoError(t, err)
clients.handleAddClient(rw, r)
require.NoError(t, err)
require.Equal(t, tc.wantCode, rw.Code)
ok := clientsCompare(t, clients, tc.wantClient)
require.True(t, ok)
})
}
}
func TestClientsContainer_HandleDelClient(t *testing.T) {
clients := newClientsContainer(t)
clientOne := newPersistentClientWithIDs(t, "client1", []string{testClientIP1})
err := clients.add(clientOne)
require.NoError(t, err)
clientTwo := newPersistentClientWithIDs(t, "client2", []string{testClientIP2})
err = clients.add(clientTwo)
require.NoError(t, err)
ok := clientsCompare(t, clients, []*client.Persistent{clientOne, clientTwo})
require.True(t, ok)
testCases := []struct {
name string
client *client.Persistent
wantCode int
wantClient []*client.Persistent
}{{
name: "remove_one",
client: clientOne,
wantCode: http.StatusOK,
wantClient: []*client.Persistent{clientTwo},
}, {
name: "duplicate_client",
client: clientOne,
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientTwo},
}, {
name: "empty_client_name",
client: newPersistentClient(""),
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientTwo},
}, {
name: "remove_two",
client: clientTwo,
wantCode: http.StatusOK,
wantClient: []*client.Persistent{},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
cj := clientToJSON(tc.client)
var body []byte
body, err = json.Marshal(cj)
require.NoError(t, err)
rw := httptest.NewRecorder()
var r *http.Request
r, err = http.NewRequest(http.MethodPost, "", bytes.NewReader(body))
require.NoError(t, err)
clients.handleDelClient(rw, r)
require.NoError(t, err)
require.Equal(t, tc.wantCode, rw.Code)
ok = clientsCompare(t, clients, tc.wantClient)
require.True(t, ok)
})
}
}
func TestClientsContainer_HandleUpdateClient(t *testing.T) {
clients := newClientsContainer(t)
clientOne := newPersistentClientWithIDs(t, "client1", []string{testClientIP1})
err := clients.add(clientOne)
require.NoError(t, err)
ok := clientsCompare(t, clients, []*client.Persistent{clientOne})
require.True(t, ok)
clientModified := newPersistentClientWithIDs(t, "client2", []string{testClientIP2})
clientEmptyID := newPersistentClient("empty_client_id")
clientEmptyID.ClientIDs = []string{""}
testCases := []struct {
name string
clientName string
modified *client.Persistent
wantCode int
wantClient []*client.Persistent
}{{
name: "update_one",
clientName: clientOne.Name,
modified: clientModified,
wantCode: http.StatusOK,
wantClient: []*client.Persistent{clientModified},
}, {
name: "empty_name",
clientName: "",
modified: clientOne,
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientModified},
}, {
name: "client_not_found",
clientName: "client_not_found",
modified: clientOne,
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientModified},
}, {
name: "empty_client_id",
clientName: clientModified.Name,
modified: clientEmptyID,
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientModified},
}, {
name: "no_ids",
clientName: clientModified.Name,
modified: newPersistentClient("no_ids"),
wantCode: http.StatusBadRequest,
wantClient: []*client.Persistent{clientModified},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
uj := updateJSON{
Name: tc.clientName,
Data: *clientToJSON(tc.modified),
}
var body []byte
body, err = json.Marshal(uj)
require.NoError(t, err)
rw := httptest.NewRecorder()
var r *http.Request
r, err = http.NewRequest(http.MethodPost, "", bytes.NewReader(body))
require.NoError(t, err)
clients.handleUpdateClient(rw, r)
require.NoError(t, err)
require.Equal(t, tc.wantCode, rw.Code)
ok = clientsCompare(t, clients, tc.wantClient)
require.True(t, ok)
})
}
}