Skip to content
Snippets Groups Projects
Verified Commit db256157 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Fixes #145

parent b66b2ffe
Branches
Tags
No related merge requests found
Pipeline #262 passed
...@@ -24,7 +24,7 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.IIgnoreListManager ...@@ -24,7 +24,7 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.IIgnoreListManager
import de.kuschku.libquassel.session.ISession import de.kuschku.libquassel.session.ISession
import de.kuschku.libquassel.session.Session import de.kuschku.libquassel.session.Session
import de.kuschku.libquassel.session.SignalProxy import de.kuschku.libquassel.session.SignalProxy
import de.kuschku.libquassel.util.GlobTransformer import de.kuschku.libquassel.util.ExpressionMatch
import de.kuschku.libquassel.util.flag.and import de.kuschku.libquassel.util.flag.and
import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.BehaviorSubject
import java.io.Serializable import java.io.Serializable
...@@ -169,8 +169,8 @@ class IgnoreListManager constructor( ...@@ -169,8 +169,8 @@ class IgnoreListManager constructor(
val scope: ScopeType, val scope: ScopeType,
val scopeRule: String, val scopeRule: String,
val isActive: Boolean, val isActive: Boolean,
val regEx: Regex?, val regEx: ExpressionMatch,
val scopeRegEx: Set<Regex> val scopeRegEx: ExpressionMatch
) : Serializable { ) : Serializable {
constructor(type: Int, ignoreRule: String, isRegEx: Boolean, strictness: Int, scope: Int, constructor(type: Int, ignoreRule: String, isRegEx: Boolean, strictness: Int, scope: Int,
scopeRule: String, isActive: Boolean) : this( scopeRule: String, isActive: Boolean) : this(
...@@ -181,24 +181,18 @@ class IgnoreListManager constructor( ...@@ -181,24 +181,18 @@ class IgnoreListManager constructor(
constructor(type: IgnoreType, ignoreRule: String, isRegEx: Boolean, strictness: StrictnessType, constructor(type: IgnoreType, ignoreRule: String, isRegEx: Boolean, strictness: StrictnessType,
scope: ScopeType, scopeRule: String, isActive: Boolean) : this( scope: ScopeType, scopeRule: String, isActive: Boolean) : this(
type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive, type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive,
try { ExpressionMatch(
Regex(ignoreRule.let { ignoreRule,
if (isRegEx) it else GlobTransformer.convertGlobToRegex(it) if (isRegEx) ExpressionMatch.MatchMode.MatchRegEx
}, RegexOption.IGNORE_CASE) else ExpressionMatch.MatchMode.MatchWildcard,
} catch (_: Throwable) { true
null ),
}, ExpressionMatch(
scopeRule.split(';') scopeRule,
.map(String::trim) if (isRegEx) ExpressionMatch.MatchMode.MatchRegEx
.map(GlobTransformer::convertGlobToRegex) else ExpressionMatch.MatchMode.MatchMultiWildcard,
.mapNotNull { true
try { )
Regex(it, RegexOption.IGNORE_CASE)
} catch (e: Throwable) {
null
}
}
.toSet()
) )
fun copy( fun copy(
...@@ -217,14 +211,17 @@ class IgnoreListManager constructor( ...@@ -217,14 +211,17 @@ class IgnoreListManager constructor(
scope = scope, scope = scope,
scopeRule = scopeRule, scopeRule = scopeRule,
isActive = isActive, isActive = isActive,
regEx = if (ignoreRule == this.ignoreRule) this.regEx else Regex(ignoreRule.let { regEx = ExpressionMatch(
if (isRegEx) it else GlobTransformer.convertGlobToRegex(it) ignoreRule,
}, RegexOption.IGNORE_CASE), if (isRegEx) ExpressionMatch.MatchMode.MatchRegEx
scopeRegEx = if (scopeRule == this.scopeRule) this.scopeRegEx else scopeRule.split(';') else ExpressionMatch.MatchMode.MatchWildcard,
.map(String::trim) true
.map(GlobTransformer::convertGlobToRegex) ),
.map { Regex(it, RegexOption.IGNORE_CASE) } scopeRegEx = ExpressionMatch(
.toSet() scopeRule,
ExpressionMatch.MatchMode.MatchMultiWildcard,
true
)
) )
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
...@@ -269,12 +266,11 @@ class IgnoreListManager constructor( ...@@ -269,12 +266,11 @@ class IgnoreListManager constructor(
it.isActive && it.type != IgnoreType.CtcpIgnore it.isActive && it.type != IgnoreType.CtcpIgnore
}.filter { }.filter {
it.scope == ScopeType.GlobalScope || it.scope == ScopeType.GlobalScope ||
it.scope == ScopeType.NetworkScope && it.scopeRegEx.any { it matches network } || it.scope == ScopeType.NetworkScope && it.scopeRegEx.match(network) ||
it.scope == ScopeType.ChannelScope && it.scopeRegEx.any { it matches bufferName } it.scope == ScopeType.ChannelScope && it.scopeRegEx.match(bufferName)
}.filter { }.filter {
val content = if (it.type == IgnoreType.MessageIgnore) msgContents else msgSender val content = if (it.type == IgnoreType.MessageIgnore) msgContents else msgSender
!it.isRegEx && it.regEx?.matches(content) == true || it.regEx.match(content)
it.isRegEx && it.regEx?.containsMatchIn(content) == true
}.map { }.map {
it.strictness it.strictness
}.sortedByDescending { }.sortedByDescending {
...@@ -296,6 +292,4 @@ class IgnoreListManager constructor( ...@@ -296,6 +292,4 @@ class IgnoreListManager constructor(
override fun toString(): String { override fun toString(): String {
return "IgnoreListManager(_ignoreList=$_ignoreList)" return "IgnoreListManager(_ignoreList=$_ignoreList)"
} }
} }
This diff is collapsed.
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2018 Janne Koschinski
* Copyright (c) 2018 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.libquassel.util
object GlobTransformer {
/**
* Converts a standard POSIX Shell globbing pattern into a regular expression
* pattern. The result can be used with the standard {@link java.util.regex} API to
* recognize strings which match the glob pattern.
* <p/>
* See also, the POSIX Shell language:
* http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13_01
*
* @param pattern A glob pattern.
* @return A regex pattern to recognize the given glob pattern.
*/
fun convertGlobToRegex(pattern: String): String {
val sb = StringBuilder(pattern.length)
var inGroup = 0
var inClass = 0
var firstIndexInClass = -1
val arr = pattern.toCharArray()
var i = 0
while (i < arr.size) {
val ch = arr[i]
when (ch) {
'\\' ->
if (++i >= arr.size) {
sb.append('\\')
} else {
val next = arr[i]
when (next) {
',' -> {
}
'Q', 'E' -> {
// extra escape needed
sb.append('\\')
sb.append('\\')
}
else -> sb.append('\\')
}// escape not needed
sb.append(next)
}
'*' -> sb.append(if (inClass == 0) ".*" else '*')
'?' -> sb.append(if (inClass == 0) '.' else '?')
'[' -> {
inClass++
firstIndexInClass = i + 1
sb.append('[')
}
']' -> {
inClass--
sb.append(']')
}
'.', '(', ')',
'+', '|', '^',
'$', '@', '%' -> {
if (inClass == 0 || firstIndexInClass == i && ch == '^')
sb.append('\\')
sb.append(ch)
}
'!' ->
sb.append(if (firstIndexInClass == i) '^' else '!')
'{' -> {
inGroup++
sb.append('(')
}
'}' -> {
inGroup--
sb.append(')')
}
',' -> sb.append(if (inGroup > 0) '|' else ',')
else -> sb.append(ch)
}
i++
}
return sb.toString()
}
}
package de.kuschku.libquassel.util
import org.junit.Assert.*
import org.junit.Test
class ExpressionMatchTest {
@Test
fun testEmptyPattern() {
// Empty pattern
val emptyMatch = ExpressionMatch("", ExpressionMatch.MatchMode.MatchPhrase, false)
// Assert empty is valid
assertTrue(emptyMatch.isValid())
// Assert empty
assertTrue(emptyMatch.isEmpty())
// Assert default match fails (same as setting match empty to false)
assertFalse(emptyMatch.match("something"))
// Assert match empty succeeds
assertTrue(emptyMatch.match("something", true))
}
@Test
fun testMatchPhrase() {
// Simple phrase, case-insensitive
val simpleMatch = ExpressionMatch("test", ExpressionMatch.MatchMode.MatchPhrase, false)
// Simple phrase, case-sensitive
val simpleMatchCS = ExpressionMatch("test", ExpressionMatch.MatchMode.MatchPhrase, true)
// Phrase with space, case-insensitive
val simpleMatchSpace = ExpressionMatch(" space ", ExpressionMatch.MatchMode.MatchPhrase, true)
// Complex phrase
val complexMatchFull = """^(?:norm|norm\-space|\!norm\-escaped|\\\!slash\-invert|\\\\double|escape\;sep|slash\-end\-split\\|quad\\\\\!noninvert|newline\-split|newline\-split\-slash\\|slash\-at\-end\\)$"""
val complexMatch = ExpressionMatch(complexMatchFull,
ExpressionMatch.MatchMode.MatchPhrase,
false)
// Assert valid and not empty
assertTrue(simpleMatch.isValid())
assertFalse(simpleMatch.isEmpty())
assertTrue(simpleMatchCS.isValid())
assertFalse(simpleMatchCS.isEmpty())
assertTrue(simpleMatchSpace.isValid())
assertFalse(simpleMatchSpace.isEmpty())
assertTrue(complexMatch.isValid())
assertFalse(complexMatch.isEmpty())
// Assert match succeeds
assertTrue(simpleMatch.match("test"))
assertTrue(simpleMatch.match("other test;"))
assertTrue(simpleMatchSpace.match(" space "))
// Assert partial match fails
assertFalse(simpleMatch.match("testing"))
assertFalse(simpleMatchSpace.match("space"))
// Assert unrelated fails
assertFalse(simpleMatch.match("not above"))
// Assert case sensitivity followed
assertFalse(simpleMatch.sourceCaseSensitive)
assertTrue(simpleMatch.match("TeSt"))
assertTrue(simpleMatchCS.sourceCaseSensitive)
assertFalse(simpleMatchCS.match("TeSt"))
// Assert complex phrases are escaped properly
assertTrue(complexMatch.match(complexMatchFull))
assertFalse(complexMatch.match("norm"))
}
@Test
fun matchMultiPhrase() {
// Simple phrases, case-insensitive
val simpleMatch = ExpressionMatch("test\nOther ",
ExpressionMatch.MatchMode.MatchMultiPhrase,
false)
// Simple phrases, case-sensitive
val simpleMatchCS = ExpressionMatch("test\nOther ",
ExpressionMatch.MatchMode.MatchMultiPhrase,
true)
// Complex phrases
val complexMatchFullA = """^(?:norm|norm\-space|\!norm\-escaped|\\\!slash\-invert|\\\\double)|escape\;sep|slash\-end\-split\\|quad\\\\\!noninvert)|newline\-split|newline\-split\-slash\\|slash\-at\-end\\)$"""
val complexMatchFullB = """^(?:invert|invert\-space)$)$"""
val complexMatch = ExpressionMatch(complexMatchFullA + "\n" + complexMatchFullB,
ExpressionMatch.MatchMode.MatchMultiPhrase,
false)
// Assert valid and not empty
assertTrue(simpleMatch.isValid())
assertFalse(simpleMatch.isEmpty())
assertTrue(simpleMatchCS.isValid())
assertFalse(simpleMatchCS.isEmpty())
assertTrue(complexMatch.isValid())
assertFalse(complexMatch.isEmpty())
// Assert match succeeds
assertTrue(simpleMatch.match("test"))
assertTrue(simpleMatch.match("test[suffix]"))
assertTrue(simpleMatch.match("other test;"))
assertTrue(simpleMatch.match("Other "))
assertTrue(simpleMatch.match(".Other !"))
// Assert partial match fails
assertFalse(simpleMatch.match("testing"))
assertFalse(simpleMatch.match("Other!"))
// Assert unrelated fails
assertFalse(simpleMatch.match("not above"))
// Assert case sensitivity followed
assertFalse(simpleMatch.sourceCaseSensitive)
assertTrue(simpleMatch.match("TeSt"))
assertTrue(simpleMatchCS.sourceCaseSensitive)
assertFalse(simpleMatchCS.match("TeSt"))
// Assert complex phrases are escaped properly
assertTrue(complexMatch.match(complexMatchFullA))
assertTrue(complexMatch.match(complexMatchFullB))
assertFalse(complexMatch.match("norm"))
assertFalse(complexMatch.match("invert"))
}
@Test
fun matchWildcard() {
// Simple wildcard, case-insensitive
val simpleMatch =
ExpressionMatch("?test*", ExpressionMatch.MatchMode.MatchWildcard, false)
// Simple wildcard, case-sensitive
val simpleMatchCS =
ExpressionMatch("?test*", ExpressionMatch.MatchMode.MatchWildcard, true)
// Escaped wildcard, case-insensitive
val simpleMatchEscape =
ExpressionMatch("""\?test\*""", ExpressionMatch.MatchMode.MatchWildcard, false)
// Inverted wildcard, case-insensitive
val simpleMatchInvert =
ExpressionMatch("!test*", ExpressionMatch.MatchMode.MatchWildcard, false)
// Not inverted wildcard, case-insensitive
val simpleMatchNoInvert =
ExpressionMatch("""\!test*""", ExpressionMatch.MatchMode.MatchWildcard, false)
// Not inverted wildcard literal slash, case-insensitive
val simpleMatchNoInvertSlash =
ExpressionMatch("""\\!test*""", ExpressionMatch.MatchMode.MatchWildcard, false)
// Complex wildcard
val complexMatch =
ExpressionMatch("""never?gonna*give\*you\?up\\test|y\yeah\\1\\\\2\\\1inval""",
ExpressionMatch.MatchMode.MatchWildcard, false)
// Assert valid and not empty
assertTrue(simpleMatch.isValid())
assertFalse(simpleMatch.isEmpty())
assertTrue(simpleMatchCS.isValid())
assertFalse(simpleMatchCS.isEmpty())
assertTrue(simpleMatchEscape.isValid())
assertFalse(simpleMatchEscape.isEmpty())
assertTrue(simpleMatchInvert.isValid())
assertFalse(simpleMatchInvert.isEmpty())
assertTrue(simpleMatchNoInvert.isValid())
assertFalse(simpleMatchNoInvert.isEmpty())
assertTrue(simpleMatchNoInvertSlash.isValid())
assertFalse(simpleMatchNoInvertSlash.isEmpty())
assertTrue(complexMatch.isValid())
assertFalse(complexMatch.isEmpty())
// Assert match succeeds
assertTrue(simpleMatch.match("@test"))
assertTrue(simpleMatch.match("@testing"))
assertTrue(simpleMatch.match("!test"))
assertTrue(simpleMatchEscape.match("?test*"))
assertTrue(simpleMatchInvert.match("atest"))
assertTrue(simpleMatchNoInvert.match("!test"))
assertTrue(simpleMatchNoInvertSlash.match("""\!test)"""))
// Assert partial match fails
assertFalse(simpleMatch.match("test"))
// Assert unrelated fails
assertFalse(simpleMatch.match("not above"))
// Assert escaped wildcard fails
assertFalse(simpleMatchEscape.match("@testing"))
assertFalse(simpleMatchNoInvert.match("test"))
assertFalse(simpleMatchNoInvert.match("anything"))
assertFalse(simpleMatchNoInvertSlash.match("!test"))
assertFalse(simpleMatchNoInvertSlash.match("test"))
assertFalse(simpleMatchNoInvertSlash.match("anything"))
// Assert non-inverted fails
assertFalse(simpleMatchInvert.match("testing"))
// Assert case sensitivity followed
assertFalse(simpleMatch.sourceCaseSensitive)
assertTrue(simpleMatch.match("@TeSt"))
assertTrue(simpleMatchCS.sourceCaseSensitive)
assertFalse(simpleMatchCS.match("@TeSt"))
// Assert complex match
assertTrue(complexMatch.match("""neverAgonnaBBBgive*you?up\test|yyeah\1\\2\1inval"""))
// Assert complex not literal match
assertFalse(complexMatch.match("""never?gonna*give\*you\?up\\test|y\yeah\\1\\\\2\\\1inval"""))
// Assert complex unrelated not match
assertFalse(complexMatch.match("other"))
}
@Test
fun matchMultiWildcard() {
/*
// Simple wildcards, case-insensitive
val simpleMatch =
ExpressionMatch("?test*;another?",
ExpressionMatch.MatchMode.MatchMultiWildcard, false)
// Simple wildcards, case-sensitive
val simpleMatchCS =
ExpressionMatch("?test*;another?",
ExpressionMatch.MatchMode.MatchMultiWildcard, true)
*/
// Escaped wildcards, case-insensitive
val simpleMatchEscape =
ExpressionMatch("""\?test\*\;*thing\*""",
ExpressionMatch.MatchMode.MatchMultiWildcard, false)
/*
// Inverted wildcards, case-insensitive
val simpleMatchInvert =
ExpressionMatch("""test*;!testing""",
ExpressionMatch.MatchMode.MatchMultiWildcard, false)
// Implicit wildcards, case-insensitive
val simpleMatchImplicit =
ExpressionMatch("""!testing*""",
ExpressionMatch.MatchMode.MatchMultiWildcard, false)
// Complex wildcard
val complexMatchFull = """norm;!invert; norm-space ; !invert-space ;;!;\!norm-escaped;\\!slash-invert;\\\\double; escape\;sep;slash-end-split\\;quad\\\\!noninvert;newline-split\nnewline-split-slash\\\nslash-at-end\\"""
// Match normal components
val complexMatchNormal = listOf(
"""norm""",
"""norm-space""",
"""!norm-escaped""",
"""\!slash-invert""",
"""\\double""",
"""escape;sep""",
"""slash-end-split\""",
"""quad\\!noninvert""",
"""newline-split""",
"""newline-split-slash\""",
"""slash-at-end\"""
)
// Match negating components
val complexMatchInvert = listOf(
"""(invert)""",
"""(invert-space)"""
)
val complexMatch =
ExpressionMatch(complexMatchFull, ExpressionMatch.MatchMode.MatchMultiWildcard,
false)
// Assert valid and not empty
assertTrue(simpleMatch.isValid())
assertFalse(simpleMatch.isEmpty())
assertTrue(simpleMatchCS.isValid())
assertFalse(simpleMatchCS.isEmpty())
assertTrue(simpleMatchEscape.isValid())
assertFalse(simpleMatchEscape.isEmpty())
assertTrue(simpleMatchInvert.isValid())
assertFalse(simpleMatchInvert.isEmpty())
assertTrue(simpleMatchImplicit.isValid())
assertFalse(simpleMatchImplicit.isEmpty())
assertTrue(complexMatch.isValid())
assertFalse(complexMatch.isEmpty())
// Assert match succeeds
assertTrue(simpleMatch.match("@test"))
assertTrue(simpleMatch.match("@testing"))
assertTrue(simpleMatch.match("!test"))
assertTrue(simpleMatch.match("anotherA"))
*/
assertTrue(simpleMatchEscape.match("?test*;thing*"))
assertTrue(simpleMatchEscape.match("?test*;AAAAAthing*"))
/*
assertTrue(simpleMatchInvert.match("test"))
assertTrue(simpleMatchInvert.match("testing things"))
// Assert implicit wildcard succeeds
assertTrue(simpleMatchImplicit.match("AAAAAA"))
// Assert partial match fails
assertFalse(simpleMatch.match("test"))
assertFalse(simpleMatch.match("another"))
assertFalse(simpleMatch.match("anotherBB"))
// Assert unrelated fails
assertFalse(simpleMatch.match("not above"))
*/
// Assert escaped wildcard fails
assertFalse(simpleMatchEscape.match("@testing"))
/*
// Assert inverted match fails
assertFalse(simpleMatchInvert.match("testing"))
assertFalse(simpleMatchImplicit.match("testing"))
// Assert case sensitivity followed
assertFalse(simpleMatch.sourceCaseSensitive)
assertTrue(simpleMatch.match("@TeSt"))
assertTrue(simpleMatchCS.sourceCaseSensitive)
assertFalse(simpleMatchCS.match("@TeSt"))
// Assert complex match
for (normMatch in complexMatchNormal) {
// Each normal component should match
assertTrue(complexMatch.match(normMatch))
}
for (invertMatch in complexMatchInvert) {
// Each invert component should not match
assertFalse(complexMatch.match(invertMatch))
}
// Assert complex not literal match
assertFalse(complexMatch.match(complexMatchFull))
// Assert complex unrelated not match
assertFalse(complexMatch.match("other"))
*/
}
@Test
fun matchRegEx() {
// Simple regex, case-insensitive
val simpleMatch =
ExpressionMatch("""simple.\*escape-match.*""",
ExpressionMatch.MatchMode.MatchRegEx, false)
// Simple regex, case-sensitive
val simpleMatchCS =
ExpressionMatch("""simple.\*escape-match.*""",
ExpressionMatch.MatchMode.MatchRegEx, true)
// Inverted regex, case-insensitive
val simpleMatchInvert =
ExpressionMatch("""!invert.\*escape-match.*""",
ExpressionMatch.MatchMode.MatchRegEx, false)
// Non-inverted regex, case-insensitive
val simpleMatchNoInvert =
ExpressionMatch("""\!simple.\*escape-match.*""",
ExpressionMatch.MatchMode.MatchRegEx, false)
// Non-inverted regex literal slash, case-insensitive
val simpleMatchNoInvertSlash =
ExpressionMatch("""\\!simple.\*escape-match.*""",
ExpressionMatch.MatchMode.MatchRegEx, false)
// Assert valid and not empty
assertTrue(simpleMatch.isValid())
assertFalse(simpleMatch.isEmpty())
assertTrue(simpleMatchCS.isValid())
assertFalse(simpleMatchCS.isEmpty())
assertTrue(simpleMatchInvert.isValid())
assertFalse(simpleMatchInvert.isEmpty())
assertTrue(simpleMatchNoInvert.isValid())
assertFalse(simpleMatchNoInvert.isEmpty())
assertTrue(simpleMatchNoInvertSlash.isValid())
assertFalse(simpleMatchNoInvertSlash.isEmpty())
// Assert match succeeds
assertTrue(simpleMatch.match("simpleA*escape-match"))
assertTrue(simpleMatch.match("simpleA*escape-matchBBBB"))
assertTrue(simpleMatchInvert.match("not above"))
assertTrue(simpleMatchNoInvert.match("!simpleA*escape-matchBBBB"))
assertTrue(simpleMatchNoInvertSlash.match("""\!simpleA*escape-matchBBBB"""))
// Assert partial match fails
assertFalse(simpleMatch.match("simpleA*escape-mat"))
assertFalse(simpleMatch.match("simple*escape-match"))
// Assert unrelated fails
assertFalse(simpleMatch.match("not above"))
// Assert escaped wildcard fails
assertFalse(simpleMatch.match("simpleABBBBescape-matchBBBB"))
// Assert inverted fails
assertFalse(simpleMatchInvert.match("invertA*escape-match"))
assertFalse(simpleMatchInvert.match("invertA*escape-matchBBBB"))
assertFalse(simpleMatchNoInvert.match("simpleA*escape-matchBBBB"))
assertFalse(simpleMatchNoInvert.match("anything"))
assertFalse(simpleMatchNoInvertSlash.match("!simpleA*escape-matchBBBB"))
assertFalse(simpleMatchNoInvertSlash.match("anything"))
// Assert case sensitivity followed
assertFalse(simpleMatch.sourceCaseSensitive)
assertTrue(simpleMatch.match("SiMpLEA*escape-MATCH"))
assertTrue(simpleMatchCS.sourceCaseSensitive)
assertFalse(simpleMatchCS.match("SiMpLEA*escape-MATCH"))
}
@Test
fun trimMultiWildcardWhitespace() {
// Patterns
val patterns = listOf(
// Literal
Pair("literal",
"literal"),
// Simple semicolon cleanup
Pair("simple1 ;simple2; simple3 ",
"simple1; simple2; simple3"),
// Simple newline cleanup
Pair("simple1 \nsimple2\n simple3 ",
"simple1\nsimple2\nsimple3"),
// Complex cleanup
Pair(
"""norm; norm-space ; newline-space """ + "\n" +
""" ;escape \; sep ; slash-end-split\\; quad\\\\norm; newline-split-slash\\""" + "\n" +
"""slash-at-end\\""",
"""norm; norm-space; newline-space""" + "\n" +
"""escape \; sep; slash-end-split\\; quad\\\\norm; newline-split-slash\\""" + "\n" +
"""slash-at-end\\"""
)
)
// Check every source string...
for (patternPair in patterns) {
// Run transformation
val result = ExpressionMatch.trimMultiWildcardWhitespace(patternPair.first)
// Assert that source trims into expected pattern
assertEquals(patternPair.second, result)
// Assert that re-trimming expected pattern gives the same result
assertEquals(ExpressionMatch.trimMultiWildcardWhitespace(result), result)
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment