Skip to content

Commit

Permalink
added basic test templates for request and response de and encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
phin1x committed Jun 25, 2023
1 parent daa1225 commit 4f0b514
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 65 deletions.
30 changes: 8 additions & 22 deletions attribute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ipp

import (
"bytes"
"github.com/stretchr/testify/assert"
"testing"
)

Expand Down Expand Up @@ -42,25 +43,18 @@ var attributeTestCases = []struct {
},
}

func TestAttributeEncoding(t *testing.T) {
func TestAttributeDecoder_Decode(t *testing.T) {
buf := new(bytes.Buffer)
enc := NewAttributeEncoder(buf)

for _, c := range attributeTestCases {
if err := enc.Encode(c.Attribute, c.Value); err != nil {
t.Errorf("error while encoding attribute %s with value %v: %v", c.Attribute, c.Value, err)
}

result := buf.Bytes()
if !bytes.Equal(result, c.Bytes) {
t.Errorf("encoding result is not correct, expected %v, got %v", c.Bytes, result)
}

assert.Nil(t, enc.Encode(c.Attribute, c.Value))
assert.Equal(t, buf.Bytes(), c.Bytes, "encoding result is not correct")
buf.Reset()
}
}

func TestAttributeDecoder(t *testing.T) {
func TestAttributeEncoder_Encode(t *testing.T) {
buf := new(bytes.Buffer)
dec := NewAttributeDecoder(buf)

Expand All @@ -70,17 +64,9 @@ func TestAttributeDecoder(t *testing.T) {
buf.Write(c.Bytes[1:])

attr, err := dec.Decode(tag)
if err != nil {
t.Errorf("error while decoding bytes %v: %v", c.Bytes, err)
}

if attr.Name != c.Attribute {
t.Errorf("decoded attribute is not correct, expected %v, got %v", c.Attribute, attr.Name)
}

if attr.Value != c.Value {
t.Errorf("decoded value is not correct, expected %v, got %v", c.Attribute, attr.Name)
}
assert.Nil(t, err)
assert.Equal(t, c.Attribute, attr.Name, "decoded attribute is not correct")
assert.Equal(t, c.Value, attr.Value, "decoded value is not correct")

buf.Reset()
}
Expand Down
6 changes: 3 additions & 3 deletions cups-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func NewCUPSClient(host string, port int, username, password string, useTLS bool
return &CUPSClient{ippClient}
}

// NewCUPSClient creates a new cups ipp client with given Adapter
// NewCUPSClientWithAdapter creates a new cups ipp client with given Adapter
func NewCUPSClientWithAdapter(username string, adapter Adapter) *CUPSClient {
ippClient := NewIPPClientWithAdapter(username, adapter)
return &CUPSClient{ippClient}
Expand Down Expand Up @@ -177,7 +177,7 @@ func (c *CUPSClient) CreatePrinter(name, deviceURI, ppd string, shared bool, err
req.PrinterAttributes[AttributeDeviceURI] = deviceURI
req.PrinterAttributes[AttributePrinterInfo] = information
req.PrinterAttributes[AttributePrinterLocation] = location
req.PrinterAttributes[AttributePrinterErrorPolicy] = string(errorPolicy)
req.PrinterAttributes[AttributePrinterErrorPolicy] = errorPolicy

_, err := c.SendRequest(c.adapter.GetHttpUri("admin", ""), req, nil)
return err
Expand Down Expand Up @@ -217,7 +217,7 @@ func (c *CUPSClient) SetPrinterIsShared(printer string, shared bool) error {
func (c *CUPSClient) SetPrinterErrorPolicy(printer string, errorPolicy string) error {
req := NewRequest(OperationCupsAddModifyPrinter, 1)
req.OperationAttributes[AttributePrinterURI] = c.getPrinterUri(printer)
req.PrinterAttributes[AttributePrinterErrorPolicy] = string(errorPolicy)
req.PrinterAttributes[AttributePrinterErrorPolicy] = errorPolicy

_, err := c.SendRequest(c.adapter.GetHttpUri("admin", ""), req, nil)
return err
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/phin1x/go-ipp

go 1.13

require github.com/stretchr/testify v1.8.4 // indirect
2 changes: 1 addition & 1 deletion ipp-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (c *IPPClient) GetJobAttributes(jobID int, attributes []string) (Attributes
// GetJobs returns jobs from a printer or class
func (c *IPPClient) GetJobs(printer, class string, whichJobs string, myJobs bool, firstJobId, limit int, attributes []string) (map[int]Attributes, error) {
req := NewRequest(OperationGetJobs, 1)
req.OperationAttributes[AttributeWhichJobs] = string(whichJobs)
req.OperationAttributes[AttributeWhichJobs] = whichJobs
req.OperationAttributes[AttributeMyJobs] = myJobs

if printer != "" {
Expand Down
27 changes: 15 additions & 12 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,28 @@ func (r *Request) Encode() ([]byte, error) {
return nil, err
}

if err := binary.Write(buf, binary.BigEndian, int8(TagOperation)); err != nil {
if err := binary.Write(buf, binary.BigEndian, TagOperation); err != nil {
return nil, err
}

if err := enc.Encode(AttributeCharset, Charset); err != nil {
return nil, err
if r.OperationAttributes == nil {
r.OperationAttributes = make(map[string]interface{}, 2)
}

if err := enc.Encode(AttributeNaturalLanguage, CharsetLanguage); err != nil {
return nil, err
if _, found := r.OperationAttributes[AttributeCharset]; !found {
r.OperationAttributes[AttributeCharset] = Charset
}

if len(r.OperationAttributes) > 0 {
if err := r.encodeOperationAttributes(enc); err != nil {
return nil, err
}
if _, found := r.OperationAttributes[AttributeNaturalLanguage]; !found {
r.OperationAttributes[AttributeNaturalLanguage] = CharsetLanguage
}

if err := r.encodeOperationAttributes(enc); err != nil {
return nil, err
}

if len(r.JobAttributes) > 0 {
if err := binary.Write(buf, binary.BigEndian, int8(TagJob)); err != nil {
if err := binary.Write(buf, binary.BigEndian, TagJob); err != nil {
return nil, err
}
for attr, value := range r.JobAttributes {
Expand All @@ -88,7 +90,7 @@ func (r *Request) Encode() ([]byte, error) {
}

if len(r.PrinterAttributes) > 0 {
if err := binary.Write(buf, binary.BigEndian, int8(TagPrinter)); err != nil {
if err := binary.Write(buf, binary.BigEndian, TagPrinter); err != nil {
return nil, err
}
for attr, value := range r.PrinterAttributes {
Expand All @@ -98,7 +100,7 @@ func (r *Request) Encode() ([]byte, error) {
}
}

if err := binary.Write(buf, binary.BigEndian, int8(TagEnd)); err != nil {
if err := binary.Write(buf, binary.BigEndian, TagEnd); err != nil {
return nil, err
}

Expand Down Expand Up @@ -127,6 +129,7 @@ func (r *Request) encodeOperationAttributes(enc *AttributeEncoder) error {
return err
}
}

return nil
}

Expand Down
59 changes: 59 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package ipp

import (
"bytes"
"github.com/stretchr/testify/assert"
"testing"
)

var requestTestCases = []struct {
Request Request
Bytes []byte
// some test cases are only for encoding, skip them in decoding tests
SkipDecoding bool
}{
{
Request: Request{
ProtocolVersionMajor: ProtocolVersionMajor,
ProtocolVersionMinor: ProtocolVersionMinor,
Operation: OperationPrintJob,
RequestId: 12345,
},
Bytes: []byte{2, 0, 0, 2, 0, 0, 48, 57, 1, 71, 0, 18, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 45, 99, 104, 97, 114, 115, 101, 116, 0, 5, 117, 116, 102, 45, 56, 72, 0, 27, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 45, 110, 97, 116, 117, 114, 97, 108, 45, 108, 97, 110, 103, 117, 97, 103, 101, 0, 5, 101, 110, 45, 85, 83, 3},
SkipDecoding: true,
},
{
Request: Request{
ProtocolVersionMajor: ProtocolVersionMajor,
ProtocolVersionMinor: ProtocolVersionMinor,
Operation: OperationPrintJob,
RequestId: 12345,
OperationAttributes: map[string]interface{}{
AttributeCharset: Charset,
AttributeNaturalLanguage: CharsetLanguage,
},
},
Bytes: []byte{2, 0, 0, 2, 0, 0, 48, 57, 1, 71, 0, 18, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 45, 99, 104, 97, 114, 115, 101, 116, 0, 5, 117, 116, 102, 45, 56, 72, 0, 27, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 45, 110, 97, 116, 117, 114, 97, 108, 45, 108, 97, 110, 103, 117, 97, 103, 101, 0, 5, 101, 110, 45, 85, 83, 3},
SkipDecoding: true,
},
}

func TestRequest_Encode(t *testing.T) {
for _, c := range requestTestCases {
data, err := c.Request.Encode()
assert.Nil(t, err)
assert.Equal(t, c.Bytes, data, "encoded request is not correct")
}
}

func TestRequestDecoder_Decode(t *testing.T) {
for _, c := range requestTestCases {
if c.SkipDecoding {
continue
}

request, err := NewRequestDecoder(bytes.NewReader(c.Bytes)).Decode(nil)
assert.Nil(t, err)
assert.Equal(t, &c.Request, request, "decoded request is not correct")
}
}
90 changes: 63 additions & 27 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,44 +74,37 @@ func (r *Response) Encode() ([]byte, error) {
return nil, err
}

if err := binary.Write(buf, binary.BigEndian, int8(TagOperation)); err != nil {
if err := binary.Write(buf, binary.BigEndian, TagOperation); err != nil {
return nil, err
}

if err := enc.Encode(AttributeCharset, Charset); err != nil {
return nil, err
if r.OperationAttributes == nil {
r.OperationAttributes = make(Attributes, 0)
}

if err := enc.Encode(AttributeNaturalLanguage, CharsetLanguage); err != nil {
return nil, err
if _, found := r.OperationAttributes[AttributeCharset]; !found {
r.OperationAttributes[AttributeCharset] = []Attribute{
{
Value: Charset,
},
}
}

if len(r.OperationAttributes) > 0 {
for name, attr := range r.OperationAttributes {
if len(attr) == 0 {
continue
}

values := make([]interface{}, len(attr))
for i, v := range attr {
values[i] = v.Value
}

if len(values) == 1 {
if err := enc.Encode(name, values[0]); err != nil {
return nil, err
}
} else {
if err := enc.Encode(name, values); err != nil {
return nil, err
}
}
if _, found := r.OperationAttributes[AttributeNaturalLanguage]; !found {
r.OperationAttributes[AttributeNaturalLanguage] = []Attribute{
{
Value: CharsetLanguage,
},
}
}

if err := r.encodeOperationAttributes(enc); err != nil {
return nil, err
}

if len(r.PrinterAttributes) > 0 {
for _, printerAttr := range r.PrinterAttributes {
if err := binary.Write(buf, binary.BigEndian, int8(TagPrinter)); err != nil {
if err := binary.Write(buf, binary.BigEndian, TagPrinter); err != nil {
return nil, err
}

Expand Down Expand Up @@ -140,7 +133,7 @@ func (r *Response) Encode() ([]byte, error) {

if len(r.JobAttributes) > 0 {
for _, jobAttr := range r.JobAttributes {
if err := binary.Write(buf, binary.BigEndian, int8(TagJob)); err != nil {
if err := binary.Write(buf, binary.BigEndian, TagJob); err != nil {
return nil, err
}

Expand Down Expand Up @@ -174,6 +167,49 @@ func (r *Response) Encode() ([]byte, error) {
return buf.Bytes(), nil
}

func (r *Response) encodeOperationAttributes(enc *AttributeEncoder) error {
ordered := []string{
AttributeCharset,
AttributeNaturalLanguage,
AttributePrinterURI,
AttributeJobID,
}

for _, name := range ordered {
if attr, ok := r.OperationAttributes[name]; ok {
delete(r.OperationAttributes, name)
if err := encodeOperationAttribute(enc, name, attr); err != nil {
return err
}
}
}

for name, attr := range r.OperationAttributes {
if err := encodeOperationAttribute(enc, name, attr); err != nil {
return err
}
}

return nil
}

func encodeOperationAttribute(enc *AttributeEncoder, name string, attr []Attribute) error {
if len(attr) == 0 {
return nil
}

values := make([]interface{}, len(attr))
for i, v := range attr {
values[i] = v.Value
}

if len(values) == 1 {
return enc.Encode(name, values[0])
}

return enc.Encode(name, values)
}

// ResponseDecoder reads and decodes a response from a stream
type ResponseDecoder struct {
reader io.Reader
Expand Down
Loading

0 comments on commit 4f0b514

Please sign in to comment.