// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Tetragon

//go:build !windows

package test

import (
	"context"
	"os"
	"sync"
	"testing"

	"github.com/stretchr/testify/require"
	"golang.org/x/sys/unix"

	ec "github.com/cilium/tetragon/api/v1/tetragon/codegen/eventchecker"
	"github.com/cilium/tetragon/pkg/jsonchecker"
	"github.com/cilium/tetragon/pkg/observer/observertesthelper"
	_ "github.com/cilium/tetragon/pkg/sensors/exec"
	tuo "github.com/cilium/tetragon/pkg/testutils/observer"
	tus "github.com/cilium/tetragon/pkg/testutils/sensors"
)

// This bpf_lseek is a simple BPF program used for tests

func TestMain(m *testing.M) {
	ec := tus.TestSensorsRun(m, "SensorTest")
	os.Exit(ec)
}

func TestSensorLseekLoad(t *testing.T) {
	if _, err := os.Stat("/sys/kernel/debug/tracing/events/syscalls"); os.IsNotExist(err) {
		t.Skip("cannot use syscall tracepoints (consider enabling CONFIG_FTRACE_SYSCALLS)")
	}

	var doneWG, readyWG sync.WaitGroup
	defer doneWG.Wait()

	ctx, cancel := context.WithTimeout(context.Background(), tus.Conf().CmdWaitTime)
	defer cancel()

	checker := ec.NewUnorderedEventChecker(
		ec.NewTestChecker(""),
	)

	obs, err := observertesthelper.GetDefaultObserver(t, ctx, tus.Conf().TetragonLib)
	if err != nil {
		t.Fatalf("GetDefaultObserver error: %s", err)
	}
	sensor := GetTestSensor()
	tus.LoadSensor(t, sensor)
	observertesthelper.LoopEvents(ctx, t, &doneWG, &readyWG, obs)
	readyWG.Wait()
	unix.Seek(BogusFd, 0, BogusWhenceVal)

	err = jsonchecker.JsonTestCheck(t, checker)
	require.NoError(t, err)
}

func TestSensorLseekEnable(t *testing.T) {
	if _, err := os.Stat("/sys/kernel/debug/tracing/events/syscalls"); os.IsNotExist(err) {
		t.Skip("cannot use syscall tracepoints (consider enabling CONFIG_FTRACE_SYSCALLS)")
	}

	var doneWG, readyWG sync.WaitGroup
	defer doneWG.Wait()

	ctx, cancel := context.WithTimeout(context.Background(), tus.Conf().CmdWaitTime)
	defer cancel()

	checker := ec.NewUnorderedEventChecker(
		ec.NewTestChecker(""),
	)

	obs, err := observertesthelper.GetDefaultObserver(t, ctx, tus.Conf().TetragonLib)
	if err != nil {
		t.Fatalf("GetDefaultObserver error: %s", err)
	}

	sensor := GetTestSensor()

	smanager := tuo.GetTestSensorManager(t)
	smanager.AddAndEnableSensor(ctx, t, sensor, sensor.Name)

	observertesthelper.LoopEvents(ctx, t, &doneWG, &readyWG, obs)
	readyWG.Wait()
	unix.Seek(BogusFd, 0, BogusWhenceVal)

	err = jsonchecker.JsonTestCheck(t, checker)
	require.NoError(t, err)
}
