Skip to content

Commit

Permalink
sensors: test intermediate states ({,un}loading)
Browse files Browse the repository at this point in the history
This patch tests the intermediate states that were introduced in the
previous patches. Specifically, it tests whether ListTracingPolicies
call observes loading/unloading states for the corresponding sensors. It
does so by a TestDelayedSensor that implements the SensorIface
interface.

Signed-off-by: Kornilios Kourtis <kornilios@isovalent.com>
  • Loading branch information
kkourt committed Jun 4, 2024
1 parent a2f6e13 commit 47690ce
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 0 deletions.
70 changes: 70 additions & 0 deletions pkg/sensors/delayed_sensor_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Tetragon

package sensors

import (
"fmt"
"testing"
"time"
)

// A sensor to test the intermediate policy states (loading / unloading)

func makeTestDelayedSensor(t *testing.T) *TestDelayedSensor {
s := &TestDelayedSensor{
name: "test-delayed-sensor",
loaded: false,
ch: make(chan struct{}),
}
RegisterPolicyHandlerAtInit("dummy-policyhandler", &dummyHandler{s: s})
t.Cleanup(func() {
delete(registeredPolicyHandlers, "dummy-policyhandler")
})

return s
}

type TestDelayedSensor struct {
name string
loaded bool
ch chan struct{}
}

func (tds *TestDelayedSensor) GetName() string {
return tds.name
}

func (tds *TestDelayedSensor) IsLoaded() bool {
return tds.loaded
}

func (tds *TestDelayedSensor) Load(_ string) error {
select {
case <-tds.ch:

case <-time.After(1 * time.Second):
return fmt.Errorf("TestDelayedSensor/Load timeout when waiting for unblocking")
}
tds.loaded = true
return nil
}

func (tds *TestDelayedSensor) Unload() error {
select {
case <-tds.ch:

case <-time.After(1 * time.Second):
return fmt.Errorf("TestDelayedSensor/Unload timeout when waiting for unblocking")
}
tds.loaded = false
return nil
}

func (tds *TestDelayedSensor) Destroy() {
tds.loaded = false
}

func (tds *TestDelayedSensor) unblock(_ *testing.T) {
tds.ch <- struct{}{}
}
105 changes: 105 additions & 0 deletions pkg/sensors/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"
"time"

"github.com/cilium/tetragon/api/v1/tetragon"
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
"github.com/cilium/tetragon/pkg/policyfilter"
"github.com/cilium/tetragon/pkg/sensors/program"
Expand Down Expand Up @@ -304,3 +305,107 @@ func TestPolicyLoadErrorOverride(t *testing.T) {
assert.Len(t, l.Policies, 1)
assert.Equal(t, EnabledState.ToTetragonState(), l.Policies[0].State)
}

func TestPolicyListingWhileLoadUnload(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

polName := "test-policy"
testSensor := makeTestDelayedSensor(t)

mgr, err := StartSensorManager("", nil)
require.NoError(t, err)
t.Cleanup(func() {
if err := mgr.StopSensorManager(ctx); err != nil {
panic("failed to stop sensor manager")
}
})

checkPolicy := func(t *testing.T, statuses []*tetragon.TracingPolicyStatus, state tetragon.TracingPolicyState) {
require.Equal(t, 1, len(statuses))
pol := statuses[0]
require.Equal(t, pol.Name, polName)
require.Equal(t, pol.State, state)
}

go func() {
// wait until at least one policy shows up, verify that it's in loading state and
// unblock the loading of the policy
for {
l, err := mgr.ListTracingPolicies(ctx)
require.NoError(t, err)
if len(l.Policies) > 0 {
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_LOADING)
testSensor.unblock(t)
break
}
time.Sleep(1 * time.Millisecond)
}
}()

t.Log("adding policy")
policy := v1alpha1.TracingPolicy{}
policy.ObjectMeta.Name = polName
err = mgr.AddTracingPolicy(ctx, &policy)
require.NoError(t, err)

// check that policy is now enabled
l, err := mgr.ListTracingPolicies(ctx)
require.NoError(t, err)
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_ENABLED)

go func() {
// wait until at least one policy shows up, verify that it's in unloading state and
// unblock the unloading of the policy
for {
l, err := mgr.ListTracingPolicies(ctx)
require.NoError(t, err)
require.Equal(t, len(l.Policies), 1)
if l.Policies[0].State == tetragon.TracingPolicyState_TP_STATE_UNLOADING {
testSensor.unblock(t)
break
}
time.Sleep(1 * time.Millisecond)
}
}()

t.Log("disabling policy")
err = mgr.DisableTracingPolicy(ctx, polName, "")
require.NoError(t, err)

// check that policy is now diabled
l, err = mgr.ListTracingPolicies(ctx)
require.NoError(t, err)
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_DISABLED)

go func() {
// wait until at least one policy shows up, verify that it's in loading state and
// unblock the loading of the policy
for {
l, err := mgr.ListTracingPolicies(ctx)
require.NoError(t, err)
require.Equal(t, len(l.Policies), 1)
if l.Policies[0].State == tetragon.TracingPolicyState_TP_STATE_LOADING {
testSensor.unblock(t)
break
}
time.Sleep(1 * time.Millisecond)
}
}()

t.Log("re-enabling policy")
err = mgr.EnableTracingPolicy(ctx, polName, "")
require.NoError(t, err)

// check that policy is now diabled
l, err = mgr.ListTracingPolicies(ctx)
require.NoError(t, err)
checkPolicy(t, l.Policies, tetragon.TracingPolicyState_TP_STATE_ENABLED)

t.Log("deleting policy")
err = mgr.DeleteTracingPolicy(ctx, polName, "")
require.NoError(t, err)
l, err = mgr.ListTracingPolicies(ctx)
require.NoError(t, err)
require.Equal(t, 0, len(l.Policies))
}

0 comments on commit 47690ce

Please sign in to comment.