88 lines
2.7 KiB
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))
|
|
}
|
|
}
|