Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/improve test coverage #20

Merged
merged 3 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions internal/files/watch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,59 @@ import (
"github.com/fsnotify/fsnotify"
)

// TestIsResolvConfEvent tests isResolvConfEvent.
func TestIsResolvConfEvent(t *testing.T) {
// other events
for _, invalid := range []fsnotify.Event{
{},
{Name: "something else"},
} {
if ok := isResolvConfEvent(invalid); ok {
t.Errorf("event should not be a resolv.conf event: %v", invalid)
}
}

// resolv.conf events
for _, valid := range []fsnotify.Event{
{Name: etcResolvConf},
{Name: stubResolvConf},
{Name: systemdResolvConf},
} {
if ok := isResolvConfEvent(valid); !ok {
t.Errorf("event should be a resolv.conf event: %v", valid)
}
}
}

// TestWatchStartEvents tests start of Watch, events.
func TestWatchStartEvents(t *testing.T) {
// create watcher
probes := make(chan struct{})
fw := NewWatch(probes)
w, err := fsnotify.NewWatcher()
if err != nil {
t.Fatal(err)
}
fw.watcher = w

// start watcher and get initial probe
go fw.start()
<-probes

// send watcher events, handle probes
fw.watcher.Errors <- errors.New("test error")
fw.watcher.Events <- fsnotify.Event{Name: etcResolvConf}
<-probes

// unexpected close of watcher channels
if err := fw.watcher.Close(); err != nil {
t.Errorf("error closing watcher: %v", err)
}

// wait for watcher
<-fw.closed
}

// TestWatchStartStop tests Start() and Stop() of Watch.
func TestWatchStartStop(t *testing.T) {
probes := make(chan struct{})
Expand Down
20 changes: 20 additions & 0 deletions internal/routes/watch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,28 @@ import (
"testing"

"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
)

// TestWatchStartEvents tests start of Watch, events.
func TestWatchStartEvents(_ *testing.T) {
// create and start watch
probes := make(chan struct{})
rw := NewWatch(probes)
go rw.start()
<-probes

// new route event
rw.events <- netlink.RouteUpdate{Type: unix.RTM_NEWROUTE}
<-probes

// delete route event
rw.events <- netlink.RouteUpdate{Type: unix.RTM_DELROUTE}
<-probes

close(rw.done)
}

// TestWatchStartStop tests Start and Stop of Watch.
func TestWatchStartStop(t *testing.T) {
probes := make(chan struct{})
Expand Down
92 changes: 54 additions & 38 deletions pkg/tnd/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,57 @@ func (d *Detector) resetTimer() {
}
}

// handleProbeRequest handles a probe request.
func (d *Detector) handleProbeRequest() {
if d.running {
d.runAgain = true
return
}
d.running = true
go d.probe()

}

// handleProbeResult handles the probe result r.
func (d *Detector) handleProbeResult(r bool) {
// handle probe result
d.running = false
if d.runAgain {
// we must trigger another probe
d.runAgain = false
d.running = true
go d.probe()
}
log.WithField("trusted", r).Debug("TND https result")
d.trusted = r
d.sendResult(d.results, r)

// reset periodic probing timer
if d.running {
// probing still active and new results about
// to arrive, so wait for them before resetting
// the timer
return
}
if !d.timer.Stop() {
<-d.timer.C
}
d.resetTimer()
}

// handleTimer handles a timer event.
func (d *Detector) handleTimer() {
if !d.running && !d.runAgain {
// no probes active, trigger new probe
log.Debug("TND periodic probe timer")
d.running = true
go d.probe()
}

// reset timer
d.resetTimer()
}

// start starts the trusted network detection.
func (d *Detector) start() {
// signal stop to user via results
Expand All @@ -120,48 +171,13 @@ func (d *Detector) start() {
for {
select {
case <-d.probes:
if d.running {
d.runAgain = true
break
}
d.running = true
go d.probe()
d.handleProbeRequest()

case r := <-d.probeResults:
// handle probe result
d.running = false
if d.runAgain {
// we must trigger another probe
d.runAgain = false
d.running = true
go d.probe()
}
log.WithField("trusted", r).Debug("TND https result")
d.trusted = r
d.sendResult(d.results, r)

// reset periodic probing timer
if d.running {
// probing still active and new results about
// to arrive, so wait for them before resetting
// the timer
break
}
if !d.timer.Stop() {
<-d.timer.C
}
d.resetTimer()
d.handleProbeResult(r)

case <-d.timer.C:
if !d.running && !d.runAgain {
// no probes active, trigger new probe
log.Debug("TND periodic probe timer")
d.running = true
go d.probe()
}

// reset timer
d.resetTimer()
d.handleTimer()

case <-d.done:
if !d.timer.Stop() {
Expand Down
119 changes: 119 additions & 0 deletions pkg/tnd/detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (
"encoding/hex"
"errors"
"net"
"net/http"
"net/http/httptest"
"reflect"
"testing"
"time"
)

// testWatcher is a watcher that implements the routes.Watcher and
Expand Down Expand Up @@ -48,6 +51,122 @@ func TestDetectorSetGetDialer(t *testing.T) {
}
}

// TestDetectorProbe tests probe of Detector.
func TestDetectorProbe(t *testing.T) {
// start test https server
ts := httptest.NewTLSServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {}))
defer ts.Close()

// create detector
tnd := NewDetector(NewConfig())

// test untrusted
tnd.SetServers(map[string]string{ts.URL: "invalid"})
go tnd.probe()

want := false
got := <-tnd.probeResults
if got != want {
t.Errorf("got %t, want %t", got, want)
}

// test trusted
cert := ts.Certificate()
sha := sha256.Sum256(cert.Raw)
hash := hex.EncodeToString(sha[:])
tnd.SetServers(map[string]string{ts.URL: hash})
go tnd.probe()

want = true
got = <-tnd.probeResults
if got != want {
t.Errorf("got %t, want %t", got, want)
}
}

// TestDetectorHandleProbeRequest tests handleProbeRequest of Detector.
func TestDetectorHandleProbeRequest(t *testing.T) {
// create detector
tnd := NewDetector(NewConfig())

// already running
tnd.running = true
tnd.handleProbeRequest()
if tnd.runAgain != true {
t.Error("run again should be true")
}

// not runnnig
tnd.running = false
tnd.handleProbeRequest()
if tnd.running != true {
t.Error("running should be true")
}

close(tnd.done)
}

// TestDetectorHandleProbeResult tests handleProbeResult of Detector.
func TestDetectorHandleProbeResult(t *testing.T) {
// create detector
tnd := NewDetector(NewConfig())

// expire timer
tnd.timer = time.NewTimer(0)

// drain results channel
go func() {
for range tnd.results {
}
}()

// test not trusted
tnd.running = true
tnd.handleProbeResult(false)
if tnd.running != false {
t.Error("running should be false")
}

// test trusted
tnd.running = true
tnd.handleProbeResult(true)
if tnd.running != false {
t.Error("running should be false")
}

// test with runAgain
tnd.running = true
tnd.runAgain = true
tnd.handleProbeResult(false)
if tnd.runAgain != false {
t.Error("runAgain should be false")
}

close(tnd.results)
}

// TestDetectorHandleTimer tests handleTimer of Detector.
func TestDetectorHandleTimer(t *testing.T) {
// create detector
tnd := NewDetector(NewConfig())

// expire timer
tnd.timer = time.NewTimer(0)

// test without already running
tnd.handleTimer()
if tnd.running != true {
t.Error("running should be true")
}

// test with already running
tnd.handleTimer()
if tnd.running != true {
t.Error("running should be true")
}
}

// TestTNDStartStop tests Start and Stop of TND.
func TestTNDStartStop(t *testing.T) {
// test rw error
Expand Down
8 changes: 6 additions & 2 deletions pkg/tnd/tndtest/detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ func TestDetectorStart(t *testing.T) {
d := NewDetector()

// test no func set
d.Start()
if err := d.Start(); err != nil {
t.Fatal(err)
}

// test func set
want := true
Expand All @@ -75,7 +77,9 @@ func TestDetectorStart(t *testing.T) {
got = true
return nil
}
d.Start()
if err := d.Start(); err != nil {
t.Fatal(err)
}
if got != want {
t.Errorf("got %t, want %t", got, want)
}
Expand Down