PrintToVeraeTimeStamp/internal/winprint/ipp_test.go

88 lines
2.7 KiB
Go

package winprint
import (
"bytes"
"net"
"net/http"
"os"
"path/filepath"
"testing"
"time"
"github.com/OpenPrinting/goipp"
)
func freeAddr(t *testing.T) string {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
a := l.Addr().String()
l.Close()
return a
}
func call(t *testing.T, addr string, m *goipp.Message, doc []byte) *goipp.Message {
b, err := m.EncodeBytes()
if err != nil {
t.Fatal(err)
}
b = append(b, doc...)
res, err := http.Post("http://"+addr+"/ipp/print", goipp.ContentType, bytes.NewReader(b))
if err != nil {
t.Fatal(err)
}
defer res.Body.Close()
var out goipp.Message
if err := out.Decode(res.Body); err != nil {
t.Fatal(err)
}
return &out
}
func req(op goipp.Op, addr string) *goipp.Message {
m := goipp.NewRequest(goipp.DefaultVersion, op, 1)
m.Operation.Add(goipp.MakeAttribute("attributes-charset", goipp.TagCharset, goipp.String("utf-8")))
m.Operation.Add(goipp.MakeAttribute("attributes-natural-language", goipp.TagLanguage, goipp.String("en")))
m.Operation.Add(goipp.MakeAttribute("printer-uri", goipp.TagURI, goipp.String("ipp://"+addr+"/ipp/print")))
return m
}
func TestIPPPrintJobFlow(t *testing.T) {
addr := freeAddr(t)
got := make(chan Job, 1)
s := &IPPServer{Addr: addr, SpoolDir: t.TempDir(), Process: func(j Job) error { got <- j; return nil }}
go s.ListenAndServe()
time.Sleep(200 * time.Millisecond)
r := call(t, addr, req(goipp.OpGetPrinterAttributes, addr), nil)
if goipp.Status(r.Code) != goipp.StatusOk || len(r.Printer) < 40 {
t.Fatalf("gpa status=%v attrs=%d", goipp.Status(r.Code), len(r.Printer))
}
pj := req(goipp.OpPrintJob, addr)
pj.Operation.Add(goipp.MakeAttribute("requesting-user-name", goipp.TagName, goipp.String("george")))
pj.Operation.Add(goipp.MakeAttribute("job-name", goipp.TagName, goipp.String("Contract.docx")))
pj.Operation.Add(goipp.MakeAttribute("document-format", goipp.TagMimeType, goipp.String("application/pdf")))
doc := []byte("%PDF-1.4\n%fake\n")
r = call(t, addr, pj, doc)
if goipp.Status(r.Code) != goipp.StatusOk {
t.Fatalf("print-job status %v", goipp.Status(r.Code))
}
select {
case j := <-got:
b, _ := os.ReadFile(j.Path)
if !bytes.Equal(b, doc) || j.Title != "Contract.docx" || j.User != "george" || filepath.Ext(j.Path) != ".pdf" {
t.Fatalf("bad job %+v body=%q", j, b)
}
case <-time.After(3 * time.Second):
t.Fatal("job not processed")
}
bad := req(goipp.OpPrintJob, addr)
bad.Operation.Add(goipp.MakeAttribute("document-format", goipp.TagMimeType, goipp.String("image/urf")))
r = call(t, addr, bad, []byte("x"))
if goipp.Status(r.Code) != goipp.StatusErrorDocumentFormatNotSupported {
t.Fatalf("expected format error, got %v", goipp.Status(r.Code))
}
}