forked from shipperizer/ldap
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathprotocol_test.go
More file actions
184 lines (174 loc) · 4.99 KB
/
Copy pathprotocol_test.go
File metadata and controls
184 lines (174 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package ldap
import (
"bytes"
"testing"
ber "github.com/go-asn1-ber/asn1-ber"
)
// redecode serializes a packet and parses it again. DecodeControl runs on
// controls parsed from the wire, not on in-memory packets, and the original
// unchecked type assertions / child indexing only panic on wire-decoded
// input. Round-tripping through bytes reproduces that path faithfully.
func redecode(p *ber.Packet) *ber.Packet {
if p == nil {
return nil
}
return ber.DecodePacket(p.Bytes())
}
func controlSeq(children ...*ber.Packet) *ber.Packet {
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
for _, c := range children {
seq.AppendChild(c)
}
return seq
}
func octet(s string) *ber.Packet {
return ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, s, "")
}
// pagingControl builds a paging control whose value wraps the supplied inner
// sequence, mirroring ControlPaging.Encode() so the byte layout matches the
// real wire format.
func pagingControl(inner *ber.Packet) *ber.Packet {
ctrl := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
ctrl.AppendChild(octet(ControlTypePaging))
value := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Paging)")
value.AppendChild(inner)
ctrl.AppendChild(value)
return ctrl
}
func searchValueSeq(children ...*ber.Packet) *ber.Packet {
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value")
for _, c := range children {
seq.AppendChild(c)
}
return seq
}
func integer(v uint64) *ber.Packet {
return ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, v, "")
}
func TestDecodeControl(t *testing.T) {
tests := []struct {
name string
packet *ber.Packet
wantErr bool
check func(t *testing.T, c Control)
}{
{
name: "string control, type only",
packet: redecode((&ControlString{ControlType: "1.2.3.4"}).Encode()),
check: func(t *testing.T, c Control) {
cs, ok := c.(*ControlString)
if !ok {
t.Fatalf("got %T, want *ControlString", c)
}
if cs.ControlType != "1.2.3.4" {
t.Errorf("ControlType = %q, want 1.2.3.4", cs.ControlType)
}
if cs.Criticality {
t.Errorf("Criticality = true, want false")
}
if cs.ControlValue != "" {
t.Errorf("ControlValue = %q, want empty", cs.ControlValue)
}
},
},
{
name: "string control, type and value",
packet: redecode((&ControlString{ControlType: "1.2.3.4", ControlValue: "payload"}).Encode()),
check: func(t *testing.T, c Control) {
cs := c.(*ControlString)
if cs.Criticality {
t.Errorf("Criticality = true, want false")
}
if cs.ControlValue != "payload" {
t.Errorf("ControlValue = %q, want payload", cs.ControlValue)
}
},
},
{
name: "string control, type criticality and value",
packet: redecode((&ControlString{ControlType: "1.2.3.4", Criticality: true, ControlValue: "payload"}).Encode()),
check: func(t *testing.T, c Control) {
cs := c.(*ControlString)
if !cs.Criticality {
t.Errorf("Criticality = false, want true")
}
if cs.ControlValue != "payload" {
t.Errorf("ControlValue = %q, want payload", cs.ControlValue)
}
},
},
{
name: "paging control round-trip",
packet: redecode((&ControlPaging{PagingSize: 100, Cookie: []byte("cookie")}).Encode()),
check: func(t *testing.T, c Control) {
cp, ok := c.(*ControlPaging)
if !ok {
t.Fatalf("got %T, want *ControlPaging", c)
}
if cp.PagingSize != 100 {
t.Errorf("PagingSize = %d, want 100", cp.PagingSize)
}
if !bytes.Equal(cp.Cookie, []byte("cookie")) {
t.Errorf("Cookie = %q, want cookie", cp.Cookie)
}
},
},
{
name: "nil packet",
packet: nil,
wantErr: true,
},
{
name: "empty control sequence",
packet: redecode(controlSeq()),
wantErr: true,
},
{
name: "control type not an octet string",
packet: redecode(controlSeq(integer(5))),
wantErr: true,
},
{
name: "criticality not a boolean",
packet: redecode(controlSeq(
octet("1.2.3.4"),
octet("not-a-bool"),
octet("value"),
)),
wantErr: true,
},
{
name: "paging value sequence too short",
packet: redecode(pagingControl(searchValueSeq(integer(10)))),
wantErr: true,
},
{
name: "paging size exceeds uint32",
packet: redecode(pagingControl(searchValueSeq(integer(uint64(1)<<32), octet("ck")))),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := DecodeControl(tt.packet)
if tt.wantErr {
if err == nil {
t.Fatalf("DecodeControl() error = nil, want error")
}
if c != nil {
t.Errorf("DecodeControl() control = %v, want nil on error", c)
}
return
}
if err != nil {
t.Fatalf("DecodeControl() unexpected error: %v", err)
}
if c == nil {
t.Fatalf("DecodeControl() control = nil, want non-nil")
}
if tt.check != nil {
tt.check(t, c)
}
})
}
}