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

test for retrieving exit code #852

Merged
merged 1 commit into from
Apr 7, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions contrib/tester-progs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ nop
sigkill-unprivileged-user-ns-tester
exit-leader
exit-tester
exit-code
libuprobe.so
uprobe-test-1
uprobe-test-2
7 changes: 7 additions & 0 deletions contrib/tester-progs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ PROGS = sigkill-tester \
nop \
exit-leader \
exit-tester \
exit-code \
uprobe-test-1 \
uprobe-test-2

Expand All @@ -28,9 +29,15 @@ exit-tester: exit-tester.c
sigkill-unprivileged-user-ns-tester: sigkill-unprivileged-user-ns-tester.c
$(GCC) -Wall $< -o $@ -lcap

nop: nop.c
$(GCC) -Wall $< -o $@ -lpthread

exit-leader: exit-leader.c
$(GCC) -Wall $< -o $@ -lpthread

exit-code: exit-code.c
$(GCC) -Wall $< -o $@ -lpthread

libuprobe.so: uprobe-lib.c
$(GCC) -Wall -fPIC $< -o $@ -shared

Expand Down
13 changes: 13 additions & 0 deletions contrib/tester-progs/exit-code.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *arg = argv[1];

// convert the argument to an integer
int exit_code = atoi(arg);

// do something with the argument
printf("The exit code is %d\n", exit_code);
return exit_code;
}
85 changes: 85 additions & 0 deletions pkg/sensors/exec/exit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,88 @@ func TestExitZombie(t *testing.T) {
err = jsonchecker.JsonTestCheck(t, checker)
assert.NoError(t, err)
}

// TestExitCode tests whether we properly return the exit code of the process.
// see: tester-progs/exit-code.c for the program we use to test this.
//
// The program will:
// - return a exit code
//
// In our test we check whether the observed exit code equals the real exit code.
func TestExitCode(t *testing.T) {
var doneWG, readyWG sync.WaitGroup
defer doneWG.Wait()

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

obs, err := observer.GetDefaultObserver(t, ctx, tus.Conf().TetragonLib)
if err != nil {
t.Fatalf("Failed to run observer: %s", err)
}
observer.LoopEvents(ctx, t, &doneWG, &readyWG, obs)
readyWG.Wait()

testExitCode := testutils.RepoRootPath("contrib/tester-progs/exit-code")

var exitCode, realCode uint32

// Test different exit codes
testCases := []int{
// Test some usual exit code
0, // Generic success code.
1, // Generic failure or unspecified error.
42, // Arbitrary value
125, // If the error is with Docker daemon itself
126, // If the contained command cannot be invoked

// Test some -errno
-30, // -EROFS(Read-only file system)
-31, // -EMLINK(Too many links)
-32, // -EPIPE(Broken pipe)
-33, // -EDOM(Math argument out of domain of func)
-34, // -ERANGE(Math result not representable)
}

for _, tc := range testCases {
// The test executes 'exit-code' benary which return a exit code
if err := exec.Command(testExitCode, fmt.Sprintf("%d", tc)).Run(); err != nil {
realCode = 0
if exitErr, ok := err.(*exec.ExitError); ok {
// handle ExitError
realCode = uint32(exitErr.ExitCode())
} else {
t.Fatalf("Failed to execute test binary: %s\n", err)
}
}

nextCheck := func(event ec.Event, l *logrus.Logger) (bool, error) {
switch ev := event.(type) {
case *tetragon.ProcessExit:
if ev.Process.Binary == testExitCode {
exitCode = ev.Status
}
return false, nil
}
return false, nil
}
finalCheck := func(l *logrus.Logger) error {
t.Logf("exitCode %v\n", exitCode)

if exitCode == realCode {
return nil
}
return fmt.Errorf("tetragon returns the exit code of the process uncorrectly")
}

checker := &ec.FnEventChecker{
NextCheckFn: nextCheck,
FinalCheckFn: finalCheck,
}

if err := jsonchecker.JsonTestCheck(t, checker); err != nil {
t.Logf("error: %s", err)
t.Fail()
}
}
}