Add tests for PushRule.Match and fork glob to make it compatible with the spec

This commit is contained in:
Tulir Asokan 2018-05-02 22:30:43 +03:00
parent 85cbd64c5e
commit aec3b8d204
9 changed files with 195 additions and 16 deletions

10
Gopkg.lock generated
View File

@ -61,12 +61,6 @@
packages = ["."] packages = ["."]
revision = "4611e809d8b1a3051c11d11f4b610c44df73fa38" revision = "4611e809d8b1a3051c11d11f4b610c44df73fa38"
[[projects]]
branch = "master"
name = "github.com/zyedidia/glob"
packages = ["."]
revision = "dd4023a66dc351ae26e592d21cd133b5b143f3d8"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "golang.org/x/image" name = "golang.org/x/image"
@ -88,7 +82,7 @@
"html", "html",
"html/atom" "html/atom"
] ]
revision = "5f9ae10d9af5b1c89ae6904293b14b064d4ada23" revision = "640f4622ab692b87c2f3a94265e6f579fe38263d"
[[projects]] [[projects]]
name = "golang.org/x/text" name = "golang.org/x/text"
@ -144,6 +138,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "ea0f742be221116a10b3fb332aee126fd8f4b3392b65a8e38a7c26e8c45faf8f" inputs-digest = "375d42f271992a59ae0bcf25e2401aae2f4d8adb7b63605c4ffef577c5154025"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -41,10 +41,6 @@
branch = "master" branch = "master"
name = "github.com/zyedidia/clipboard" name = "github.com/zyedidia/clipboard"
[[constraint]]
branch = "master"
name = "github.com/zyedidia/glob"
[[constraint]] [[constraint]]
branch = "master" branch = "master"
name = "golang.org/x/image" name = "golang.org/x/image"

View File

@ -24,6 +24,8 @@ func globToRegex(glob string) (*regexp.Regexp, error) {
firstIndexInClass := -1 firstIndexInClass := -1
arr := []byte(glob) arr := []byte(glob)
hasGlobCharacters := false
for i := 0; i < len(arr); i++ { for i := 0; i < len(arr); i++ {
ch := arr[i] ch := arr[i]
@ -50,16 +52,19 @@ func globToRegex(glob string) (*regexp.Regexp, error) {
} else { } else {
regex += "*" regex += "*"
} }
hasGlobCharacters = true
case '?': case '?':
if inClass == 0 { if inClass == 0 {
regex += "." regex += "."
} else { } else {
regex += "?" regex += "?"
} }
hasGlobCharacters = true
case '[': case '[':
inClass++ inClass++
firstIndexInClass = i + 1 firstIndexInClass = i + 1
regex += "[" regex += "["
hasGlobCharacters = true
case ']': case ']':
inClass-- inClass--
regex += "]" regex += "]"
@ -68,21 +73,25 @@ func globToRegex(glob string) (*regexp.Regexp, error) {
regex += "\\" regex += "\\"
} }
regex += string(ch) regex += string(ch)
hasGlobCharacters = true
case '!': case '!':
if firstIndexInClass == i { if firstIndexInClass == i {
regex += "^" regex += "^"
} else { } else {
regex += "!" regex += "!"
} }
hasGlobCharacters = true
case '{': case '{':
inGroup++ inGroup++
regex += "(" regex += "("
hasGlobCharacters = true
case '}': case '}':
inGroup-- inGroup--
regex += ")" regex += ")"
case ',': case ',':
if inGroup > 0 { if inGroup > 0 {
regex += "|" regex += "|"
hasGlobCharacters = true
} else { } else {
regex += "," regex += ","
} }
@ -90,5 +99,10 @@ func globToRegex(glob string) (*regexp.Regexp, error) {
regex += string(ch) regex += string(ch)
} }
} }
if hasGlobCharacters {
return regexp.Compile("^" + regex + "$") return regexp.Compile("^" + regex + "$")
} else {
return regexp.Compile(regex)
}
} }

View File

@ -21,7 +21,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/zyedidia/glob" "maunium.net/go/gomuks/lib/glob"
"maunium.net/go/gomatrix" "maunium.net/go/gomatrix"
"maunium.net/go/gomuks/matrix/rooms" "maunium.net/go/gomuks/matrix/rooms"
) )
@ -82,7 +82,10 @@ func (cond *PushCondition) matchValue(room Room, event *gomatrix.Event) bool {
key = key[0:index] key = key[0:index]
} }
pattern, _ := glob.Compile(cond.Pattern) pattern, err := glob.Compile(cond.Pattern)
if err != nil {
return false
}
switch key { switch key {
case "type": case "type":

View File

@ -47,6 +47,12 @@ func TestPushCondition_Match_KindEvent_EventType(t *testing.T) {
assert.True(t, condition.Match(blankTestRoom, event)) assert.True(t, condition.Match(blankTestRoom, event))
} }
func TestPushCondition_Match_KindEvent_EventType_IllegalGlob(t *testing.T) {
condition := newMatchPushCondition("type", "m.room.invalid_glo[b")
event := newFakeEvent("m.room.invalid_glob", map[string]interface{}{})
assert.False(t, condition.Match(blankTestRoom, event))
}
func TestPushCondition_Match_KindEvent_Sender_Fail(t *testing.T) { func TestPushCondition_Match_KindEvent_Sender_Fail(t *testing.T) {
condition := newMatchPushCondition("sender", "@foo:maunium.net") condition := newMatchPushCondition("sender", "@foo:maunium.net")
event := newFakeEvent("m.room.foo", map[string]interface{}{}) event := newFakeEvent("m.room.foo", map[string]interface{}{})

View File

@ -17,7 +17,7 @@
package pushrules package pushrules
import ( import (
"github.com/zyedidia/glob" "maunium.net/go/gomuks/lib/glob"
"maunium.net/go/gomatrix" "maunium.net/go/gomatrix"
) )

View File

@ -15,3 +15,169 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package pushrules_test package pushrules_test
import (
"testing"
"github.com/stretchr/testify/assert"
"maunium.net/go/gomuks/matrix/pushrules"
)
func TestPushRule_Match_Conditions(t *testing.T) {
cond1 := newMatchPushCondition("content.msgtype", "m.emote")
cond2 := newMatchPushCondition("content.body", "*pushrules")
rule := &pushrules.PushRule{
Type: pushrules.OverrideRule,
Enabled: true,
Conditions: []*pushrules.PushCondition{cond1, cond2},
}
event := newFakeEvent("m.room.message", map[string]interface{}{
"msgtype": "m.emote",
"body": "is testing pushrules",
})
assert.True(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Conditions_Disabled(t *testing.T) {
cond1 := newMatchPushCondition("content.msgtype", "m.emote")
cond2 := newMatchPushCondition("content.body", "*pushrules")
rule := &pushrules.PushRule{
Type: pushrules.OverrideRule,
Enabled: false,
Conditions: []*pushrules.PushCondition{cond1, cond2},
}
event := newFakeEvent("m.room.message", map[string]interface{}{
"msgtype": "m.emote",
"body": "is testing pushrules",
})
assert.False(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Conditions_FailIfOneFails(t *testing.T) {
cond1 := newMatchPushCondition("content.msgtype", "m.emote")
cond2 := newMatchPushCondition("content.body", "*pushrules")
rule := &pushrules.PushRule{
Type: pushrules.OverrideRule,
Enabled: true,
Conditions: []*pushrules.PushCondition{cond1, cond2},
}
event := newFakeEvent("m.room.message", map[string]interface{}{
"msgtype": "m.text",
"body": "I'm testing pushrules",
})
assert.False(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Content(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.ContentRule,
Enabled: true,
Pattern: "is testing*",
}
event := newFakeEvent("m.room.message", map[string]interface{}{
"msgtype": "m.emote",
"body": "is testing pushrules",
})
assert.True(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Content_Fail(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.ContentRule,
Enabled: true,
Pattern: "is testing*",
}
event := newFakeEvent("m.room.message", map[string]interface{}{
"msgtype": "m.emote",
"body": "is not testing pushrules",
})
assert.False(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Content_ImplicitGlob(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.ContentRule,
Enabled: true,
Pattern: "testing",
}
event := newFakeEvent("m.room.message", map[string]interface{}{
"msgtype": "m.emote",
"body": "is not testing pushrules",
})
assert.True(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Content_IllegalGlob(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.ContentRule,
Enabled: true,
Pattern: "this is not a valid glo[b",
}
event := newFakeEvent("m.room.message", map[string]interface{}{
"msgtype": "m.emote",
"body": "this is not a valid glob",
})
assert.False(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Room(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.RoomRule,
Enabled: true,
RuleID: "!fakeroom:maunium.net",
}
event := newFakeEvent("m.room.message", map[string]interface{}{})
assert.True(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Room_Fail(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.RoomRule,
Enabled: true,
RuleID: "!otherroom:maunium.net",
}
event := newFakeEvent("m.room.message", map[string]interface{}{})
assert.False(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Sender(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.SenderRule,
Enabled: true,
RuleID: "@tulir:maunium.net",
}
event := newFakeEvent("m.room.message", map[string]interface{}{})
assert.True(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_Sender_Fail(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.RoomRule,
Enabled: true,
RuleID: "@someone:matrix.org",
}
event := newFakeEvent("m.room.message", map[string]interface{}{})
assert.False(t, rule.Match(blankTestRoom, event))
}
func TestPushRule_Match_UnknownTypeAlwaysFail(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.PushRuleType("foobar"),
Enabled: true,
RuleID: "@someone:matrix.org",
}
event := newFakeEvent("m.room.message", map[string]interface{}{})
assert.False(t, rule.Match(blankTestRoom, event))
}