Skip to content

Commit

Permalink
test: add strace function
Browse files Browse the repository at this point in the history
Signed-off-by: Alessio Greggi <[email protected]>
  • Loading branch information
alegrey91 committed Aug 19, 2024
1 parent bd4528d commit 0110548
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 1 deletion.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/coreos/go-iptables v0.6.1-0.20220901214115-d2b8608923d1
github.com/fsnotify/fsnotify v1.6.0
github.com/spf13/cobra v1.5.0
golang.org/x/sync v0.8.0
gopkg.in/yaml.v3 v3.0.1
)

Expand All @@ -19,7 +20,6 @@ require (
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/tools v0.1.12 // indirect
Expand Down
7 changes: 7 additions & 0 deletions tests/strace.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# this testscript test the 'create' command

# if go is not installed, then skip
[!exec:go] skip

strace fwdctl list -h
stdout 'Usage:'
79 changes: 79 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package main

import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"

"github.com/alegrey91/fwdctl/pkg/iptables"
goiptables "github.com/coreos/go-iptables/iptables"
"github.com/rogpeppe/go-internal/testscript"
Expand Down Expand Up @@ -39,11 +47,82 @@ func fwdExists(ts *testscript.TestScript, neg bool, args []string) {
}
}

func strace(ts *testscript.TestScript, neg bool, args []string) {
if len(args) < 1 {
ts.Fatalf("syntax: strace needs at least one argument")
}

outputDir := "syscalls"
if err := os.MkdirAll(outputDir, 0755); err != nil {
ts.Fatalf("failed to create output directory: %v", err)
}

// Prepare the strace output file
timestamp := time.Now().Format("20060102-150405")
outputFile := filepath.Join(outputDir, fmt.Sprintf("strace-%s.log", timestamp))

// Prepare the command to execute with strace, filtering only system calls
straceArgs := []string{"-f", "-e", "trace=all"}
straceArgs = append(straceArgs, args...)
strace := exec.Command("strace", straceArgs...)

var stdoutBuf bytes.Buffer
strace.Stdout = &stdoutBuf
var stderrBuf bytes.Buffer
strace.Stderr = &stderrBuf

// Run the command
if err := strace.Run(); err != nil {
if !neg {
ts.Fatalf("command failed: %v", err)
}
} else {
if neg {
ts.Fatalf("command succeeded when it should have failed")
}
}

fmt.Fprintf(ts.Stdout(), "%s", stdoutBuf.String())

syscalls := processStraceOutput(stderrBuf.String())
if err := os.WriteFile(outputFile, []byte(syscalls), 0644); err != nil {
ts.Logf("strace output saved to %s", outputFile)
}
}

func processStraceOutput(output string) string {
lines := strings.Split(output, "\n")

// Use a map to store unique system call names
syscalls := make(map[string]struct{})

// Iterate over each line and extract the system call name
for _, line := range lines {
// Extract the system call name before the first '('
if idx := strings.Index(line, "("); idx != -1 {
syscall := strings.TrimSpace(line[:idx])
if syscall != "" {
syscalls[syscall] = struct{}{}
}
}
}

// Convert the map keys to a slice to get unique system call names
var syscallList []string
for syscall := range syscalls {
syscallList = append(syscallList, syscall)
}

// Join the unique system call names into a single string, one per line
return strings.Join(syscallList, "\n")
}

func customCommands() map[string]func(ts *testscript.TestScript, neg bool, args []string) {
return map[string]func(ts *testscript.TestScript, neg bool, args []string){

// fwd_exists check that the given forward exists
// invoke as "fwd_exists iface proto dest_port src_addr src_port"
"fwd_exists": fwdExists,
"strace": strace,
}
}

0 comments on commit 0110548

Please sign in to comment.