github.com/jaylevin/jenkins-library@v1.230.4/pkg/mock/runner.go (about)

     1  //go:build !release
     2  // +build !release
     3  
     4  package mock
     5  
     6  import (
     7  	"io"
     8  	"io/ioutil"
     9  	"regexp"
    10  	"strings"
    11  
    12  	"github.com/SAP/jenkins-library/pkg/command"
    13  )
    14  
    15  type ExecMockRunner struct {
    16  	Dir                 []string
    17  	Env                 []string
    18  	ExitCode            int
    19  	Calls               []ExecCall
    20  	stdin               io.Reader
    21  	stdout              io.Writer
    22  	stderr              io.Writer
    23  	Stub                func(call string, stdoutReturn map[string]string, shouldFailOnCommand map[string]error, stdout io.Writer) error
    24  	StdoutReturn        map[string]string
    25  	ShouldFailOnCommand map[string]error
    26  }
    27  
    28  type ExecCall struct {
    29  	Execution *Execution
    30  	Async     bool
    31  	Exec      string
    32  	Params    []string
    33  }
    34  
    35  type Execution struct {
    36  	Killed bool
    37  }
    38  
    39  type ShellMockRunner struct {
    40  	Dir                 string
    41  	Env                 []string
    42  	ExitCode            int
    43  	Calls               []string
    44  	Shell               []string
    45  	stdin               io.Reader
    46  	stdout              io.Writer
    47  	stderr              io.Writer
    48  	StdoutReturn        map[string]string
    49  	ShouldFailOnCommand map[string]error
    50  }
    51  
    52  func (m *ExecMockRunner) SetDir(d string) {
    53  	m.Dir = append(m.Dir, d)
    54  }
    55  
    56  func (m *ExecMockRunner) SetEnv(e []string) {
    57  	m.Env = e
    58  }
    59  
    60  func (m *ExecMockRunner) AppendEnv(e []string) {
    61  	m.Env = append(m.Env, e...)
    62  }
    63  
    64  func (m *ExecMockRunner) RunExecutable(e string, p ...string) error {
    65  
    66  	exec := ExecCall{Exec: e, Params: p}
    67  	m.Calls = append(m.Calls, exec)
    68  
    69  	c := strings.Join(append([]string{e}, p...), " ")
    70  
    71  	return m.handleCall(c, m.StdoutReturn, m.ShouldFailOnCommand, m.stdout)
    72  }
    73  
    74  func (m *ExecMockRunner) GetExitCode() int {
    75  	return m.ExitCode
    76  }
    77  
    78  func (m *ExecMockRunner) RunExecutableInBackground(e string, p ...string) (command.Execution, error) {
    79  
    80  	execution := Execution{}
    81  	exec := ExecCall{Exec: e, Params: p, Async: true, Execution: &execution}
    82  	m.Calls = append(m.Calls, exec)
    83  
    84  	c := strings.Join(append([]string{e}, p...), " ")
    85  
    86  	err := m.handleCall(c, m.StdoutReturn, m.ShouldFailOnCommand, m.stdout)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	return &execution, nil
    91  }
    92  
    93  func (m *ExecMockRunner) Stdin(in io.Reader) {
    94  	m.stdin = in
    95  }
    96  
    97  func (m *ExecMockRunner) Stdout(out io.Writer) {
    98  	m.stdout = out
    99  }
   100  
   101  func (m *ExecMockRunner) GetStdout() io.Writer {
   102  	return m.stdout
   103  }
   104  
   105  func (m *ExecMockRunner) Stderr(err io.Writer) {
   106  	m.stderr = err
   107  }
   108  
   109  func (m *ExecMockRunner) GetStderr() io.Writer {
   110  	return m.stderr
   111  }
   112  
   113  func (m *ExecMockRunner) handleCall(call string, stdoutReturn map[string]string, shouldFailOnCommand map[string]error, stdout io.Writer) error {
   114  	if m.Stub != nil {
   115  		return m.Stub(call, stdoutReturn, shouldFailOnCommand, stdout)
   116  	} else {
   117  		return handleCall(call, stdoutReturn, shouldFailOnCommand, stdout)
   118  	}
   119  }
   120  
   121  func (m *ShellMockRunner) SetDir(d string) {
   122  	m.Dir = d
   123  }
   124  
   125  func (m *ShellMockRunner) SetEnv(e []string) {
   126  	m.Env = append(m.Env, e...)
   127  }
   128  
   129  func (m *ShellMockRunner) AppendEnv(e []string) {
   130  	m.Env = append(m.Env, e...)
   131  }
   132  
   133  func (m *ShellMockRunner) RunShell(s string, c string) error {
   134  
   135  	m.Shell = append(m.Shell, s)
   136  	m.Calls = append(m.Calls, c)
   137  
   138  	return handleCall(c, m.StdoutReturn, m.ShouldFailOnCommand, m.stdout)
   139  }
   140  
   141  func (m *ShellMockRunner) GetExitCode() int {
   142  	return m.ExitCode
   143  }
   144  
   145  func (e *Execution) Kill() error {
   146  	e.Killed = true
   147  	return nil
   148  }
   149  
   150  func (e *Execution) Wait() error {
   151  	return nil
   152  }
   153  
   154  func handleCall(call string, stdoutReturn map[string]string, shouldFailOnCommand map[string]error, stdout io.Writer) error {
   155  
   156  	if stdoutReturn != nil {
   157  		for k, v := range stdoutReturn {
   158  
   159  			found := k == call
   160  
   161  			if !found {
   162  
   163  				r, e := regexp.Compile(k)
   164  				if e != nil {
   165  					return e
   166  					// we don't distinguish here between an error returned
   167  					// since it was configured or returning this error here
   168  					// indicating an invalid regex. Anyway: when running the
   169  					// test we will see it ...
   170  				}
   171  				if r.MatchString(call) {
   172  					found = true
   173  
   174  				}
   175  			}
   176  
   177  			if found {
   178  				stdout.Write([]byte(v))
   179  			}
   180  		}
   181  	}
   182  
   183  	if shouldFailOnCommand != nil {
   184  		for k, v := range shouldFailOnCommand {
   185  
   186  			found := k == call
   187  
   188  			if !found {
   189  				r, e := regexp.Compile(k)
   190  				if e != nil {
   191  					return e
   192  					// we don't distinguish here between an error returned
   193  					// since it was configured or returning this error here
   194  					// indicating an invalid regex. Anyway: when running the
   195  					// test we will see it ...
   196  				}
   197  				if r.MatchString(call) {
   198  					found = true
   199  
   200  				}
   201  			}
   202  
   203  			if found {
   204  				return v
   205  			}
   206  		}
   207  	}
   208  
   209  	return nil
   210  }
   211  
   212  func (m *ShellMockRunner) Stdin(in io.Reader) {
   213  	m.stdin = in
   214  }
   215  
   216  func (m *ShellMockRunner) Stdout(out io.Writer) {
   217  	m.stdout = out
   218  }
   219  
   220  func (m *ShellMockRunner) GetStdout() io.Writer {
   221  	return m.stdout
   222  }
   223  
   224  func (m *ShellMockRunner) GetStderr() io.Writer {
   225  	return m.stderr
   226  }
   227  
   228  func (m *ShellMockRunner) Stderr(err io.Writer) {
   229  	m.stderr = err
   230  }
   231  
   232  type StepOptions struct {
   233  	TestParam string `json:"testParam,omitempty"`
   234  }
   235  
   236  func OpenFileMock(name string, tokens map[string]string) (io.ReadCloser, error) {
   237  	var r string
   238  	switch name {
   239  	case "testDefaults.yml":
   240  		r = "general:\n  testParam: testValue"
   241  	case "testDefaultsInvalid.yml":
   242  		r = "invalid yaml"
   243  	default:
   244  		r = ""
   245  	}
   246  	return ioutil.NopCloser(strings.NewReader(r)), nil
   247  }