github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/container/externalbuilder/session_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package externalbuilder_test 8 9 import ( 10 "io" 11 "os/exec" 12 "syscall" 13 14 "github.com/hechain20/hechain/common/flogging" 15 "github.com/hechain20/hechain/core/container/externalbuilder" 16 . "github.com/onsi/ginkgo" 17 . "github.com/onsi/gomega" 18 "github.com/onsi/gomega/gbytes" 19 "go.uber.org/zap" 20 "go.uber.org/zap/zapcore" 21 ) 22 23 var _ = Describe("Session", func() { 24 var ( 25 logbuf *gbytes.Buffer 26 logger *flogging.FabricLogger 27 ) 28 29 BeforeEach(func() { 30 logbuf = gbytes.NewBuffer() 31 writer := io.MultiWriter(logbuf, GinkgoWriter) 32 enc := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{MessageKey: "msg"}) 33 core := zapcore.NewCore(enc, zapcore.AddSync(writer), zap.NewAtomicLevel()) 34 logger = flogging.NewFabricLogger(zap.New(core).Named("logger")) 35 }) 36 37 It("starts commands and returns a session handle to wait on", func() { 38 cmd := exec.Command("true") 39 sess, err := externalbuilder.Start(logger, cmd) 40 Expect(err).NotTo(HaveOccurred()) 41 Expect(sess).NotTo(BeNil()) 42 43 err = sess.Wait() 44 Expect(err).NotTo(HaveOccurred()) 45 }) 46 47 It("captures stderr to the provided logger", func() { 48 cmd := exec.Command("sh", "-c", "echo 'this is a message to stderr' >&2") 49 sess, err := externalbuilder.Start(logger, cmd) 50 Expect(err).NotTo(HaveOccurred()) 51 err = sess.Wait() 52 Expect(err).NotTo(HaveOccurred()) 53 54 Expect(logbuf).To(gbytes.Say("this is a message to stderr")) 55 }) 56 57 It("delivers signals to started commands", func() { 58 cmd := exec.Command("cat") 59 stdin, err := cmd.StdinPipe() 60 Expect(err).NotTo(HaveOccurred()) 61 defer stdin.Close() 62 63 sess, err := externalbuilder.Start(logger, cmd) 64 Expect(err).NotTo(HaveOccurred()) 65 66 exitCh := make(chan error) 67 go func() { exitCh <- sess.Wait() }() 68 69 Consistently(exitCh).ShouldNot(Receive()) 70 sess.Signal(syscall.SIGTERM) 71 Eventually(exitCh).Should(Receive(MatchError("signal: terminated"))) 72 }) 73 74 It("calls exit functions", func() { 75 var called1, called2 bool 76 var exitErr1, exitErr2 error 77 78 cmd := exec.Command("true") 79 sess, err := externalbuilder.Start(logger, cmd, func(err error) { 80 called1 = true 81 exitErr1 = err 82 }, func(err error) { 83 called2 = true 84 exitErr2 = err 85 }) 86 Expect(err).NotTo(HaveOccurred()) 87 Expect(sess).NotTo(BeNil()) 88 89 err = sess.Wait() 90 Expect(err).NotTo(HaveOccurred()) 91 92 Expect(called1).To(BeTrue()) 93 Expect(exitErr1).NotTo(HaveOccurred()) 94 Expect(called2).To(BeTrue()) 95 Expect(exitErr2).NotTo(HaveOccurred()) 96 }) 97 98 When("start fails", func() { 99 It("returns an error", func() { 100 cmd := exec.Command("./this-is-not-a-command") 101 _, err := externalbuilder.Start(logger, cmd) 102 Expect(err).To(MatchError("fork/exec ./this-is-not-a-command: no such file or directory")) 103 }) 104 }) 105 106 When("the command fails", func() { 107 It("returns the exit error from the command", func() { 108 cmd := exec.Command("false") 109 sess, err := externalbuilder.Start(logger, cmd) 110 Expect(err).NotTo(HaveOccurred()) 111 112 err = sess.Wait() 113 Expect(err).To(MatchError("exit status 1")) 114 Expect(err).To(BeAssignableToTypeOf(&exec.ExitError{})) 115 }) 116 117 It("passes the error to the exit function", func() { 118 var exitErr error 119 cmd := exec.Command("false") 120 sess, err := externalbuilder.Start(logger, cmd, func(err error) { 121 exitErr = err 122 }) 123 Expect(err).NotTo(HaveOccurred()) 124 125 err = sess.Wait() 126 Expect(err).To(MatchError("exit status 1")) 127 Expect(exitErr).To(Equal(err)) 128 }) 129 }) 130 })