mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
refactor(runner): remove agent SDK connection and snapshot step
This commit is contained in:
1 parent
71d88a6827
commit
6e06f54d90
1 file changed
+9
-96
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/priyanshujain/sanderling/internal/agent"
|
||||
"github.com/priyanshujain/sanderling/internal/driver"
|
||||
"github.com/priyanshujain/sanderling/internal/hierarchy"
|
||||
"github.com/priyanshujain/sanderling/internal/ltl"
|
||||
@@ -21,11 +20,9 @@ import (
|
||||
|
||||
type Options struct {
|
||||
Duration time.Duration
|
||||
SnapshotTimeout time.Duration
|
||||
IdleTimeout time.Duration
|
||||
|
||||
BundleID string
|
||||
Connection *agent.Conn
|
||||
Driver driver.DeviceDriver
|
||||
Verifier *verifier.Verifier
|
||||
TraceWriter *trace.Writer
|
||||
@@ -44,10 +41,9 @@ type ViolationRecord struct {
|
||||
Properties []string
|
||||
}
|
||||
|
||||
// Run drives the snapshot/evaluate/release/act loop until the duration
|
||||
// elapses or the context is canceled. The caller is responsible for
|
||||
// launching the app and connecting the SDK before Run is called, and for
|
||||
// terminating the app afterwards.
|
||||
// Run drives the evaluate/act loop until the duration elapses or the context
|
||||
// is canceled. The caller is responsible for launching the app before Run is
|
||||
// called and for terminating it afterwards.
|
||||
func Run(ctx context.Context, options Options) (Summary, error) {
|
||||
if err := validate(options); err != nil {
|
||||
return Summary{}, err
|
||||
@@ -71,10 +67,8 @@ func Run(ctx context.Context, options Options) (Summary, error) {
|
||||
stepIndex++
|
||||
stepStart := time.Now()
|
||||
|
||||
// Hierarchy, metrics, and logs are independent device reads. Run
|
||||
// them concurrently so metrics+logs hide behind the hierarchy
|
||||
// fetch (~2s). All three must finish before snapshotStep pauses
|
||||
// the SDK.
|
||||
// Hierarchy, metrics, and logs are independent device reads — run
|
||||
// them concurrently so metrics+logs hide behind the hierarchy fetch.
|
||||
var tree *hierarchy.Tree
|
||||
var hierarchyErr error
|
||||
var metrics *trace.Metrics
|
||||
@@ -115,31 +109,20 @@ func Run(ctx context.Context, options Options) (Summary, error) {
|
||||
if tree != nil {
|
||||
treeSize = len(tree.Elements)
|
||||
}
|
||||
|
||||
snapshot, err := snapshotStep(ctx, options)
|
||||
if err != nil {
|
||||
return summary, fmt.Errorf("step %d snapshot: %w", stepIndex, err)
|
||||
}
|
||||
lastLogTime = stepStart
|
||||
|
||||
exceptions := decodeExceptions(snapshot)
|
||||
|
||||
if err := options.Verifier.PushSnapshot(verifier.SnapshotInput{
|
||||
Snapshots: verifier.Snapshots(snapshot.Snapshots),
|
||||
Tree: tree,
|
||||
LastAction: lastAction,
|
||||
StepTime: stepStart,
|
||||
RunStart: summary.StartTime,
|
||||
Logs: logs,
|
||||
Exceptions: exceptions,
|
||||
}); err != nil {
|
||||
return summary, fmt.Errorf("step %d push: %w", stepIndex, err)
|
||||
}
|
||||
screen, screenErr := screenFromSnapshot(snapshot.Snapshots)
|
||||
if screenErr != nil {
|
||||
logger.Warn("screen snapshot decode failed", "step", stepIndex, "err", screenErr)
|
||||
}
|
||||
if screen == "" && tree != nil && len(tree.Elements) > 0 {
|
||||
|
||||
screen := ""
|
||||
if tree != nil && len(tree.Elements) > 0 {
|
||||
screen = tree.Elements[0].Screen
|
||||
}
|
||||
logger.Info("step", "index", stepIndex, "screen", screen, "nodes", treeSize)
|
||||
@@ -168,9 +151,7 @@ func Run(ctx context.Context, options Options) (Summary, error) {
|
||||
Index: stepIndex,
|
||||
Timestamp: stepStart,
|
||||
Screen: screen,
|
||||
Snapshots: snapshot.Snapshots,
|
||||
Action: traceAction,
|
||||
Exceptions: traceExceptions(exceptions),
|
||||
Violations: violations,
|
||||
Hierarchy: tree,
|
||||
Residuals: residuals,
|
||||
@@ -188,12 +169,6 @@ func Run(ctx context.Context, options Options) (Summary, error) {
|
||||
})
|
||||
}
|
||||
|
||||
if options.Connection != nil {
|
||||
if err := options.Connection.Release(ctx); err != nil {
|
||||
return summary, fmt.Errorf("step %d release: %w", stepIndex, err)
|
||||
}
|
||||
}
|
||||
|
||||
if nextErr == nil {
|
||||
if err := applyAction(ctx, options.Driver, nextAction, tree); err != nil {
|
||||
if isWDADrop(err) {
|
||||
@@ -240,28 +215,12 @@ func validate(options Options) error {
|
||||
if options.Duration <= 0 {
|
||||
return errors.New("runner: Duration must be positive")
|
||||
}
|
||||
if options.SnapshotTimeout <= 0 {
|
||||
options.SnapshotTimeout = 5 * time.Second
|
||||
}
|
||||
if options.IdleTimeout <= 0 {
|
||||
options.IdleTimeout = 2 * time.Second
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func snapshotStep(ctx context.Context, options Options) (agent.Message, error) {
|
||||
if options.Connection == nil {
|
||||
return agent.Message{}, nil
|
||||
}
|
||||
snapshotTimeout := options.SnapshotTimeout
|
||||
if snapshotTimeout <= 0 {
|
||||
snapshotTimeout = 5 * time.Second
|
||||
}
|
||||
snapshotCtx, snapshotCancel := context.WithTimeout(ctx, snapshotTimeout)
|
||||
defer snapshotCancel()
|
||||
return options.Connection.Snapshot(snapshotCtx)
|
||||
}
|
||||
|
||||
func violationNames(verdicts map[string]ltl.Verdict) []string {
|
||||
var names []string
|
||||
for name, verdict := range verdicts {
|
||||
@@ -272,18 +231,6 @@ func violationNames(verdicts map[string]ltl.Verdict) []string {
|
||||
return names
|
||||
}
|
||||
|
||||
func screenFromSnapshot(snapshots map[string]json.RawMessage) (string, error) {
|
||||
raw, ok := snapshots["screen"]
|
||||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
var screen string
|
||||
if err := json.Unmarshal(raw, &screen); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return screen, nil
|
||||
}
|
||||
|
||||
func applyAction(ctx context.Context, drv driver.DeviceDriver, action verifier.Action, tree *hierarchy.Tree) error {
|
||||
switch action.Kind {
|
||||
case verifier.ActionKindTap:
|
||||
@@ -355,22 +302,6 @@ func collectLogs(ctx context.Context, drv driver.DeviceDriver, since time.Time)
|
||||
return result
|
||||
}
|
||||
|
||||
func decodeExceptions(snapshot agent.Message) []verifier.Exception {
|
||||
if len(snapshot.Exceptions) == 0 {
|
||||
return nil
|
||||
}
|
||||
result := make([]verifier.Exception, 0, len(snapshot.Exceptions))
|
||||
for _, e := range snapshot.Exceptions {
|
||||
result = append(result, verifier.Exception{
|
||||
Class: e.Class,
|
||||
Message: e.Message,
|
||||
StackTrace: e.StackTrace,
|
||||
UnixMillis: e.UnixMillis,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func resolveCoordinates(action verifier.Action, tree *hierarchy.Tree) (int, int, bool) {
|
||||
if action.X > 0 && action.Y > 0 {
|
||||
return action.X, action.Y, true
|
||||
@@ -421,9 +352,7 @@ func traceActionFor(action verifier.Action, tree *hierarchy.Tree) *trace.Action
|
||||
}
|
||||
|
||||
// stampSelectorTarget mirrors applyAction's coordinate-resolution rule so the
|
||||
// trace records the same point the runner taps. When the spec passed an ax
|
||||
// element directly, action.X/Y are already populated and we use them; when the
|
||||
// spec passed a string selector, we resolve it against the captured hierarchy.
|
||||
// trace records the same point the runner taps.
|
||||
func stampSelectorTarget(traceAction *trace.Action, action verifier.Action, tree *hierarchy.Tree) {
|
||||
if action.X > 0 && action.Y > 0 {
|
||||
traceAction.TapPoint = &trace.PointRecord{X: action.X, Y: action.Y}
|
||||
@@ -512,19 +441,3 @@ func isWDADrop(err error) bool {
|
||||
return strings.Contains(msg, "ConnectException") ||
|
||||
(strings.Contains(msg, "code = Internal") && strings.Contains(msg, "SocketException"))
|
||||
}
|
||||
|
||||
func traceExceptions(exceptions []verifier.Exception) []trace.Exception {
|
||||
if len(exceptions) == 0 {
|
||||
return nil
|
||||
}
|
||||
result := make([]trace.Exception, 0, len(exceptions))
|
||||
for _, e := range exceptions {
|
||||
result = append(result, trace.Exception{
|
||||
Class: e.Class,
|
||||
Message: e.Message,
|
||||
StackTrace: e.StackTrace,
|
||||
UnixMillis: e.UnixMillis,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in new issue
Block a user