blob: f9731dc83c27550ff626cbd9ab0cd3c42d88569b [file] [log] [blame]
// Copyright 2020 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 crostini
import (
"context"
"fmt"
"time"
"chromiumos/tast/ctxutil"
"chromiumos/tast/errors"
"chromiumos/tast/local/chrome"
"chromiumos/tast/local/chrome/uiauto"
"chromiumos/tast/local/chrome/uiauto/nodewith"
"chromiumos/tast/local/chrome/uiauto/role"
"chromiumos/tast/local/coords"
"chromiumos/tast/local/crostini"
"chromiumos/tast/local/crostini/ui/terminalapp"
"chromiumos/tast/local/input"
"chromiumos/tast/local/screenshot"
"chromiumos/tast/local/vm"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: AppEmacs,
Desc: "Test Emacs in Terminal window",
Contacts: []string{"jinrongwu@google.com", "cros-containers-dev@google.com"},
Attr: []string{"group:mainline", "informational"},
Vars: append([]string{"keepState"}, screenshot.ScreenDiffVars...),
VarDeps: []string{"ui.gaiaPoolDefault"},
SoftwareDeps: []string{"chrome", "vm_host", "amd64"},
Params: []testing.Param{
// Parameters generated by params_test.go. DO NOT EDIT.
{
ExtraData: []string{crostini.GetContainerMetadataArtifact("buster", true), crostini.GetContainerRootfsArtifact("buster", true)},
ExtraSoftwareDeps: []string{"dlc"},
ExtraHardwareDeps: crostini.CrostiniAppTest,
Pre: crostini.StartedByDlcBusterLargeContainer(),
Timeout: 15 * time.Minute,
},
},
})
}
func AppEmacs(ctx context.Context, s *testing.State) {
tconn := s.PreValue().(crostini.PreData).TestAPIConn
cr := s.PreValue().(crostini.PreData).Chrome
keyboard := s.PreValue().(crostini.PreData).Keyboard
cont := s.PreValue().(crostini.PreData).Container
// Use a shortened context for test operations to reserve time for cleanup.
cleanupCtx := ctx
ctx, cancel := ctxutil.Shorten(ctx, 90*time.Second)
defer cancel()
defer crostini.RunCrostiniPostTest(cleanupCtx, s.PreValue().(crostini.PreData))
// Open Terminal app.
terminalApp, err := terminalapp.Launch(ctx, tconn)
if err != nil {
s.Fatal("Failed to open Terminal app: ", err)
}
restartIfError := true
defer func() {
// Restart Crostini in the end in case any error in the middle and Emacs is not closed.
// This also closes the Terminal window.
if restartIfError {
if err := terminalApp.RestartCrostini(keyboard, cont, cr.NormalizedUser())(cleanupCtx); err != nil {
s.Log("Failed to restart Crostini: ", err)
}
} else {
terminalApp.Exit(keyboard)(cleanupCtx)
}
}()
d, err := screenshot.NewDifferFromChrome(ctx, s, cr, screenshot.Config{DefaultOptions: screenshot.Options{WindowWidthDP: 666, WindowHeightDP: 714}})
if err != nil {
s.Fatal("Failed to start screen differ: ", err)
}
defer d.DieOnFailedDiffs()
if err := createFileWithEmacs(ctx, keyboard, terminalApp, tconn, cont, d); err != nil {
s.Fatal("Failed to create file with emacs in Terminal: ", err)
}
restartIfError = false
}
// createFileWithEmacs creates a file with emacs and types a string into it and save it in container.
func createFileWithEmacs(ctx context.Context, keyboard *input.KeyboardEventWriter, terminalApp *terminalapp.TerminalApp, tconn *chrome.TestConn, cont *vm.Container, d screenshot.Differ) error {
const (
testFile = "test.txt"
testString = "This is a test string"
)
// Anything animated like blinking cursors will break screendiffs.
cont.WriteFile(ctx, "~/.emacs", "(blink-cursor-mode 0)")
// Open emacs in Terminal.
// Avoid opening the splash screen since it means the screenshot will contain data like CPU architecture,
// which is terrible for screen diffing.
if err := terminalApp.RunCommand(keyboard, fmt.Sprintf("emacs --no-splash %s", testFile))(ctx); err != nil {
return errors.Wrap(err, "failed to run command 'emacs' in Terminal window")
}
ui := uiauto.New(tconn)
window := nodewith.Name("emacs@penguin").Role(role.Window).First()
// Left click left-top of the emacs window.
loc, err := ui.Location(ctx, window)
if err != nil {
return errors.Wrap(err, "failed to get the location of Emacs window")
}
if err := uiauto.Combine("Click, input, save and exit Emacs",
// Click left top to focus on the input area.
ui.MouseClickAtLocation(0, coords.Point{X: loc.Left, Y: loc.Top}),
// Type string.
keyboard.TypeAction(testString),
// Press ctrl+x and ctrl+s to save.
keyboard.AccelAction("ctrl+X"),
keyboard.AccelAction("ctrl+S"),
// After saving, wait for the "save" button to grey out.
d.DiffWindow(ctx, "emacs", screenshot.Retries(2)),
// Press ctrl+x and ctrl+c to and quit.
keyboard.AccelAction("ctrl+X"),
keyboard.AccelAction("ctrl+C"),
// Check window closed.
ui.WaitUntilGone(window))(ctx); err != nil {
return err
}
// Check the content of the test file.
if err := cont.CheckFileContent(ctx, testFile, testString+"\n"); err != nil {
return errors.Wrap(err, "failed to verify the content of the file")
}
return nil
}