blob: ba20a7d5756737a1a4ad5e50bc0d3bbe2376606e [file]
// Copyright 2022 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 tape
import (
"context"
"os"
"time"
"chromiumos/tast/errors"
"chromiumos/tast/rpc"
"chromiumos/tast/services/cros/tape"
"chromiumos/tast/testing"
)
const (
// RemoteComRobloxClientLeasedAccountFixture is a remote fixture which is used for Roblox testing.
RemoteComRobloxClientLeasedAccountFixture = "tapeRemoteComRobloxClientLeasedAccountFixture"
// RobloxTestPoolID is the name of the pool id associated with Roblox accounts.
RobloxTestPoolID = "com.roblox.client"
// RobloxLeaseTimeForAllTestsInSeconds is the amount of time needed for all Roblox tests.
RobloxLeaseTimeForAllTestsInSeconds = 60 * 60 * 1 // 1 hour.
// remoteFixtureTimeouts stores the timeouts for the Remote fixture functionality.
remoteFixtureTimeout = 5 * time.Minute
)
// LeasedAccountFileData holds the data to identify the leased account. This information is stored on the local DUT.
type LeasedAccountFileData struct {
Username string `json:"username"`
}
type remoteLeasedAccountFixture struct {
poolID string
timeoutInSeconds int32
genericAccount GenericAccount
}
// NewRemoteLeasedAccountFixture returns the fixture implementation for a remote fixture which is associated with a pool.
func NewRemoteLeasedAccountFixture(poolID string, timeoutInSeconds int32) testing.FixtureImpl {
return &remoteLeasedAccountFixture{
poolID: poolID,
timeoutInSeconds: timeoutInSeconds,
}
}
// availableServiceAccount returns the first available service account that
// can be used for TAPE. serviceAccounts are a list of paths to
// service accounts on the remote host.
func availableServiceAccount(s *testing.FixtState) (string, error) {
serviceAccounts := []string{
s.RequiredVar("tape.service_account1"),
s.RequiredVar("tape.service_account2"),
}
for _, sa := range serviceAccounts {
if _, err := os.Stat(sa); err == nil {
return sa, nil
}
}
return "", errors.New("no available service accounts found")
}
func (t *remoteLeasedAccountFixture) SetUp(ctx context.Context, s *testing.FixtState) interface{} {
// Get a generic account for testing with the provided pool id and timeout.
serviceAccount, err := availableServiceAccount(s)
if err != nil {
s.Fatal("Failed to access service account for TAPE: ", err)
}
client, err := NewTapeClient(ctx, serviceAccount)
if err != nil {
s.Fatal("Failed to setup TAPE client: ", err)
}
params := RequestGenericAccountParams{
TimeoutInSeconds: t.timeoutInSeconds,
PoolID: &t.poolID,
}
gar, err := RequestGenericAccount(ctx, params, client)
if err != nil {
s.Fatal("Failed to request generic account: ", err)
}
t.genericAccount = *gar
// Write the content to the DUT.
c, err := rpc.Dial(ctx, s.DUT(), s.RPCHint())
if err != nil {
s.Fatal("Failed to dial: ", err)
}
defer c.Close(ctx)
tsc := tape.NewTapeServiceClient(c.Conn)
if _, err := tsc.SaveGenericAccountInfoToFile(ctx, &tape.SaveGenericAccountInfoToFileRequest{
Path: LocalDUTAccountFileLocation(t.poolID),
Username: gar.Username,
}); err != nil {
s.Fatal("Failed to save generic account to DUT: ", err)
}
return nil
}
func (t *remoteLeasedAccountFixture) Reset(ctx context.Context) error { return nil }
func (t *remoteLeasedAccountFixture) PreTest(ctx context.Context, s *testing.FixtTestState) {}
func (t *remoteLeasedAccountFixture) PostTest(ctx context.Context, s *testing.FixtTestState) {}
func (t *remoteLeasedAccountFixture) TearDown(ctx context.Context, s *testing.FixtState) {
serviceAccount, err := availableServiceAccount(s)
if err != nil {
s.Fatal("Failed to access service account for TAPE: ", err)
}
client, err := NewTapeClient(ctx, serviceAccount)
if err != nil {
s.Fatal("Failed to setup TAPE client: ", err)
}
if err := ReleaseGenericAccount(ctx, &t.genericAccount, client); err != nil {
s.Fatal("Failed to request generic account: ", err)
}
// Remove the data from the DUT.
c, err := rpc.Dial(ctx, s.DUT(), s.RPCHint())
if err != nil {
s.Fatal("Failed to dial: ", err)
}
defer c.Close(ctx)
tsc := tape.NewTapeServiceClient(c.Conn)
if _, err := tsc.RemoveGenericAccountInfo(ctx, &tape.RemoveGenericAccountInfoRequest{
Path: LocalDUTAccountFileLocation(t.poolID),
}); err != nil {
s.Fatal("Failed to remove generic account information from DUT: ", err)
}
}
// RemoteFixtures is a convenience method which holds all remote fixtures for
// TAPE. They will all be automatically registered. Note that no two remote fixtures
// should define the same PoolID. This is a requirement of the current implementation.
func RemoteFixtures() []*testing.Fixture {
return []*testing.Fixture{
&testing.Fixture{
Name: RemoteComRobloxClientLeasedAccountFixture,
Desc: "Remote fixture which stores a Roblox account on a DUT. The account is unique to the DUT and is guaranteed to not be in use on other DUTs",
Contacts: []string{"davidwelling@google.com", "arc-engprod@google.com"},
Impl: NewRemoteLeasedAccountFixture(RobloxTestPoolID, RobloxLeaseTimeForAllTestsInSeconds),
SetUpTimeout: remoteFixtureTimeout,
TearDownTimeout: remoteFixtureTimeout,
ServiceDeps: []string{"tast.cros.tape.TapeService"},
Vars: []string{"tape.service_account1", "tape.service_account2"},
},
}
}