Skip to content

Commit f46ebea

Browse files
committed
add tests
1 parent 04d88a2 commit f46ebea

File tree

1 file changed

+315
-7
lines changed

1 file changed

+315
-7
lines changed

caldav/server_test.go

Lines changed: 315 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66
"io"
7-
"io/ioutil"
87
"net/http/httptest"
98
"strings"
109
"testing"
@@ -38,7 +37,7 @@ func TestPropFindSupportedCalendarComponent(t *testing.T) {
3837

3938
res := w.Result()
4039
defer res.Body.Close()
41-
data, err := ioutil.ReadAll(res.Body)
40+
data, err := io.ReadAll(res.Body)
4241
if err != nil {
4342
t.Error(err)
4443
}
@@ -73,7 +72,7 @@ func TestPropFindRoot(t *testing.T) {
7372

7473
res := w.Result()
7574
defer res.Body.Close()
76-
data, err := ioutil.ReadAll(res.Body)
75+
data, err := io.ReadAll(res.Body)
7776
if err != nil {
7877
t.Error(err)
7978
}
@@ -128,7 +127,7 @@ func TestMultiCalendarBackend(t *testing.T) {
128127

129128
res := w.Result()
130129
defer res.Body.Close()
131-
data, err := ioutil.ReadAll(res.Body)
130+
data, err := io.ReadAll(res.Body)
132131
if err != nil {
133132
t.Error(err)
134133
}
@@ -147,7 +146,7 @@ func TestMultiCalendarBackend(t *testing.T) {
147146

148147
res = w.Result()
149148
defer res.Body.Close()
150-
data, err = ioutil.ReadAll(res.Body)
149+
data, err = io.ReadAll(res.Body)
151150
if err != nil {
152151
t.Error(err)
153152
}
@@ -167,7 +166,7 @@ func TestMultiCalendarBackend(t *testing.T) {
167166

168167
res = w.Result()
169168
defer res.Body.Close()
170-
data, err = ioutil.ReadAll(res.Body)
169+
data, err = io.ReadAll(res.Body)
171170
if err != nil {
172171
t.Error(err)
173172
}
@@ -177,6 +176,311 @@ func TestMultiCalendarBackend(t *testing.T) {
177176
}
178177
}
179178

179+
var propFindAllProp = `
180+
<?xml version="1.0" encoding="utf-8" ?>
181+
<D:propfind xmlns:D="DAV:">
182+
<D:allprop/>
183+
</D:propfind>
184+
`
185+
186+
var reportTest1 = `
187+
<?xml version="1.0" encoding="utf-8"?>
188+
<C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav">
189+
<D:prop xmlns:D="DAV:">
190+
<D:getetag/>
191+
<D:getcontenttype/>
192+
<D:getcontentlength/>
193+
<D:getlastmodified/>
194+
<C:calendar-data/>
195+
</D:prop>
196+
<C:filter>
197+
<C:comp-filter name="VCALENDAR">
198+
<C:comp-filter name="VEVENT"/>
199+
</C:comp-filter>
200+
</C:filter>
201+
</C:calendar-query>
202+
`
203+
204+
var propFindTest1 = `
205+
<?xml version="1.0" encoding="UTF-8"?>
206+
<A:propfind xmlns:A="DAV:">
207+
<A:prop>
208+
<B:calendar-home-set xmlns:B="urn:ietf:params:xml:ns:caldav"/>
209+
<B:calendar-user-address-set xmlns:B="urn:ietf:params:xml:ns:caldav"/>
210+
<B:max-attendees-per-instance xmlns:B="urn:ietf:params:xml:ns:caldav"/>
211+
<A:principal-collection-set/>
212+
<A:principal-URL/>
213+
<A:resource-id/>
214+
<A:supported-report-set/>
215+
<B:supported-calendar-component-set xmlns:B="urn:ietf:params:xml:ns:caldav"/>
216+
<B:max-resource-size xmlns:B="urn:ietf:params:xml:ns:caldav"/>
217+
<B:calendar-timezone xmlns:B="urn:ietf:params:xml:ns:caldav"/>
218+
<A:current-user-principal/>
219+
<A:displayname/>
220+
<B:calendar-description xmlns:B="urn:ietf:params:xml:ns:caldav"/>
221+
<B:calendar-data xmlns:B="urn:ietf:params:xml:ns:caldav"/>
222+
<A:resourcetype/>
223+
<A:getcontenttype/>
224+
<A:getetag/>
225+
</A:prop>
226+
</A:propfind>
227+
`
228+
229+
var calendarTestData1 = `
230+
BEGIN:VCALENDAR
231+
VERSION:2.0
232+
PRODID:-//Example Corp.//CalDAV Client//EN
233+
BEGIN:VTIMEZONE
234+
LAST-MODIFIED:20040110T032845Z
235+
TZID:US/Eastern
236+
BEGIN:DAYLIGHT
237+
DTSTART:20000404T020000
238+
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
239+
TZNAME:EDT
240+
TZOFFSETFROM:-0500
241+
TZOFFSETTO:-0400
242+
END:DAYLIGHT
243+
BEGIN:STANDARD
244+
DTSTART:20001026T020000
245+
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
246+
TZNAME:EST
247+
TZOFFSETFROM:-0400
248+
TZOFFSETTO:-0500
249+
END:STANDARD
250+
END:VTIMEZONE
251+
BEGIN:VEVENT
252+
ATTENDEE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:[email protected]
253+
ATTENDEE;PARTSTAT=NEEDS-ACTION:mailto:[email protected]
254+
DTSTAMP:20060206T001220Z
255+
DTSTART;TZID=US/Eastern:20060104T100000
256+
DURATION:PT1H
257+
LAST-MODIFIED:20060206T001330Z
258+
ORGANIZER:mailto:[email protected]
259+
SEQUENCE:1
260+
STATUS:TENTATIVE
261+
SUMMARY:Event #3
262+
263+
264+
END:VEVENT
265+
END:VCALENDAR
266+
`
267+
268+
func TestPropFindAllPropAndQuery(t *testing.T) {
269+
calendar := Calendar{
270+
Description: "This is a description which SHOULD NOT be returned in allprop",
271+
Path: "/user/calendars/default/",
272+
SupportedComponentSet: []string{"VEVENT", "VTODO"},
273+
}
274+
cal, err := ical.NewDecoder(strings.NewReader(calendarTestData1)).Decode()
275+
if err != nil {
276+
t.Fatal(err)
277+
}
278+
object := CalendarObject{
279+
Path: "/user/calendars/default/DC6C50A017428C5216A2F1CD.ics",
280+
Data: cal,
281+
ETag: "191382932849",
282+
}
283+
handler := Handler{Backend: testBackend{
284+
calendars: []Calendar{calendar},
285+
objectMap: map[string][]CalendarObject{
286+
calendar.Path: []CalendarObject{object},
287+
},
288+
}}
289+
290+
req := httptest.NewRequest("PROPFIND", "/user/calendars/default/", strings.NewReader(propFindAllProp))
291+
req.Header.Set("Content-Type", "application/xml")
292+
req.Header.Set("Depth", "0")
293+
w := httptest.NewRecorder()
294+
handler.ServeHTTP(w, req)
295+
296+
res := w.Result()
297+
defer res.Body.Close()
298+
data, err := io.ReadAll(res.Body)
299+
if err != nil {
300+
t.Fatal(err)
301+
}
302+
resp := string(data)
303+
if !strings.Contains(resp, "<resourcetype xmlns=\"DAV:\">") {
304+
t.Fatalf("want resourcetype prop in allprop")
305+
} else if !strings.Contains(resp, "<collection xmlns=\"DAV:\">") {
306+
t.Fatalf("want collection resourcetype")
307+
} else if !strings.Contains(resp, "<calendar xmlns=\"urn:ietf:params:xml:ns:caldav\">") {
308+
t.Fatalf("expect calendar resourcetype")
309+
} else if strings.Contains(resp, "<calendar-description xmlns=\"urn:ietf:params:xml:ns:caldav\">") {
310+
t.Fatalf("do not want calendar-description in allprop")
311+
} else if strings.Contains(resp, "DC6C50A017428C5216A2F1CD.ics") {
312+
t.Fatalf("do not want children if Depth: 0")
313+
}
314+
315+
req = httptest.NewRequest("PROPFIND", "/user/calendars/default/", strings.NewReader(propFindAllProp))
316+
req.Header.Set("Content-Type", "application/xml")
317+
req.Header.Set("Depth", "1")
318+
w = httptest.NewRecorder()
319+
handler.ServeHTTP(w, req)
320+
321+
res = w.Result()
322+
defer res.Body.Close()
323+
data, err = io.ReadAll(res.Body)
324+
if err != nil {
325+
t.Fatal(err)
326+
}
327+
resp = string(data)
328+
if !strings.Contains(resp, fmt.Sprintf("<href>%s</href>", object.Path)) {
329+
t.Fatalf("want child href in allprop")
330+
} else if !strings.Contains(resp, object.ETag) {
331+
t.Fatalf("want child ETag in allprop")
332+
} else if !strings.Contains(resp, "<getcontenttype xmlns=\"DAV:\">text/calendar</getcontenttype>") {
333+
t.Fatalf("want child getcontenttype in allprop")
334+
} else if strings.Contains(resp, "<calendar-data xmlns=\"urn:ietf:params:xml:ns:caldav\">") {
335+
t.Fatalf("do not want calendar-data in allprop")
336+
}
337+
338+
req = httptest.NewRequest("REPORT", "/user/calendars/default/", strings.NewReader(reportTest1))
339+
req.Header.Set("Content-Type", "application/xml")
340+
w = httptest.NewRecorder()
341+
handler.ServeHTTP(w, req)
342+
343+
res = w.Result()
344+
defer res.Body.Close()
345+
data, err = io.ReadAll(res.Body)
346+
if err != nil {
347+
t.Fatal(err)
348+
}
349+
resp = string(data)
350+
if !strings.Contains(resp, fmt.Sprintf("<href>%s</href>", object.Path)) {
351+
t.Fatalf("want child href in REPORT")
352+
} else if !strings.Contains(resp, object.ETag) {
353+
t.Fatalf("want child ETag in REPORT")
354+
} else if !strings.Contains(resp, "<getcontenttype xmlns=\"DAV:\">text/calendar</getcontenttype>") {
355+
t.Fatalf("want child getcontenttype in REPORT")
356+
} else if !strings.Contains(resp, "<calendar-data xmlns=\"urn:ietf:params:xml:ns:caldav\">") {
357+
t.Fatalf("do want calendar-data in REPORT")
358+
} else if !strings.Contains(resp, "UID:[email protected]") {
359+
t.Fatalf("calendar-data improperly returned")
360+
}
361+
362+
req = httptest.NewRequest("PROPFIND", object.Path, strings.NewReader(propFindTest1))
363+
req.Header.Set("Content-Type", "application/xml")
364+
w = httptest.NewRecorder()
365+
handler.ServeHTTP(w, req)
366+
367+
res = w.Result()
368+
defer res.Body.Close()
369+
data, err = io.ReadAll(res.Body)
370+
if err != nil {
371+
t.Fatal(err)
372+
}
373+
resp = string(data)
374+
if strings.Contains(resp, "UID:[email protected]") {
375+
t.Fatalf("do not want calendar data in PROPFIND")
376+
} else if !strings.Contains(resp, object.ETag) {
377+
t.Fatalf("want child ETag in PROPFIND")
378+
} else if !strings.Contains(resp, "<getcontenttype xmlns=\"DAV:\">text/calendar</getcontenttype>") {
379+
t.Fatalf("want child getcontenttype in PROPFIND")
380+
}
381+
}
382+
383+
var calendarTestData2 = `
384+
BEGIN:VCALENDAR
385+
VERSION:2.0
386+
PRODID:-//Example Corp.//CalDAV Client//EN
387+
BEGIN:VTIMEZONE
388+
LAST-MODIFIED:20040110T032845Z
389+
TZID:US/Eastern
390+
BEGIN:DAYLIGHT
391+
DTSTART:20000404T020000
392+
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
393+
TZNAME:EDT
394+
TZOFFSETFROM:-0500
395+
TZOFFSETTO:-0400
396+
END:DAYLIGHT
397+
BEGIN:STANDARD
398+
DTSTART:20001026T020000
399+
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
400+
TZNAME:EST
401+
TZOFFSETFROM:-0400
402+
TZOFFSETTO:-0500
403+
END:STANDARD
404+
END:VTIMEZONE
405+
BEGIN:VEVENT
406+
DTSTAMP:20060206T001102Z
407+
DTSTART;TZID=US/Eastern:20060102T100000
408+
DURATION:PT1H
409+
SUMMARY:Event #1
410+
Description:Go Steelers!
411+
412+
END:VEVENT
413+
END:VCALENDAR
414+
`
415+
416+
var multigetTest1 = `
417+
<?xml version="1.0" encoding="utf-8" ?>
418+
<C:calendar-multiget xmlns:D="DAV:"
419+
xmlns:C="urn:ietf:params:xml:ns:caldav">
420+
<D:prop>
421+
<D:getetag/>
422+
<C:calendar-data/>
423+
</D:prop>
424+
<D:href>/user/calendars/default/74855313FA803DA593CD579A.ics</D:href>
425+
<D:href>/user/calendars/default/DC6C50A017428C5216A2F1CD.ics</D:href>
426+
</C:calendar-multiget>
427+
`
428+
429+
func TestFindMultiget(t *testing.T) {
430+
calendar := Calendar{
431+
Description: "This is a description which SHOULD NOT be returned in allprop",
432+
Path: "/user/calendars/default/",
433+
SupportedComponentSet: []string{"VEVENT"},
434+
}
435+
cal, err := ical.NewDecoder(strings.NewReader(calendarTestData1)).Decode()
436+
if err != nil {
437+
t.Fatal(err)
438+
}
439+
object1 := CalendarObject{
440+
Path: "/user/calendars/default/DC6C50A017428C5216A2F1CD.ics",
441+
Data: cal,
442+
ETag: "191382932849",
443+
}
444+
cal, err = ical.NewDecoder(strings.NewReader(calendarTestData2)).Decode()
445+
if err != nil {
446+
t.Fatal(err)
447+
}
448+
object2 := CalendarObject{
449+
Path: "/user/calendars/default/74855313FA803DA593CD579A.ics",
450+
Data: cal,
451+
ETag: "191382932850",
452+
}
453+
handler := Handler{Backend: testBackend{
454+
calendars: []Calendar{calendar},
455+
objectMap: map[string][]CalendarObject{
456+
calendar.Path: []CalendarObject{object1, object2},
457+
},
458+
}}
459+
460+
req := httptest.NewRequest("REPORT", "/user/calendars/default/", strings.NewReader(multigetTest1))
461+
req.Header.Set("Content-Type", "application/xml")
462+
req.Header.Set("Depth", "1")
463+
w := httptest.NewRecorder()
464+
handler.ServeHTTP(w, req)
465+
466+
res := w.Result()
467+
defer res.Body.Close()
468+
data, err := io.ReadAll(res.Body)
469+
if err != nil {
470+
t.Fatal(err)
471+
}
472+
resp := string(data)
473+
if !strings.Contains(resp, "UID:[email protected]") {
474+
t.Fatalf("want object1 in multiget report")
475+
} else if !strings.Contains(resp, "UID:[email protected]") {
476+
t.Fatalf("want object2 in multiget report")
477+
} else if !strings.Contains(resp, object1.ETag) {
478+
t.Fatalf("want object1 ETag in multiget report")
479+
} else if !strings.Contains(resp, object2.ETag) {
480+
t.Fatalf("want object2 ETag in multiget report")
481+
}
482+
}
483+
180484
type testBackend struct {
181485
calendars []Calendar
182486
objectMap map[string][]CalendarObject
@@ -231,5 +535,9 @@ func (t testBackend) ListCalendarObjects(ctx context.Context, path string, req *
231535
}
232536

233537
func (t testBackend) QueryCalendarObjects(ctx context.Context, path string, query *CalendarQuery) ([]CalendarObject, error) {
234-
return nil, nil
538+
if cos, err := t.ListCalendarObjects(ctx, path, nil); err != nil {
539+
return nil, err
540+
} else {
541+
return Filter(query, cos)
542+
}
235543
}

0 commit comments

Comments
 (0)