Files
cunicu/pkg/daemon/watcher_linux_test.go
Steffen Vogel 3bee839348 fix: Update copyright years
Signed-off-by: Steffen Vogel <post@steffenvogel.de>
2025-01-01 22:45:39 +01:00

249 lines
5.2 KiB
Go

// SPDX-FileCopyrightText: 2023-2025 Steffen Vogel <post@steffenvogel.de>
// SPDX-License-Identifier: Apache-2.0
//go:build linux
package daemon_test
import (
"fmt"
"math/rand"
g "cunicu.li/gont/v2/pkg"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"cunicu.li/cunicu/pkg/crypto"
"cunicu.li/cunicu/pkg/daemon"
"cunicu.li/cunicu/pkg/device"
"cunicu.li/cunicu/test"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("watcher", func() {
var err error
var c *wgctrl.Client
var w *daemon.Watcher
var devUser bool
var h *daemon.EventsHandler
var ns *g.Namespace
var devName string
JustBeforeEach(OncePerOrdered, func() {
By("Creating net namespace")
nsName := fmt.Sprintf("wg-test-ns-%d", rand.Intn(1000)) //nolint:gosec
ns, err = g.NewNamespace(nsName)
Expect(err).To(Succeed())
func() {
exit, err := ns.Enter()
Expect(err).To(Succeed())
defer exit()
c, err = wgctrl.New()
Expect(err).To(Succeed())
}()
By("Creating watcher")
w, err = daemon.NewWatcher(c, 0, func(dev string) bool { return dev == devName })
Expect(err).To(Succeed())
h = daemon.NewEventsHandler(16)
w.AddAllHandler(h)
go func() {
exit, _ := ns.Enter()
defer exit()
w.Watch()
}()
})
JustAfterEach(OncePerOrdered, func() {
err := w.Close()
Expect(err).To(Succeed())
err = ns.Close()
Expect(err).To(Succeed())
})
// Overload It() to enter/exit namespace
It := func(name string, function func()) {
It(name, Offset(1), func() {
exit, err := ns.Enter()
Expect(err).To(Succeed())
function()
exit()
})
}
TestSync := func() {
var i *daemon.Interface
var p *daemon.Peer
var d device.Device
It("adding interface", func() {
d, err = device.NewDevice(devName, devUser)
Expect(err).To(Succeed())
err = w.Sync()
Expect(err).To(Succeed())
var ie daemon.InterfaceAddedEvent
Expect(h.Events).To(test.ReceiveEvent(&ie))
i = ie.Interface
Expect(ie.Interface).NotTo(BeNil())
Expect(ie.Interface.Name()).To(Equal(devName))
})
It("modifying the interface", func() {
oldListenPort := i.ListenPort
newListenPort := oldListenPort + 1
err = c.ConfigureDevice(devName, wgtypes.Config{
ListenPort: &newListenPort,
})
Expect(err).To(Succeed())
err = w.Sync()
Expect(err).To(Succeed())
var ie daemon.InterfaceModifiedEvent
Expect(h.Events).To(test.ReceiveEvent(&ie))
Expect(ie.Interface).NotTo(BeNil())
Expect(ie.Interface.Name()).To(Equal(devName))
Expect(ie.Modified & daemon.InterfaceModifiedListenPort).NotTo(BeZero())
Expect(ie.Interface.ListenPort).To(Equal(newListenPort))
Expect(ie.Old.ListenPort).To(Equal(oldListenPort))
})
It("adding a peer", func() {
sk, err := crypto.GenerateKey()
Expect(err).To(Succeed())
err = c.ConfigureDevice(i.Name(), wgtypes.Config{
Peers: []wgtypes.PeerConfig{
{
PublicKey: wgtypes.Key(sk.PublicKey()),
},
},
})
Expect(err).To(Succeed())
err = w.Sync()
Expect(err).To(Succeed())
var ie daemon.InterfaceModifiedEvent
Expect(h.Events).To(test.ReceiveEvent(&ie))
Expect(ie.Modified & daemon.InterfaceModifiedPeers).NotTo(BeZero())
var pe daemon.PeerAddedEvent
Expect(h.Events).To(test.ReceiveEvent(&pe))
// Remember peer for further test subjects
p = pe.Peer
Expect(pe.Peer.PublicKey()).To(Equal(sk.PublicKey()))
})
It("modifying a peer", func() {
psk, err := crypto.GeneratePrivateKey()
Expect(err).To(Succeed())
err = p.SetPresharedKey(&psk)
Expect(err).To(Succeed())
err = w.Sync()
Expect(err).To(Succeed())
var pe daemon.PeerModifiedEvent
Expect(h.Events).To(test.ReceiveEvent(&pe))
Expect(pe.Peer.PublicKey()).To(Equal(p.PublicKey()))
Expect(pe.Modified & daemon.PeerModifiedPresharedKey).NotTo(BeZero())
Expect(pe.Peer.PresharedKey()).To(Equal(psk))
})
It("removing a peer", func() {
err = c.ConfigureDevice(i.Name(), wgtypes.Config{
Peers: []wgtypes.PeerConfig{
{
PublicKey: wgtypes.Key(p.PublicKey()),
Remove: true,
},
},
})
Expect(err).To(Succeed())
err = w.Sync()
Expect(err).To(Succeed())
var ie daemon.InterfaceModifiedEvent
Expect(h.Events).To(test.ReceiveEvent(&ie))
Expect(ie.Modified & daemon.InterfaceModifiedPeers).NotTo(BeZero())
var pe daemon.PeerRemovedEvent
Expect(h.Events).To(test.ReceiveEvent(&pe))
Expect(pe.Peer.PublicKey()).To(Equal(p.PublicKey()))
})
It("removing an interface", func() {
err = d.Close()
Expect(err).To(Succeed())
err = w.Sync()
Expect(err).To(Succeed())
var ie daemon.InterfaceRemovedEvent
Expect(h.Events).To(test.ReceiveEvent(&ie))
Expect(ie.Interface).NotTo(BeNil())
Expect(ie.Interface.Name()).To(Equal(devName))
})
}
Context("sync", func() {
Context("kernel", Ordered, func() {
BeforeAll(func() {
devName = "wg-kernel"
devUser = false
})
TestSync()
})
Context("user", Ordered, func() {
BeforeAll(func() {
devName = fmt.Sprintf("wg-user-%d", rand.Intn(1000)) //nolint:gosec
devUser = true
})
TestSync()
})
})
Context("watch", Pending, func() {
Context("periodic", func() {
})
Context("user", func() {
})
Context("kernel", func() {
})
})
})