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