blob: 8420e241572658c740107447b095d411faa9f863 [file] [log] [blame]
// Copyright 2019 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 usbprintertests provides utility functions for running tests with a
// USB printer.
package usbprintertests
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"chromiumos/tast/errors"
"chromiumos/tast/local/printing/document"
"chromiumos/tast/local/printing/lp"
"chromiumos/tast/local/printing/printer"
"chromiumos/tast/local/printing/usbprinter"
"chromiumos/tast/testing"
)
func usbPrinterURI(ctx context.Context, devInfo usbprinter.DevInfo) string {
return fmt.Sprintf("usb://%s/%s", devInfo.VID, devInfo.PID)
}
// RunPrintTest executes a test for the virtual USB printer defined by the
// given arguments. This tests that the printer is able to be configured, and
// produces the expected output at record when a print job is issued.
// toPrint and golden specify the paths to the file to be printed and the
// expected printer output.
func RunPrintTest(ctx context.Context, s *testing.State,
opts []usbprinter.Option, record, ppd, toPrint, golden string) {
if err := printer.ResetCups(ctx); err != nil {
s.Fatal("Failed to reset cupsd: ", err)
}
pr, err := usbprinter.Start(ctx, opts...)
if err != nil {
s.Fatal("Failed to attach virtual printer: ", err)
}
defer func(ctx context.Context) {
if err := pr.Stop(ctx); err != nil {
s.Error("Failed to stop virtual printer: ", err)
}
// Remove the recorded file. Ignore errors if the path doesn't exist.
if err := os.Remove(record); err != nil && !os.IsNotExist(err) {
s.Error("Failed to remove file: ", err)
}
}(ctx)
// If no PPD was provided, then the printer is an IPP-over-USB device
// for which we waited on autoconf; the name will have been stored in
// the PrinterInstance.
var foundPrinterName = pr.ConfiguredName
if ppd != "" {
// If a PPD is provided then we configure the printer ourselves.
foundPrinterName = "virtual-test"
if err := lp.CupsAddPrinter(ctx, foundPrinterName, usbPrinterURI(ctx, pr.DevInfo), ppd); err != nil {
s.Fatal("Failed to configure printer: ", err)
}
}
s.Log("Printer configured with name: ", foundPrinterName)
job, err := lp.CupsStartPrintJob(ctx, foundPrinterName, toPrint)
if err != nil {
s.Fatal("Failed to start printer: ", err)
}
s.Logf("Waiting for %s to complete", job)
if err = testing.Poll(ctx, func(ctx context.Context) error {
if done, err := lp.JobCompleted(ctx, foundPrinterName, job); err != nil {
return err
} else if !done {
return errors.Errorf("job %s is not done yet", job)
}
testing.ContextLogf(ctx, "Job %s is complete", job)
return nil
}, nil); err != nil {
s.Fatal("Print job didn't complete: ", err)
}
goldenData, err := ioutil.ReadFile(golden)
if err != nil {
s.Fatal("Failed to read golden file: ", err)
}
output, err := ioutil.ReadFile(record)
if err != nil {
s.Fatal("Failed to read output file: ", err)
}
if document.CleanContents(string(goldenData)) != document.CleanContents(string(output)) {
outFile := filepath.Base(golden)
outPath := filepath.Join(s.OutDir(), outFile)
if err := ioutil.WriteFile(outPath, output, 0644); err != nil {
s.Error("Failed to dump output: ", err)
}
s.Errorf("Printer output differs from expected: output saved to %q", outFile)
}
}