blob: b8af94d3d7b9e883ab182be1a9b4d83d6cef8fee [file] [log] [blame]
// 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 playbilling
import (
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"chromiumos/tast/fsutil"
"chromiumos/tast/local/arc"
"chromiumos/tast/local/arc/optin"
"chromiumos/tast/local/chrome"
"chromiumos/tast/testing"
)
const (
userVar = "arc.PlayBillingUser"
passVar = "arc.PlayBillingPass"
assetLinksVar = "arc.PlayBillingAssetLinks"
apk = "ArcPlayBillingTestPWA_20210517.apk"
icon = "play_billing_icon.png"
index = "play_billing_index.html"
manifest = "play_billing_manifest.json"
payments = "play_billing_payments.js"
service = "play_billing_service.js"
localServerPort = 80
)
// pwaFiles are data files required to serve the Play Billing PWA.
var pwaFiles = []string{
icon,
index,
manifest,
payments,
service,
}
// DataFiles are the files required for each Play Billing tests.
var DataFiles = append(pwaFiles, apk)
func init() {
testing.AddFixture(&testing.Fixture{
Name: "arcBootedForPlayBilling",
Desc: "The fixture starts chrome with ARC supported used for Play Billing tests",
Contacts: []string{"benreich@chromium.org", "jshikaram@chromium.org"},
Impl: arc.NewArcBootedWithPlayStoreFixture(func(ctx context.Context, s *testing.FixtState) ([]chrome.Option, error) {
userID, ok := s.Var(userVar)
if !ok {
s.Fatalf("Runtime variable %s is not provided", userVar)
}
userPasswd, ok := s.Var(passVar)
if !ok {
s.Fatalf("Runtime variable %s is not provided", passVar)
}
return []chrome.Option{
chrome.ExtraArgs(arc.DisableSyncFlags()...),
chrome.ARCSupported(),
chrome.GAIALogin(chrome.Creds{User: userID, Pass: userPasswd})}, nil
}),
// Add two minutes to setup time to allow extra Play Store UI operations.
SetUpTimeout: chrome.GAIALoginTimeout + optin.OptinTimeout + arc.BootTimeout + 2*time.Minute,
ResetTimeout: chrome.ResetTimeout,
// Provide a longer enough PostTestTimeout value to fixture when ARC will try to dump ARCVM message.
// Or there might be error of "context deadline exceeded".
PostTestTimeout: 5 * time.Second,
TearDownTimeout: chrome.ResetTimeout,
Vars: []string{userVar, passVar},
})
testing.AddFixture(&testing.Fixture{
Name: "playBillingFixture",
Desc: "The fixture builds on arcBootedForPlayBilling but ensures the Play Billing PWA is started and the APK is sideloaded",
Impl: &playBillingFixture{},
Contacts: []string{"benreich@chromium", "jshikaram@chromium.org"},
Parent: "arcBootedForPlayBilling",
Vars: []string{assetLinksVar},
Data: []string{apk, icon, index, manifest, payments, service},
SetUpTimeout: 2 * time.Minute,
})
}
type playBillingFixture struct {
pwaServer *http.Server
pwaDir string
}
// The FixtData object is made available to users of this fixture via:
//
// func DoSomething(ctx context.Context, s *testing.State) {
// d := s.FixtValue().(playbilling.FixtData)
// ...
// }
type FixtData struct {
ARC *arc.ARC
Chrome *chrome.Chrome
TestApp *TestApp
}
func (f *playBillingFixture) SetUp(ctx context.Context, s *testing.FixtState) interface{} {
arcDevice := s.ParentValue().(*arc.PreData).ARC
cr := s.ParentValue().(*arc.PreData).Chrome
// Install the test APK.
if err := arcDevice.Install(ctx, s.DataPath(apk)); err != nil {
s.Fatal("Failed to install the APK: ", err)
}
pwaDir, err := ioutil.TempDir("", "tast-play-billing-pwa")
if err != nil {
s.Fatal("Failed to create temporary directory for Play Billing PWA: ", err)
}
f.pwaDir = pwaDir
for _, name := range pwaFiles {
pwaFilePath := filepath.Join(f.pwaDir, strings.TrimPrefix(name, "play_billing_"))
if err := fsutil.CopyFile(s.DataPath(name), pwaFilePath); err != nil {
s.Fatalf("Failed to copy extension file %q: %v", name, err)
}
}
assetLinks, ok := s.Var(assetLinksVar)
if !ok {
s.Fatal("Failed retrieving runtime variable: ", assetLinksVar)
}
wellKnownDirectory := filepath.Join(f.pwaDir, ".well-known")
if err := os.MkdirAll(wellKnownDirectory, 0700); err != nil {
s.Fatal("Failed to create the .well-known directory: ", err)
}
testFileLocation := filepath.Join(wellKnownDirectory, "assetlinks.json")
if err := ioutil.WriteFile(testFileLocation, []byte(assetLinks), 0644); err != nil {
s.Fatalf("Failed creating %q: %s", testFileLocation, err)
}
fs := http.FileServer(http.Dir(f.pwaDir))
f.pwaServer = &http.Server{Addr: fmt.Sprintf(":%v", localServerPort), Handler: fs}
go func() {
if err := f.pwaServer.ListenAndServe(); err != http.ErrServerClosed {
testing.ContextLog(ctx, "Failed to create local server: ", err)
}
}()
testApp, err := NewTestApp(ctx, cr, arcDevice)
if err != nil {
s.Fatal("Failed trying to setup test app: ", err)
}
return &FixtData{arcDevice, cr, testApp}
}
func (f *playBillingFixture) Reset(ctx context.Context) error {
// TODO: Ensure all PWA windows and ARC payment overlays are properly closed.
return nil
}
func (f *playBillingFixture) PreTest(ctx context.Context, s *testing.FixtTestState) {}
func (f *playBillingFixture) PostTest(ctx context.Context, s *testing.FixtTestState) {}
func (f *playBillingFixture) TearDown(ctx context.Context, s *testing.FixtState) {
if err := f.pwaServer.Shutdown(ctx); err != nil {
s.Log("Failed to shutdown PWA server: ", err)
}
if err := os.RemoveAll(f.pwaDir); err != nil {
s.Logf("Failed to remove PWA directory %q: %v", f.pwaDir, err)
}
}