mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-25 05:19:25 +01:00
91cfdb963d
Make snomask add/remove behavior match other ircds
292 lines
8.6 KiB
Go
292 lines
8.6 KiB
Go
// Copyright (c) 2018 Shivaram Lingamneni
|
|
// released under the MIT license
|
|
|
|
package modes
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func assertEqual(supplied, expected interface{}, t *testing.T) {
|
|
if !reflect.DeepEqual(supplied, expected) {
|
|
t.Errorf("expected %v but got %v", expected, supplied)
|
|
}
|
|
}
|
|
|
|
func TestParseUserModeChanges(t *testing.T) {
|
|
emptyUnknown := make(map[rune]bool)
|
|
changes, unknown := ParseUserModeChanges("+i")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(changes, ModeChanges{ModeChange{Op: Add, Mode: Invisible}}, t)
|
|
|
|
// no-op change to sno
|
|
changes, unknown = ParseUserModeChanges("+is")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(changes, ModeChanges{ModeChange{Op: Add, Mode: Invisible}, ModeChange{Op: Add, Mode: ServerNotice}}, t)
|
|
|
|
// add snomasks
|
|
changes, unknown = ParseUserModeChanges("+is", "ac")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(changes, ModeChanges{ModeChange{Op: Add, Mode: Invisible}, ModeChange{Op: Add, Mode: ServerNotice, Arg: "ac"}}, t)
|
|
|
|
// remove snomasks
|
|
changes, unknown = ParseUserModeChanges("+s", "-cx")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(changes, ModeChanges{ModeChange{Op: Add, Mode: ServerNotice, Arg: "-cx"}}, t)
|
|
|
|
// remove all snomasks (arg is parsed but has no meaning)
|
|
changes, unknown = ParseUserModeChanges("-is", "ac")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(changes, ModeChanges{ModeChange{Op: Remove, Mode: Invisible}, ModeChange{Op: Remove, Mode: ServerNotice, Arg: "ac"}}, t)
|
|
|
|
// remove all snomasks
|
|
changes, unknown = ParseUserModeChanges("-is")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(changes, ModeChanges{ModeChange{Op: Remove, Mode: Invisible}, ModeChange{Op: Remove, Mode: ServerNotice}}, t)
|
|
}
|
|
|
|
func TestIssue874(t *testing.T) {
|
|
emptyUnknown := make(map[rune]bool)
|
|
modes, unknown := ParseChannelModeChanges("+k")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("+k", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{ModeChange{Op: Add, Mode: Key, Arg: "beer"}}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("-k")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{ModeChange{Op: Remove, Mode: Key, Arg: "*"}}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("-k", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{ModeChange{Op: Remove, Mode: Key, Arg: "*"}}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("+kb", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Add, Mode: Key, Arg: "beer"},
|
|
ModeChange{Op: List, Mode: BanMask, Arg: ""},
|
|
}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("-kb", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Remove, Mode: Key, Arg: "*"},
|
|
ModeChange{Op: List, Mode: BanMask, Arg: ""},
|
|
}, t)
|
|
|
|
// "beer" is the ban arg, +k with no arg should be ignored
|
|
modes, unknown = ParseChannelModeChanges("+bk", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Add, Mode: BanMask, Arg: "beer"},
|
|
}, t)
|
|
|
|
// "beer" is the ban arg again
|
|
modes, unknown = ParseChannelModeChanges("-bk", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Remove, Mode: BanMask, Arg: "beer"},
|
|
ModeChange{Op: Remove, Mode: Key, Arg: "*"},
|
|
}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("+bk", "shivaram", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Add, Mode: BanMask, Arg: "shivaram"},
|
|
ModeChange{Op: Add, Mode: Key, Arg: "beer"},
|
|
}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("+kb", "beer", "shivaram")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Add, Mode: Key, Arg: "beer"},
|
|
ModeChange{Op: Add, Mode: BanMask, Arg: "shivaram"},
|
|
}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("-bk", "shivaram", "beer")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Remove, Mode: BanMask, Arg: "shivaram"},
|
|
ModeChange{Op: Remove, Mode: Key, Arg: "*"},
|
|
}, t)
|
|
|
|
modes, unknown = ParseChannelModeChanges("-kb", "beer", "shivaram")
|
|
assertEqual(unknown, emptyUnknown, t)
|
|
assertEqual(modes, ModeChanges{
|
|
ModeChange{Op: Remove, Mode: Key, Arg: "*"},
|
|
ModeChange{Op: Remove, Mode: BanMask, Arg: "shivaram"},
|
|
}, t)
|
|
}
|
|
|
|
func TestParseChannelModeChanges(t *testing.T) {
|
|
modes, unknown := ParseChannelModeChanges("+h", "wrmsr")
|
|
if len(unknown) > 0 {
|
|
t.Errorf("unexpected unknown mode change: %v", unknown)
|
|
}
|
|
expected := ModeChange{
|
|
Op: Add,
|
|
Mode: Halfop,
|
|
Arg: "wrmsr",
|
|
}
|
|
if len(modes) != 1 || modes[0] != expected {
|
|
t.Errorf("unexpected mode change: %v", modes)
|
|
}
|
|
|
|
modes, unknown = ParseChannelModeChanges("-v", "shivaram")
|
|
if len(unknown) > 0 {
|
|
t.Errorf("unexpected unknown mode change: %v", unknown)
|
|
}
|
|
expected = ModeChange{
|
|
Op: Remove,
|
|
Mode: Voice,
|
|
Arg: "shivaram",
|
|
}
|
|
if len(modes) != 1 || modes[0] != expected {
|
|
t.Errorf("unexpected mode change: %v", modes)
|
|
}
|
|
|
|
modes, unknown = ParseChannelModeChanges("+tx")
|
|
if len(unknown) != 1 || !unknown['x'] {
|
|
t.Errorf("expected that x is an unknown mode, instead: %v", unknown)
|
|
}
|
|
expected = ModeChange{
|
|
Op: Add,
|
|
Mode: OpOnlyTopic,
|
|
Arg: "",
|
|
}
|
|
if len(modes) != 1 || modes[0] != expected {
|
|
t.Errorf("unexpected mode change: %v", modes)
|
|
}
|
|
|
|
modes, unknown = ParseChannelModeChanges("+b")
|
|
if len(unknown) > 0 {
|
|
t.Errorf("unexpected unknown mode change: %v", unknown)
|
|
}
|
|
// +b with no argument becomes a list operation
|
|
expectedChanges := ModeChanges{{
|
|
Op: List,
|
|
Mode: BanMask,
|
|
}}
|
|
if !reflect.DeepEqual(modes, expectedChanges) {
|
|
t.Errorf("unexpected mode change: %v instead of %v", modes, expectedChanges)
|
|
}
|
|
}
|
|
|
|
func TestSetMode(t *testing.T) {
|
|
set := NewModeSet()
|
|
|
|
if applied := set.SetMode(Invisible, false); applied != false {
|
|
t.Errorf("all modes should be false by default")
|
|
}
|
|
|
|
if applied := set.SetMode(Invisible, true); applied != true {
|
|
t.Errorf("initial SetMode call should return true")
|
|
}
|
|
|
|
set.SetMode(Operator, true)
|
|
|
|
if applied := set.SetMode(Invisible, true); applied != false {
|
|
t.Errorf("redundant SetMode call should return false")
|
|
}
|
|
|
|
expected1 := []Mode{Invisible, Operator}
|
|
expected2 := []Mode{Operator, Invisible}
|
|
if allModes := set.AllModes(); !(reflect.DeepEqual(allModes, expected1) || reflect.DeepEqual(allModes, expected2)) {
|
|
t.Errorf("unexpected AllModes value: %v", allModes)
|
|
}
|
|
|
|
if modeString := set.String(); !(modeString == "io" || modeString == "oi") {
|
|
t.Errorf("unexpected modestring: %s", modeString)
|
|
}
|
|
}
|
|
|
|
func TestModeString(t *testing.T) {
|
|
set := NewModeSet()
|
|
set.SetMode('A', true)
|
|
set.SetMode('z', true)
|
|
|
|
if modeString := set.String(); !(modeString == "Az" || modeString == "Za") {
|
|
t.Errorf("unexpected modestring: %s", modeString)
|
|
}
|
|
}
|
|
|
|
func TestNilReceivers(t *testing.T) {
|
|
set := NewModeSet()
|
|
set = nil
|
|
|
|
if set.HasMode(Invisible) {
|
|
t.Errorf("nil ModeSet should not have any modes")
|
|
}
|
|
|
|
str := set.String()
|
|
if str != "" {
|
|
t.Errorf("nil Modeset should have empty String(), got %v instead", str)
|
|
}
|
|
}
|
|
|
|
func TestHighestChannelUserMode(t *testing.T) {
|
|
set := NewModeSet()
|
|
|
|
if set.HighestChannelUserMode() != Mode(0) {
|
|
t.Errorf("no channel user modes should be present yet")
|
|
}
|
|
|
|
set.SetMode(Voice, true)
|
|
if set.HighestChannelUserMode() != Voice {
|
|
t.Errorf("should see that user is voiced")
|
|
}
|
|
|
|
set.SetMode(ChannelAdmin, true)
|
|
if set.HighestChannelUserMode() != ChannelAdmin {
|
|
t.Errorf("should see that user has channel admin")
|
|
}
|
|
|
|
set = nil
|
|
if set.HighestChannelUserMode() != Mode(0) {
|
|
t.Errorf("nil modeset should have the zero mode as highest channel-user mode")
|
|
}
|
|
}
|
|
|
|
func TestChanmodesToken(t *testing.T) {
|
|
tok := ChanmodesToken()
|
|
for _, mode := range SupportedChannelModes {
|
|
if strings.IndexRune(tok, rune(mode)) == -1 {
|
|
t.Errorf("+%s not included in ChanmodesToken()", mode)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestModeChangesString(t *testing.T) {
|
|
m := ModeChanges{
|
|
ModeChange{Op: Add, Mode: RegisteredOnly},
|
|
ModeChange{Op: Add, Mode: Key, Arg: "beer"},
|
|
ModeChange{Op: Add, Mode: BanMask, Arg: "shivaram"},
|
|
}
|
|
assertEqual(m.Strings(), []string{"+Rkb", "beer", "shivaram"}, t)
|
|
|
|
m = ModeChanges{
|
|
ModeChange{Op: Add, Mode: RegisteredOnly},
|
|
ModeChange{Op: Remove, Mode: Key, Arg: "beer"},
|
|
ModeChange{Op: Add, Mode: BanMask, Arg: "shivaram"},
|
|
}
|
|
assertEqual(m.Strings(), []string{"+R-k+b", "beer", "shivaram"}, t)
|
|
}
|
|
|
|
func BenchmarkModeString(b *testing.B) {
|
|
set := NewModeSet()
|
|
set.SetMode('A', true)
|
|
set.SetMode('N', true)
|
|
set.SetMode('b', true)
|
|
set.SetMode('i', true)
|
|
set.SetMode('x', true)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = set.String()
|
|
}
|
|
}
|