github.com/goreleaser/goreleaser@v1.25.1/internal/exec/exec_mock.go (about)

     1  package exec
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"reflect"
     8  	"sort"
     9  	"strings"
    10  )
    11  
    12  // nolint: gochecknoglobals
    13  var (
    14  	MockEnvVar = "GORELEASER_MOCK_DATA"
    15  	MockCmd    = os.Args[0]
    16  )
    17  
    18  type MockData struct {
    19  	AnyOf []MockCall `json:"any_of,omitempty"`
    20  }
    21  
    22  type MockCall struct {
    23  	Stdout       string   `json:"stdout,omitempty"`
    24  	Stderr       string   `json:"stderr,omitempty"`
    25  	ExpectedArgs []string `json:"args"`
    26  	ExpectedEnv  []string `json:"env"`
    27  	ExitCode     int      `json:"exit_code"`
    28  }
    29  
    30  func (m MockData) MarshalJSON() ([]byte, error) {
    31  	type t MockData
    32  	return json.Marshal((t)(m))
    33  }
    34  
    35  func (m *MockData) UnmarshalJSON(b []byte) error {
    36  	type t MockData
    37  	return json.Unmarshal(b, (*t)(m))
    38  }
    39  
    40  // MarshalMockEnv mocks marshal.
    41  //
    42  // nolint: interfacer
    43  func MarshalMockEnv(data *MockData) string {
    44  	b, err := data.MarshalJSON()
    45  	if err != nil {
    46  		errData := &MockData{
    47  			AnyOf: []MockCall{
    48  				{
    49  					Stderr:   fmt.Sprintf("unable to marshal mock data: %s", err),
    50  					ExitCode: 1,
    51  				},
    52  			},
    53  		}
    54  		b, _ = errData.MarshalJSON()
    55  	}
    56  
    57  	return MockEnvVar + "=" + string(b)
    58  }
    59  
    60  func ExecuteMockData(jsonData string) int {
    61  	md := &MockData{}
    62  	err := md.UnmarshalJSON([]byte(jsonData))
    63  	if err != nil {
    64  		fmt.Fprintf(os.Stderr, "unable to unmarshal mock data: %s", err)
    65  		return 1
    66  	}
    67  
    68  	givenArgs := os.Args[1:]
    69  	givenEnv := filterEnv(os.Environ())
    70  
    71  	if len(md.AnyOf) == 0 {
    72  		fmt.Fprintf(os.Stderr, "no mock calls expected. args: %q, env: %q",
    73  			givenArgs, givenEnv)
    74  		return 1
    75  	}
    76  
    77  	for _, item := range md.AnyOf {
    78  		if item.ExpectedArgs == nil {
    79  			item.ExpectedArgs = []string{}
    80  		}
    81  		if item.ExpectedEnv == nil {
    82  			item.ExpectedEnv = []string{}
    83  		}
    84  
    85  		sort.Strings(givenEnv)
    86  		sort.Strings(item.ExpectedEnv)
    87  		sort.Strings(givenArgs)
    88  		sort.Strings(item.ExpectedArgs)
    89  
    90  		if reflect.DeepEqual(item.ExpectedArgs, givenArgs) &&
    91  			reflect.DeepEqual(item.ExpectedEnv, givenEnv) {
    92  			fmt.Fprint(os.Stdout, item.Stdout)
    93  			fmt.Fprint(os.Stderr, item.Stderr)
    94  
    95  			return item.ExitCode
    96  		}
    97  	}
    98  
    99  	fmt.Fprintf(os.Stderr, "no mock calls matched. args: %q, env: %q",
   100  		givenArgs, givenEnv)
   101  	return 1
   102  }
   103  
   104  func filterEnv(vars []string) []string {
   105  	for i, env := range vars {
   106  		if strings.HasPrefix(env, MockEnvVar+"=") {
   107  			return append(vars[:i], vars[i+1:]...)
   108  		}
   109  	}
   110  
   111  	return vars
   112  }