| 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) | |
| } | |
| } |