Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/src/main/kotlin/at/bitfire/ical4android/Event.kt
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ data class Event(
get() = Logger.getLogger(Event::class.java.name)

/**
* Parses an iCalendar resource, applies [at.bitfire.ical4android.validation.ICalPreprocessor]
* Parses an iCalendar resource, applies [at.bitfire.synctools.icalendar.validation.ICalPreprocessor]
* and [EventValidator] to increase compatibility and extracts the VEVENTs.
*
* @param reader where the iCalendar is read from
Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/kotlin/at/bitfire/ical4android/ICalendar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
package at.bitfire.ical4android

import at.bitfire.ical4android.ICalendar.Companion.CALENDAR_NAME
import at.bitfire.ical4android.validation.ICalPreprocessor
import at.bitfire.synctools.BuildConfig
import at.bitfire.synctools.exception.InvalidRemoteResourceException
import at.bitfire.synctools.icalendar.ICalendarParser
import at.bitfire.synctools.icalendar.validation.ICalPreprocessor
import net.fortuna.ical4j.data.CalendarBuilder
import net.fortuna.ical4j.data.ParserException
import net.fortuna.ical4j.model.Calendar
Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/kotlin/at/bitfire/ical4android/Task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ data class Task(
get() = Logger.getLogger(Task::class.java.name)

/**
* Parses an iCalendar resource, applies [at.bitfire.ical4android.validation.ICalPreprocessor] to increase compatibility
* Parses an iCalendar resource, applies [at.bitfire.synctools.icalendar.validation.ICalPreprocessor] to increase compatibility
* and extracts the VTODOs.
*
* @param reader where the iCalendar is taken from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

package at.bitfire.synctools.icalendar

import at.bitfire.ical4android.validation.ICalPreprocessor
import at.bitfire.synctools.exception.InvalidRemoteResourceException
import at.bitfire.synctools.icalendar.validation.ICalPreprocessor
import net.fortuna.ical4j.data.CalendarBuilder
import net.fortuna.ical4j.data.CalendarParserFactory
import net.fortuna.ical4j.data.ContentHandlerContext
Expand All @@ -20,8 +20,12 @@ import java.util.logging.Logger

/**
* Custom iCalendar parser that applies error correction using [ICalPreprocessor].
*
* @param preprocessor pre-processor to use
*/
class ICalendarParser {
class ICalendarParser(
private val preprocessor: ICalPreprocessor = ICalPreprocessor()
) {

private val logger
get() = Logger.getLogger(javaClass.name)
Expand All @@ -39,7 +43,7 @@ class ICalendarParser {
*/
fun parse(reader: Reader): Calendar {
// preprocess stream to work around problems that prevent parsing and thus can't be fixed later
val preprocessed = ICalPreprocessor.preprocessStream(reader)
val preprocessed = preprocessor.preprocessStream(reader)

// parse stream, ignoring invalid properties (if possible)
val calendar: Calendar
Expand All @@ -57,7 +61,7 @@ class ICalendarParser {

// Pre-process calendar for increased compatibility (fixes some common errors)
try {
ICalPreprocessor.preprocessCalendar(calendar)
preprocessor.preprocessCalendar(calendar)
} catch (e: Exception) {
logger.log(Level.WARNING, "Couldn't pre-process iCalendar", e)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package at.bitfire.ical4android.validation
package at.bitfire.synctools.icalendar.validation

/**
* Fixes durations with day offsets with the 'T' prefix.
* See also https://github.com/bitfireAT/ical4android/issues/77
*/
object FixInvalidDayOffsetPreprocessor : StreamPreprocessor() {
class FixInvalidDayOffsetPreprocessor : StreamPreprocessor() {

override fun regexpForProblem() = Regex(
// Examples:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package at.bitfire.ical4android.validation
package at.bitfire.synctools.icalendar.validation

import at.bitfire.ical4android.validation.FixInvalidUtcOffsetPreprocessor.TZOFFSET_REGEXP
import java.util.logging.Level
import java.util.logging.Logger

Expand All @@ -17,7 +16,7 @@ import java.util.logging.Logger
* Rewrites values of all TZOFFSETFROM and TZOFFSETTO properties which match [TZOFFSET_REGEXP]
* so that an hour value of 00 is inserted.
*/
object FixInvalidUtcOffsetPreprocessor: StreamPreprocessor() {
class FixInvalidUtcOffsetPreprocessor: StreamPreprocessor() {

private val logger
get() = Logger.getLogger(javaClass.name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package at.bitfire.ical4android.validation
package at.bitfire.synctools.icalendar.validation

import androidx.annotation.VisibleForTesting
import net.fortuna.ical4j.model.Calendar
import net.fortuna.ical4j.model.Property
import net.fortuna.ical4j.transform.rfc5545.CreatedPropertyRule
Expand All @@ -24,7 +25,7 @@ import java.util.logging.Logger
* (like "W. Europe Standard Time" to an Android-friendly name like "Europe/Vienna")
*
*/
object ICalPreprocessor {
class ICalPreprocessor {

private val propertyRules = arrayOf(
CreatedPropertyRule(), // make sure CREATED is UTC
Expand All @@ -33,9 +34,10 @@ object ICalPreprocessor {
DateListPropertyRule() // ... by the ical4j VTIMEZONE with the same TZID!
)

private val streamPreprocessors = arrayOf(
FixInvalidUtcOffsetPreprocessor, // fix things like TZOFFSET(FROM,TO):+5730
FixInvalidDayOffsetPreprocessor // fix things like DURATION:PT2D
@VisibleForTesting
internal val streamPreprocessors = arrayOf(
FixInvalidUtcOffsetPreprocessor(), // fix things like TZOFFSET(FROM,TO):+5730
FixInvalidDayOffsetPreprocessor() // fix things like DURATION:PT2D
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package at.bitfire.ical4android.validation
package at.bitfire.synctools.icalendar.validation

import java.io.IOException
import java.io.Reader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,54 @@

package at.bitfire.synctools.icalendar

import at.bitfire.ical4android.validation.ICalPreprocessor
import at.bitfire.synctools.exception.InvalidRemoteResourceException
import at.bitfire.synctools.icalendar.validation.ICalPreprocessor
import io.mockk.every
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.RelaxedMockK
import io.mockk.junit4.MockKRule
import io.mockk.mockkObject
import io.mockk.slot
import io.mockk.verify
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.io.Reader
import java.io.StringReader

class ICalendarParserTest {

@get:Rule
val mockkRule = MockKRule(this)

@RelaxedMockK
lateinit var preprocessor: ICalPreprocessor

@InjectMockKs
lateinit var parser: ICalendarParser

@Before
fun setUp() {
val reader = slot<Reader>()
every { preprocessor.preprocessStream(capture(reader)) } answers { reader.captured }
}


@Test
fun testParse_AppliesPreProcessing() {
mockkObject(ICalPreprocessor)

val reader = StringReader(
"BEGIN:VCALENDAR\r\n" +
"BEGIN:VEVENT\r\n" +
"END:VEVENT\r\n" +
"END:VCALENDAR\r\n"
)
val cal = ICalendarParser().parse(reader)
val cal = parser.parse(reader)

verify(exactly = 1) {
// verify preprocessing was applied to stream
ICalPreprocessor.preprocessStream(any())
preprocessor.preprocessStream(any())

// verify preprocessing was applied to resulting calendar
ICalPreprocessor.preprocessCalendar(cal)
preprocessor.preprocessCalendar(cal)
}
}

Expand All @@ -50,13 +66,14 @@ class ICalendarParserTest {
"END:VEVENT\r\n" +
"END:VCALENDAR\r\n"
)
ICalendarParser().parse(reader)
parser.parse(reader)
// no exception called
}

@Test(expected = InvalidRemoteResourceException::class)
fun testParse_ThrowsExceptionOnInvalidInput() {
val reader = StringReader("invalid")
ICalendarParser().parse(reader)
parser.parse(reader)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package at.bitfire.ical4android.validation
package at.bitfire.synctools.icalendar.validation

import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
Expand All @@ -13,17 +13,19 @@ import org.junit.Test
import java.time.Duration

class FixInvalidDayOffsetPreprocessorTest {

private val processor = FixInvalidDayOffsetPreprocessor()

/**
* Calls [FixInvalidDayOffsetPreprocessor.fixString] and asserts the result is equal to [expected].
* Calls `processor.fixString` and asserts the result is equal to [expected].
*
* @param expected The expected result
* @param testValue The value to test
* @param parseDuration If `true`, [Duration.parse] is called on the fixed value to make sure it's a valid duration
*/
private fun assertFixedEquals(expected: String, testValue: String, parseDuration: Boolean = true) {
// Fix the duration string
val fixed = FixInvalidDayOffsetPreprocessor.fixString(testValue)
val fixed = processor.fixString(testValue)

// Test the duration can now be parsed
if (parseDuration)
Expand All @@ -40,7 +42,7 @@ class FixInvalidDayOffsetPreprocessorTest {
fun test_FixString_NoOccurrence() {
assertEquals(
"Some String",
FixInvalidDayOffsetPreprocessor.fixString("Some String"),
processor.fixString("Some String"),
)
}

Expand Down Expand Up @@ -99,14 +101,14 @@ class FixInvalidDayOffsetPreprocessorTest {

@Test
fun test_RegexpForProblem_DayOffsetTo_Invalid() {
val regex = FixInvalidDayOffsetPreprocessor.regexpForProblem()
val regex = processor.regexpForProblem()
assertTrue(regex.matches("DURATION:PT2D"))
assertTrue(regex.matches("TRIGGER:PT1D"))
}

@Test
fun test_RegexpForProblem_DayOffsetTo_Valid() {
val regex = FixInvalidDayOffsetPreprocessor.regexpForProblem()
val regex = processor.regexpForProblem()
assertFalse(regex.matches("DURATION:-PT12H"))
assertFalse(regex.matches("TRIGGER:-PT15M"))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,58 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package at.bitfire.ical4android.validation
package at.bitfire.synctools.icalendar.validation

import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test

class FixInvalidUtcOffsetPreprocessorTest {

private val processor = FixInvalidUtcOffsetPreprocessor()

@Test
fun test_FixString_NoOccurrence() {
assertEquals(
"Some String",
FixInvalidUtcOffsetPreprocessor.fixString("Some String"))
processor.fixString("Some String"))
}

@Test
fun test_FixString_TzOffsetFrom_Invalid() {
assertEquals("TZOFFSETFROM:+005730",
FixInvalidUtcOffsetPreprocessor.fixString("TZOFFSETFROM:+5730"))
processor.fixString("TZOFFSETFROM:+5730"))
}

@Test
fun test_FixString_TzOffsetFrom_Valid() {
assertEquals("TZOFFSETFROM:+005730",
FixInvalidUtcOffsetPreprocessor.fixString("TZOFFSETFROM:+005730"))
processor.fixString("TZOFFSETFROM:+005730"))
}

@Test
fun test_FixString_TzOffsetTo_Invalid() {
assertEquals("TZOFFSETTO:+005730",
FixInvalidUtcOffsetPreprocessor.fixString("TZOFFSETTO:+5730"))
processor.fixString("TZOFFSETTO:+5730"))
}

@Test
fun test_FixString_TzOffsetTo_Valid() {
assertEquals("TZOFFSETTO:+005730",
FixInvalidUtcOffsetPreprocessor.fixString("TZOFFSETTO:+005730"))
processor.fixString("TZOFFSETTO:+005730"))
}


@Test
fun test_RegexpForProblem_TzOffsetTo_Invalid() {
val regex = FixInvalidUtcOffsetPreprocessor.regexpForProblem()
val regex = processor.regexpForProblem()
assertTrue(regex.matches("TZOFFSETTO:+5730"))
}

@Test
fun test_RegexpForProblem_TzOffsetTo_Valid() {
val regex = FixInvalidUtcOffsetPreprocessor.regexpForProblem()
val regex = processor.regexpForProblem()
assertFalse(regex.matches("TZOFFSETTO:+005730"))
}

Expand Down
Loading