github.com/nya3jp/tast@v0.0.0-20230601000426-85c8e4d83a9b/src/go.chromium.org/tast/core/internal/planner/external.go (about)

     1  // Copyright 2022 The ChromiumOS Authors
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file.
     4  
     5  package planner
     6  
     7  import (
     8  	"context"
     9  
    10  	"go.chromium.org/tast/core/internal/minidriver"
    11  	"go.chromium.org/tast/core/internal/minidriver/failfast"
    12  	"go.chromium.org/tast/core/internal/minidriver/target"
    13  	"go.chromium.org/tast/core/internal/planner/internal/fixture"
    14  	"go.chromium.org/tast/core/internal/planner/internal/output"
    15  	"go.chromium.org/tast/core/internal/protocol"
    16  	"go.chromium.org/tast/core/internal/testing"
    17  
    18  	frameworkprotocol "go.chromium.org/tast/core/framework/protocol"
    19  )
    20  
    21  // ExternalTarget specifies the external target bundle to run.
    22  type ExternalTarget struct {
    23  	Device *protocol.TargetDevice
    24  	Config *protocol.RunTargetConfig
    25  	Bundle string
    26  }
    27  
    28  // runExternalTests runs tests in primary target.
    29  // It sends a request to run the tests to the target bundle, and handles fixture
    30  // stack operation requests.
    31  // It returns an error If a test could not be run, or an internal framework
    32  // error has happened.
    33  // It returns unstarted tests.
    34  // External tests might not fully finish in case Stack Reset failure.
    35  // unstarted tests are returned for allowing retry unstarted tests.
    36  func runExternalTests(ctx context.Context, names []string, stack *fixture.CombinedStack, pcfg *Config, out output.Stream) (unstarted []string, err error) {
    37  	scfg := &target.ServiceConfig{
    38  		Devservers: pcfg.ExternalTarget.Config.GetDevservers(),
    39  		TLWServer:  pcfg.Service.GetTlwServer(),
    40  
    41  		UseEphemeralDevserver: pcfg.Service.GetUseEphemeralDevservers(),
    42  		TastDir:               pcfg.Service.GetTastDir(),
    43  		ExtraAllowedBuckets:   pcfg.Service.GetExtraAllowedBuckets(),
    44  		DebuggerPorts:         []int{int(pcfg.ExternalTarget.Config.GetDebugPort())},
    45  	}
    46  	tcfg := &target.Config{
    47  		SSHConfig:     pcfg.ExternalTarget.Device.GetDutConfig().GetSshConfig(),
    48  		TastVars:      pcfg.Features.GetInfra().GetVars(),
    49  		ServiceConfig: scfg,
    50  	}
    51  	cc, err := target.NewConnCache(ctx, tcfg, pcfg.ExternalTarget.Device.GetDutConfig().GetSshConfig().GetConnectionSpec(), pcfg.ExternalTarget.Device.GetDutConfig().GetSshConfig().GetProxyCommand(), "")
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	fixtureServer := fixture.NewStackServer(&fixture.StackServerConfig{
    57  		Out:    out,
    58  		Stack:  stack,
    59  		OutDir: pcfg.Dirs.GetOutDir(),
    60  		CloudStorage: testing.NewCloudStorage(
    61  			pcfg.Service.GetDevservers(),
    62  			pcfg.Service.GetTlwServer(),
    63  			pcfg.Service.GetTlwSelfName(),
    64  			pcfg.Service.GetDutServer(),
    65  			pcfg.DataFile.GetBuildArtifactsUrl(),
    66  			pcfg.Service.GetSwarmingTaskID(),
    67  			pcfg.Service.GetBuildBucketID(),
    68  		),
    69  		RemoteData: pcfg.RemoteData,
    70  	})
    71  
    72  	counter := failfast.NewCounter(int(pcfg.ExternalTarget.Config.GetMaxTestFailures()))
    73  	factory := minidriver.NewIntermediateHandlersFactory(pcfg.Dirs.GetOutDir(), counter, out.ExternalEvent, fixtureServer.Handle)
    74  
    75  	companionFeatures := make(map[string]*frameworkprotocol.DUTFeatures)
    76  	companionFeatures[""] = pcfg.Features.GetDut()
    77  	for key, value := range pcfg.Features.GetCompanionFeatures() {
    78  		companionFeatures[key] = value
    79  	}
    80  
    81  	cfg := &minidriver.Config{
    82  		Retries:        int(pcfg.ExternalTarget.Config.GetRetries()),
    83  		ResDir:         pcfg.Dirs.GetOutDir(),
    84  		Devservers:     pcfg.ExternalTarget.Config.GetDevservers(),
    85  		Target:         pcfg.ExternalTarget.Device.GetDutConfig().GetSshConfig().GetConnectionSpec(),
    86  		LocalDataDir:   pcfg.ExternalTarget.Config.GetDirs().GetDataDir(),
    87  		LocalOutDir:    pcfg.ExternalTarget.Config.GetDirs().GetOutDir(),
    88  		LocalTempDir:   pcfg.ExternalTarget.Config.GetDirs().GetTempDir(),
    89  		LocalBundleDir: pcfg.ExternalTarget.Device.GetBundleDir(),
    90  		DownloadMode:   pcfg.DataFile.GetDownloadMode(),
    91  		SwarmingTaskID: pcfg.ExternalTarget.Config.GetSwarmingTaskID(),
    92  		BuildBucketID:  pcfg.ExternalTarget.Config.GetBuildBucketID(),
    93  
    94  		WaitUntilReady:        pcfg.ExternalTarget.Config.GetWaitUntilReady(),
    95  		CheckTestDeps:         pcfg.Features.GetCheckDeps(),
    96  		TestVars:              pcfg.Features.GetInfra().GetVars(),
    97  		MaybeMissingVars:      pcfg.Features.GetInfra().GetMaybeMissingVars(),
    98  		MsgTimeout:            pcfg.ExternalTarget.Config.GetMsgTimeout().AsDuration(),
    99  		SystemServicesTimeout: pcfg.ExternalTarget.Config.GetSystemServicesTimeout().AsDuration(),
   100  		WaitUntilReadyTimeout: pcfg.ExternalTarget.Config.GetWaitUntilReadyTimeout().AsDuration(),
   101  
   102  		DebuggerPort: int(pcfg.ExternalTarget.Config.GetDebugPort()),
   103  		Proxy:        pcfg.ExternalTarget.Config.GetProxy(),
   104  
   105  		DUTFeatures:       companionFeatures,
   106  		ForceSkips:        pcfg.Features.ForceSkips,
   107  		Factory:           factory,
   108  		BuildArtifactsURL: pcfg.DataFile.GetBuildArtifactsUrl(),
   109  
   110  		Recursive: true,
   111  	}
   112  
   113  	d := minidriver.NewDriver(cfg, cc)
   114  
   115  	startFixture := stack.Top()
   116  
   117  	jsonResults, err := d.RunLocalTests(ctx, pcfg.ExternalTarget.Bundle, names, startFixture)
   118  	if err == minidriver.ErrNoTestRanInLastAttempt {
   119  		if len(jsonResults) == 0 {
   120  			return nil, err
   121  		}
   122  		// Fixture failure stopped local tests running.
   123  	} else if err != nil {
   124  		return nil, err
   125  	}
   126  	startedSet := make(map[string]struct{})
   127  	for _, t := range jsonResults {
   128  		startedSet[t.Name] = struct{}{}
   129  	}
   130  	for _, name := range names {
   131  		if _, ok := startedSet[name]; !ok {
   132  			unstarted = append(unstarted, name)
   133  		}
   134  	}
   135  	return unstarted, nil
   136  }