blob: 60e197ae0878144df3f7f32b40c9a9015e7a88f2 [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"
"regexp"
"time"
"chromiumos/tast/local/crostini"
"chromiumos/tast/local/testexec"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: PulseAudioBasic,
Desc: "Runs a basic test on the container's pusleaudio service using a pre-built crostini image",
Contacts: []string{"paulhsia@chromium.org", "cros-containers-dev@google.com", "chromeos-audio-bugs@google.com"},
Attr: []string{"group:mainline", "informational"},
Vars: []string{"keepState"},
SoftwareDeps: []string{"chrome", "vm_host"},
Params: []testing.Param{
// Parameters generated by params_test.go. DO NOT EDIT.
{
Name: "amd64_stable",
ExtraData: []string{"crostini_vm_amd64.zip", "crostini_test_container_metadata_buster_amd64.tar.xz", "crostini_test_container_rootfs_buster_amd64.tar.xz"},
ExtraSoftwareDeps: []string{"amd64"},
ExtraHardwareDeps: crostini.CrostiniStable,
Pre: crostini.StartedByComponentBuster(),
Timeout: 7 * time.Minute,
}, {
Name: "amd64_unstable",
ExtraAttr: []string{"informational"},
ExtraData: []string{"crostini_vm_amd64.zip", "crostini_test_container_metadata_buster_amd64.tar.xz", "crostini_test_container_rootfs_buster_amd64.tar.xz"},
ExtraSoftwareDeps: []string{"amd64"},
ExtraHardwareDeps: crostini.CrostiniUnstable,
Pre: crostini.StartedByComponentBuster(),
Timeout: 7 * time.Minute,
}, {
Name: "arm_stable",
ExtraData: []string{"crostini_vm_arm.zip", "crostini_test_container_metadata_buster_arm.tar.xz", "crostini_test_container_rootfs_buster_arm.tar.xz"},
ExtraSoftwareDeps: []string{"arm"},
ExtraHardwareDeps: crostini.CrostiniStable,
Pre: crostini.StartedByComponentBuster(),
Timeout: 7 * time.Minute,
}, {
Name: "arm_unstable",
ExtraAttr: []string{"informational"},
ExtraData: []string{"crostini_vm_arm.zip", "crostini_test_container_metadata_buster_arm.tar.xz", "crostini_test_container_rootfs_buster_arm.tar.xz"},
ExtraSoftwareDeps: []string{"arm"},
ExtraHardwareDeps: crostini.CrostiniUnstable,
Pre: crostini.StartedByComponentBuster(),
Timeout: 7 * time.Minute,
},
},
})
}
var alsaSinksPattern = regexp.MustCompile("1\talsa_output.hw_0_0\tmodule-alsa-sink.c\ts16le 2ch 48000Hz\t(IDLE|SUSPENDED)\n")
func PulseAudioBasic(ctx context.Context, s *testing.State) {
cont := s.PreValue().(crostini.PreData).Container
defer crostini.RunCrostiniPostTest(ctx, s.PreValue().(crostini.PreData))
s.Log("List ALSA output devices")
if err := cont.Command(ctx, "aplay", "-l").Run(testexec.DumpLogOnError); err != nil {
s.Fatal("Failed to list ALSA output devices: ", err)
}
for _, stopOpt := range []string{"stop", "restart", "kill"} {
// Stops pulseaudio server by `stopOpt` and restarts the server by a playback stream.
s.Run(ctx, stopOpt, func(ctx context.Context, s *testing.State) {
s.Logf("%s pulseaudio service", stopOpt)
// Use systemctl to control pulseaudio service.
if err := cont.Command(ctx, "systemctl", " --user", stopOpt, "pulseaudio").Run(testexec.DumpLogOnError); err != nil {
s.Fatalf("Failed to %s pulseaudio: %v", stopOpt, err)
}
testing.ContextLog(ctx, "Play zeros with ALSA device")
if err := cont.Command(ctx, "aplay", "-f", "dat", "-d", " 3", "/dev/zero").Run(testexec.DumpLogOnError); err != nil {
s.Fatal("Failed to playback with ALSA devices: ", err)
}
if out, err := cont.Command(ctx, "pactl", "list", "sinks", "short").Output(testexec.DumpLogOnError); err != nil {
s.Fatal("Failed to list pulseaudio sinks: ", err)
} else if !alsaSinksPattern.Match(out) {
s.Fatalf("Failed to load ALSA device to pulseaudio: %q", string(out))
}
})
}
}