blob: f7c0664924a2c0c7c675789ab0a9373bd440465a [file] [log] [blame] [edit]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Package diag is a library of functionality to utilize the built-in Chrome
// network diagnostic routines.
package diag
import (
"context"
"fmt"
"time"
"chromiumos/tast/common/network/diag"
"chromiumos/tast/errors"
"chromiumos/tast/local/chrome"
"chromiumos/tast/testing"
)
// MojoAPI is a struct that encapsulates a Network Diagnostics mojo remote.
// Functions are exposed to call the underlying diagnostics routines.
type MojoAPI struct {
conn *chrome.Conn
mojoRemote *chrome.JSObject
}
// NewMojoAPI returns a MojoAPI object that is connected to a network
// diagnostics mojo remote instance on success, or an error.
func NewMojoAPI(ctx context.Context, conn *chrome.Conn) (*MojoAPI, error) {
var mojoRemote chrome.JSObject
if err := conn.Call(ctx, &mojoRemote, diag.NetDiagJs); err != nil {
return nil, errors.Wrap(err, "failed to set up the network diagnostics mojo API")
}
return &MojoAPI{conn, &mojoRemote}, nil
}
// RunRoutine calls into the injected network diagnostics mojo API and returns a
// diag.RoutineResult on success, or an error.
func (m *MojoAPI) RunRoutine(ctx context.Context, routine string) (*diag.RoutineResult, error) {
result := diag.RoutineResult{Verdict: diag.VerdictUnknown}
jsWrap := fmt.Sprintf("function() { return this.%v() }", routine)
if err := m.mojoRemote.Call(ctx, &result, jsWrap); err != nil {
return nil, errors.Wrapf(err, "failed to run %v", routine)
}
switch result.Verdict {
case diag.VerdictNoProblem, diag.VerdictProblem, diag.VerdictNotRun:
return &result, nil
}
return nil, errors.Errorf("unknown routine verdict; got: %v", result.Verdict)
}
// PollRoutine will continuously run the specified routine until the provided
// diag.RoutineResult is matched.
func (m *MojoAPI) PollRoutine(ctx context.Context, routine string, expectedResult *diag.RoutineResult) error {
// If the context does not have the deadline, use 10 seconds timeout.
var timeout time.Duration
if _, ok := ctx.Deadline(); !ok {
timeout = 10 * time.Second
}
if err := testing.Poll(ctx, func(ctx context.Context) error {
result, err := m.RunRoutine(ctx, routine)
if err != nil {
return testing.PollBreak(errors.Wrap(err, "failed to run routine"))
}
if err := diag.CheckRoutineResult(result, expectedResult); err != nil {
return err
}
return nil
}, &testing.PollOptions{Timeout: timeout}); err != nil {
return errors.Wrap(err, "timout waiting for routine to have expected results")
}
return nil
}
// Release frees the resources help by the internal MojoAPI components.
func (m *MojoAPI) Release(ctx context.Context) error {
return m.mojoRemote.Release(ctx)
}