Skip to content

Commit 28f91d2

Browse files
Timo Liljatlilja
authored andcommitted
test(dav): add OPTION_FORGIVING tests for CalDAV Plugin, CalDavBackend and ImportService
Assisted-by: ClaudeCode:claude-sonnet-4-6 Signed-off-by: Timo Lilja <timo.lilja@iki.fi>
1 parent 94fb959 commit 28f91d2

4 files changed

Lines changed: 113 additions & 2 deletions

File tree

apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ abstract class AbstractCalDavBackend extends TestCase {
5252
protected IGroupManager&MockObject $groupManager;
5353
protected IEventDispatcher&MockObject $dispatcher;
5454
private LoggerInterface&MockObject $logger;
55-
private IConfig&MockObject $config;
55+
protected IConfig&MockObject $config;
5656
private ISecureRandom $random;
5757
protected SharingBackend $sharingBackend;
5858
protected IDBConnection $db;

apps/dav/tests/unit/CalDAV/CalDavBackendTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,4 +2104,24 @@ public function testDefaultAlarmProperties(): void {
21042104
// Clean up
21052105
$this->backend->deleteCalendar($calendars[0]['id'], true);
21062106
}
2107+
2108+
private const ICS_ENTOURAGE = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Test//Test//EN\r\nBEGIN:VEVENT\r\nDTSTART:20260715T100000Z\r\nDTEND:20260715T110000Z\r\nSUMMARY:Test\r\nUID:test-uid-123\r\nX-ENTOURAGE_UUID:test-uid-123\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n";
2109+
2110+
public function testGetDenormalizedDataRejectsNonStandardPropertyWhenFlagDisabled(): void {
2111+
$this->config->method('getSystemValueBool')
2112+
->with('dav.forgiving_ical_parser', false)
2113+
->willReturn(false);
2114+
2115+
$this->expectException(\Sabre\VObject\ParseException::class);
2116+
$this->backend->getDenormalizedData(self::ICS_ENTOURAGE);
2117+
}
2118+
2119+
public function testGetDenormalizedDataAcceptsNonStandardPropertyWhenFlagEnabled(): void {
2120+
$this->config->method('getSystemValueBool')
2121+
->with('dav.forgiving_ical_parser', false)
2122+
->willReturn(true);
2123+
2124+
$result = $this->backend->getDenormalizedData(self::ICS_ENTOURAGE);
2125+
$this->assertSame('test-uid-123', $result['uid']);
2126+
}
21072127
}

apps/dav/tests/unit/CalDAV/Import/ImportServiceTest.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,29 @@
1111
use OCA\DAV\CalDAV\CalendarImpl;
1212
use OCA\DAV\CalDAV\Import\ImportService;
1313
use OCP\Calendar\CalendarImportOptions;
14+
use OCP\IConfig;
1415
use PHPUnit\Framework\MockObject\MockObject;
1516
use Sabre\VObject\Component\VCalendar;
1617
use Sabre\VObject\Component\VEvent;
18+
use Sabre\VObject\ParseException;
1719

1820
class ImportServiceTest extends \Test\TestCase {
1921

2022
private ImportService $service;
2123
private CalendarImpl|MockObject $calendar;
2224
private CalDavBackend|MockObject $backend;
25+
private IConfig|MockObject $config;
2326
private array $importResults = [];
2427

2528
protected function setUp(): void {
2629
parent::setUp();
2730

2831
$this->backend = $this->createMock(CalDavBackend::class);
29-
$this->service = new ImportService($this->backend);
32+
$this->config = $this->createMock(IConfig::class);
33+
$this->config->method('getSystemValueBool')
34+
->with('dav.forgiving_ical_parser', false)
35+
->willReturn(false);
36+
$this->service = new ImportService($this->backend, $this->config);
3037
$this->calendar = $this->createMock(CalendarImpl::class);
3138

3239
}
@@ -148,4 +155,30 @@ public function testImportWithMultiLineUID(): void {
148155
$this->assertArrayHasKey($longUID, $result);
149156
$this->assertEquals('created', $result[$longUID]['outcome']);
150157
}
158+
159+
private const ICS_ENTOURAGE = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Test//Test//EN\r\nBEGIN:VEVENT\r\nDTSTART:20260715T100000Z\r\nDTEND:20260715T110000Z\r\nSUMMARY:Test\r\nUID:test-uid-123\r\nX-ENTOURAGE_UUID:test-uid-123\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n";
160+
161+
public function testImportTextRejectsNonStandardPropertyWhenFlagDisabled(): void {
162+
$stream = fopen('php://memory', 'r+');
163+
fwrite($stream, self::ICS_ENTOURAGE);
164+
rewind($stream);
165+
166+
$this->expectException(ParseException::class);
167+
iterator_to_array($this->service->importText($stream));
168+
}
169+
170+
public function testImportTextAcceptsNonStandardPropertyWhenFlagEnabled(): void {
171+
$this->config = $this->createMock(IConfig::class);
172+
$this->config->method('getSystemValueBool')
173+
->with('dav.forgiving_ical_parser', false)
174+
->willReturn(true);
175+
$this->service = new ImportService($this->backend, $this->config);
176+
177+
$stream = fopen('php://memory', 'r+');
178+
fwrite($stream, self::ICS_ENTOURAGE);
179+
rewind($stream);
180+
181+
$objects = iterator_to_array($this->service->importText($stream));
182+
$this->assertCount(1, $objects);
183+
}
151184
}

apps/dav/tests/unit/CalDAV/PluginTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
namespace OCA\DAV\Tests\unit\CalDAV;
1010

1111
use OCA\DAV\CalDAV\Plugin;
12+
use OCP\IConfig;
13+
use PHPUnit\Framework\MockObject\MockObject;
14+
use Sabre\DAV\Exception\UnsupportedMediaType;
15+
use Sabre\DAV\Server as SabreServer;
16+
use Sabre\HTTP\RequestInterface;
17+
use Sabre\HTTP\ResponseInterface;
1218
use Test\TestCase;
1319

1420
class PluginTest extends TestCase {
@@ -45,4 +51,56 @@ public function testGetCalendarHomeForPrincipal(string $input, string $expected)
4551
public function testGetCalendarHomeForUnknownPrincipal(): void {
4652
$this->assertNull($this->plugin->getCalendarHomeForPrincipal('FOO/BAR/BLUB'));
4753
}
54+
55+
private const ICS_ENTOURAGE = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Test//Test//EN\r\nBEGIN:VEVENT\r\nDTSTART:20260715T100000Z\r\nDTEND:20260715T110000Z\r\nSUMMARY:Test\r\nUID:test-uid-123\r\nX-ENTOURAGE_UUID:test-uid-123\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n";
56+
57+
private function makePlugin(bool $forgiving): Plugin {
58+
/** @var IConfig&MockObject $config */
59+
$config = $this->createMock(IConfig::class);
60+
$config->method('getSystemValueBool')
61+
->with('dav.forgiving_ical_parser', false)
62+
->willReturn($forgiving);
63+
64+
$plugin = new class($config) extends Plugin {
65+
public function exposeValidateICalendar(string &$data, string $path, bool &$modified, RequestInterface $request, ResponseInterface $response, bool $isNew): void {
66+
$this->validateICalendar($data, $path, $modified, $request, $response, $isNew);
67+
}
68+
};
69+
70+
/** @var SabreServer&MockObject $server */
71+
$server = $this->createMock(SabreServer::class);
72+
$server->method('getProperties')->willReturn([]);
73+
$server->method('getHTTPPrefer')->willReturn(['handling' => 'lenient']);
74+
$server->method('emit')->willReturn(true);
75+
76+
// Inject server without calling initialize() to avoid its side effects on xml/resourceTypeMapping
77+
$prop = new \ReflectionProperty(\Sabre\CalDAV\Plugin::class, 'server');
78+
$prop->setValue($plugin, $server);
79+
80+
return $plugin;
81+
}
82+
83+
public function testValidateICalendarRejectsNonStandardPropertyWhenFlagDisabled(): void {
84+
$plugin = $this->makePlugin(false);
85+
$data = self::ICS_ENTOURAGE;
86+
$modified = false;
87+
$request = $this->createMock(RequestInterface::class);
88+
$response = $this->createMock(ResponseInterface::class);
89+
90+
$this->expectException(UnsupportedMediaType::class);
91+
$plugin->exposeValidateICalendar($data, 'calendars/admin/personal/test.ics', $modified, $request, $response, true);
92+
}
93+
94+
public function testValidateICalendarAcceptsNonStandardPropertyWhenFlagEnabled(): void {
95+
$plugin = $this->makePlugin(true);
96+
$data = self::ICS_ENTOURAGE;
97+
$modified = false;
98+
$request = $this->createMock(RequestInterface::class);
99+
$response = $this->createMock(ResponseInterface::class);
100+
$response->expects($this->once())
101+
->method('setHeader')
102+
->with('X-Sabre-Ew-Gross', $this->stringContains('X-ENTOURAGE_UUID'));
103+
104+
$plugin->exposeValidateICalendar($data, 'calendars/admin/personal/test.ics', $modified, $request, $response, true);
105+
}
48106
}

0 commit comments

Comments
 (0)