github.com/bitrise-io/go-xamarin@v0.0.0-20211005113058-bf60a8bae851/tools/testcloud/testcloud.go (about)

     1  package testcloud
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  
     7  	"github.com/bitrise-io/go-utils/command"
     8  	"github.com/bitrise-io/go-utils/pathutil"
     9  	"github.com/bitrise-io/go-xamarin/constants"
    10  )
    11  
    12  // Parallelization ...
    13  type Parallelization string
    14  
    15  const (
    16  	// ParallelizationUnknown ...
    17  	ParallelizationUnknown Parallelization = "unkown"
    18  	// ParallelizationByTestFixture ...
    19  	ParallelizationByTestFixture Parallelization = "by_test_fixture"
    20  	// ParallelizationByTestChunk ...
    21  	ParallelizationByTestChunk Parallelization = "by_test_chunk"
    22  )
    23  
    24  // ParseParallelization ...
    25  func ParseParallelization(parallelization string) (Parallelization, error) {
    26  	switch parallelization {
    27  	case "by_test_fixture":
    28  		return ParallelizationByTestFixture, nil
    29  	case "by_test_chunk":
    30  		return ParallelizationByTestChunk, nil
    31  	default:
    32  		return ParallelizationUnknown, fmt.Errorf("Unkown parallelization (%s)", parallelization)
    33  	}
    34  }
    35  
    36  // Model ...
    37  type Model struct {
    38  	testCloudExePth string
    39  
    40  	apkPth  string
    41  	ipaPth  string
    42  	dsymPth string
    43  
    44  	apiKey          string
    45  	user            string
    46  	assemblyDir     string
    47  	devices         string
    48  	isAsyncJSON     bool
    49  	series          string
    50  	nunitXMLPth     string
    51  	parallelization Parallelization
    52  
    53  	signOptions   []string
    54  	customOptions []string
    55  }
    56  
    57  // NewModel ...
    58  func NewModel(testCloudExexPth string) (*Model, error) {
    59  	absTestCloudExexPth, err := pathutil.AbsPath(testCloudExexPth)
    60  	if err != nil {
    61  		return nil, fmt.Errorf("Failed to expand path (%s), error: %s", testCloudExexPth, err)
    62  	}
    63  
    64  	return &Model{testCloudExePth: absTestCloudExexPth}, nil
    65  }
    66  
    67  // SetAPKPth ...
    68  func (testCloud *Model) SetAPKPth(apkPth string) *Model {
    69  	testCloud.apkPth = apkPth
    70  	return testCloud
    71  }
    72  
    73  // SetIPAPth ...
    74  func (testCloud *Model) SetIPAPth(ipaPth string) *Model {
    75  	testCloud.ipaPth = ipaPth
    76  	return testCloud
    77  }
    78  
    79  // SetDSYMPth ...
    80  func (testCloud *Model) SetDSYMPth(dsymPth string) *Model {
    81  	testCloud.dsymPth = dsymPth
    82  	return testCloud
    83  }
    84  
    85  // SetAPIKey ...
    86  func (testCloud *Model) SetAPIKey(apiKey string) *Model {
    87  	testCloud.apiKey = apiKey
    88  	return testCloud
    89  }
    90  
    91  // SetUser ...
    92  func (testCloud *Model) SetUser(user string) *Model {
    93  	testCloud.user = user
    94  	return testCloud
    95  }
    96  
    97  // SetAssemblyDir ...
    98  func (testCloud *Model) SetAssemblyDir(assemblyDir string) *Model {
    99  	testCloud.assemblyDir = assemblyDir
   100  	return testCloud
   101  }
   102  
   103  // SetDevices ...
   104  func (testCloud *Model) SetDevices(devices string) *Model {
   105  	testCloud.devices = devices
   106  	return testCloud
   107  }
   108  
   109  // SetIsAsyncJSON ...
   110  func (testCloud *Model) SetIsAsyncJSON(isAsyncJSON bool) *Model {
   111  	testCloud.isAsyncJSON = isAsyncJSON
   112  	return testCloud
   113  }
   114  
   115  // SetSeries ...
   116  func (testCloud *Model) SetSeries(series string) *Model {
   117  	testCloud.series = series
   118  	return testCloud
   119  }
   120  
   121  // SetNunitXMLPth ...
   122  func (testCloud *Model) SetNunitXMLPth(nunitXMLPth string) *Model {
   123  	testCloud.nunitXMLPth = nunitXMLPth
   124  	return testCloud
   125  }
   126  
   127  // SetParallelization ...
   128  func (testCloud *Model) SetParallelization(parallelization Parallelization) *Model {
   129  	testCloud.parallelization = parallelization
   130  	return testCloud
   131  }
   132  
   133  // SetSignOptions ...
   134  func (testCloud *Model) SetSignOptions(options ...string) *Model {
   135  	testCloud.signOptions = options
   136  	return testCloud
   137  }
   138  
   139  // SetCustomOptions ...
   140  func (testCloud *Model) SetCustomOptions(options ...string) *Model {
   141  	testCloud.customOptions = options
   142  	return testCloud
   143  }
   144  
   145  func (testCloud *Model) submitCommandSlice() []string {
   146  	cmdSlice := []string{constants.MonoPath}
   147  	cmdSlice = append(cmdSlice, testCloud.testCloudExePth)
   148  	cmdSlice = append(cmdSlice, "submit")
   149  
   150  	if testCloud.apkPth != "" {
   151  		cmdSlice = append(cmdSlice, testCloud.apkPth)
   152  	}
   153  
   154  	if testCloud.ipaPth != "" {
   155  		cmdSlice = append(cmdSlice, testCloud.ipaPth)
   156  	}
   157  	if testCloud.dsymPth != "" {
   158  		cmdSlice = append(cmdSlice, "--dsym", testCloud.dsymPth)
   159  	}
   160  
   161  	cmdSlice = append(cmdSlice, testCloud.apiKey)
   162  	cmdSlice = append(cmdSlice, testCloud.signOptions...)
   163  	cmdSlice = append(cmdSlice, "--user", testCloud.user)
   164  	cmdSlice = append(cmdSlice, "--assembly-dir", testCloud.assemblyDir)
   165  	cmdSlice = append(cmdSlice, "--devices", testCloud.devices)
   166  
   167  	if testCloud.isAsyncJSON {
   168  		cmdSlice = append(cmdSlice, "--async-json")
   169  	}
   170  
   171  	cmdSlice = append(cmdSlice, "--series", testCloud.series)
   172  
   173  	if testCloud.nunitXMLPth != "" {
   174  		cmdSlice = append(cmdSlice, "--nunit-xml", testCloud.nunitXMLPth)
   175  	}
   176  
   177  	if testCloud.parallelization == ParallelizationByTestChunk {
   178  		cmdSlice = append(cmdSlice, "--test-chunk")
   179  	} else if testCloud.parallelization == ParallelizationByTestFixture {
   180  		cmdSlice = append(cmdSlice, "--fixture-chunk")
   181  	}
   182  
   183  	cmdSlice = append(cmdSlice, testCloud.customOptions...)
   184  
   185  	return cmdSlice
   186  }
   187  
   188  // String ...
   189  func (testCloud Model) String() string {
   190  	cmdSlice := testCloud.submitCommandSlice()
   191  	return command.PrintableCommandArgs(true, cmdSlice)
   192  }
   193  
   194  // CaptureLineCallback ...
   195  type CaptureLineCallback func(line string)
   196  
   197  // Submit ...
   198  func (testCloud Model) Submit(callback CaptureLineCallback) error {
   199  	cmdSlice := testCloud.submitCommandSlice()
   200  
   201  	command, err := command.NewFromSlice(cmdSlice)
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	cmd := *command.GetCmd()
   207  
   208  	// Redirect output
   209  	stdoutReader, err := cmd.StdoutPipe()
   210  	if err != nil {
   211  		return err
   212  	}
   213  
   214  	scanner := bufio.NewScanner(stdoutReader)
   215  	go func() {
   216  		for scanner.Scan() {
   217  			line := scanner.Text()
   218  			if callback != nil {
   219  				callback(line)
   220  			}
   221  		}
   222  	}()
   223  	if err := scanner.Err(); err != nil {
   224  		return err
   225  	}
   226  
   227  	if err := cmd.Start(); err != nil {
   228  		return err
   229  	}
   230  
   231  	return cmd.Wait()
   232  }