blob: bb50d388378dc88e9a2bf32512ce0f0b4b631bc0 [file] [log] [blame]
package modules
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"strconv"
"testing"
"github.com/google/go-cmp/cmp"
)
var (
mockCmdStdout string
mockCmdExitStatus = 0
)
func fakeExecCommand(command string, args ...string) *exec.Cmd {
cs := []string{"-test.run=TestHelperProcess", "--", command}
cs = append(cs, args...)
cmd := exec.Command(os.Args[0], cs...)
es := strconv.Itoa(mockCmdExitStatus)
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1",
"STDOUT=" + mockCmdStdout,
"EXIT_STATUS=" + es}
return cmd
}
// TestHelperProcess is not a real test. It is a helper process for faking exec.Command.
func TestHelperProcess(t *testing.T) {
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
return
}
fmt.Fprintf(os.Stdout, os.Getenv("STDOUT"))
es, err := strconv.Atoi(os.Getenv("EXIT_STATUS"))
if err != nil {
t.Fatalf("Failed to convert EXIT_STATUS to int: %v", err)
}
os.Exit(es)
}
func TestHasInstalled(t *testing.T) {
execCommand = fakeExecCommand
defer func() {
execCommand = exec.Command
mockCmdExitStatus = 0
}()
for _, tc := range []struct {
testName string
moduleName string
cmdStdout string
cmdExitStatus int
expectOutput bool
}{
{"TestModuleInstalled", "nf_nat",
"Module\tSize\tUsed by\nnf_nat_ipv4\t16384\t2 ipt_MASQUERADE,iptable_nat\nnf_nat\t53248\t1 nf_nat_ipv4\n",
0, true,
},
{"TestModuleNotInstalled", "fat",
"Module\tSize\tUsed by\nnf_nat_ipv4\t16384\t2 ipt_MASQUERADE,iptable_nat\nnf_nat\t53248\t1 nf_nat_ipv4\n",
0, false,
},
} {
t.Run(tc.testName, func(t *testing.T) {
mockCmdStdout = tc.cmdStdout
mockCmdExitStatus = tc.cmdExitStatus
out, err := isModuleLoaded(tc.moduleName)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if out != tc.expectOutput {
t.Errorf("Unexpected return value, want %v, got %v", tc.expectOutput, out)
}
})
}
}
func TestAppendSignature(t *testing.T) {
modulefile, err := ioutil.TempFile("", "modulefile")
if err != nil {
t.Fatalf("AppendSignature: failed to create temp file: %v", err)
}
defer os.Remove(modulefile.Name())
sigfile, err := ioutil.TempFile("", "sigfile")
if err != nil {
t.Fatalf("AppendSignature: failed to create temp file: %v", err)
}
defer os.Remove(sigfile.Name())
_, err = modulefile.Write([]byte("module"))
if err != nil {
t.Fatalf("AppendSignature: failed to write to file %s: %v", modulefile.Name(), err)
}
if err := modulefile.Close(); err != nil {
t.Fatalf("AppendSignature: failed to close file %s: %v", modulefile.Name(), err)
}
_, err = sigfile.Write([]byte("signature"))
if err != nil {
t.Fatalf("AppendSignature: failed to write to file %s: %v", sigfile.Name(), err)
}
if err := sigfile.Close(); err != nil {
t.Fatalf("AppendSignature: failed to close file %s: %v", sigfile.Name(), err)
}
if err := AppendSignature(modulefile.Name(), modulefile.Name(), sigfile.Name()); err != nil {
t.Fatalf("AppendSignature: failed to run with error: %v", err)
}
signedModuleBytes, err := ioutil.ReadFile(modulefile.Name())
if err != nil {
t.Fatalf("AppendSignature: failed to read signed module file: %v", err)
}
expectedBytes := [...]byte{
// The following line is the bytes of the original module: "module"
0x6D, 0x6F, 0x64, 0x75, 0x6c, 0x65,
// The following line is the bytes of the signature: "signature"
0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
// The following lines are the bytes of module_signature struct
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x09,
// The following lines are the bytes of PKCS7 message: "~Module signature appended~\n"
0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61,
0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x7e, 0xa,
}
if diff := cmp.Diff(expectedBytes[:], signedModuleBytes); diff != "" {
t.Errorf("AppendSignature: signedModuleBytes doesn't match,\nwant: %v\ngot: %v\ndiff: %v",
expectedBytes, signedModuleBytes, diff)
}
}