Upstream: merge in some changes
This commit is contained in:
parent
f6b2020909
commit
18243520dc
|
@ -553,7 +553,7 @@ func handleMOTD(c *Client, e Event) {
|
|||
}
|
||||
|
||||
// Otherwise, assume we're getting sent the MOTD line-by-line.
|
||||
if len(c.state.motd) != 0 {
|
||||
if c.state.motd != "" {
|
||||
c.state.motd += "\n"
|
||||
}
|
||||
c.state.motd += e.Last()
|
||||
|
|
2
cap.go
2
cap.go
|
@ -62,7 +62,7 @@ func possibleCapList(c *Client) map[string][]string {
|
|||
if !c.Config.DisableSTS && !c.Config.SSL {
|
||||
// If fallback supported, and we failed recently, don't try negotiating STS.
|
||||
// ONLY do this fallback if we're expired (primarily useful during the first
|
||||
// sts negotation).
|
||||
// sts negotiation).
|
||||
if time.Since(c.state.sts.lastFailed) < 5*time.Minute && !c.Config.DisableSTSFallback {
|
||||
c.debug.Println("skipping strict transport policy negotiation; failed within the last 5 minutes")
|
||||
} else {
|
||||
|
|
44
cap_test.go
44
cap_test.go
|
@ -34,26 +34,36 @@ func TestCapSupported(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestParseCap(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
want map[string]map[string]string
|
||||
}{
|
||||
{in: "sts=port=6697,duration=1234567890,preload", want: map[string]map[string]string{"sts": {"duration": "1234567890", "preload": "", "port": "6697"}}},
|
||||
{in: "userhost-in-names", want: map[string]map[string]string{"userhost-in-names": nil}},
|
||||
{in: "userhost-in-names test2", want: map[string]map[string]string{"userhost-in-names": nil, "test2": nil}},
|
||||
{in: "example/name=test", want: map[string]map[string]string{"example/name": {"test": ""}}},
|
||||
{
|
||||
in: "userhost-in-names example/name example/name2=test=1,test2=true",
|
||||
want: map[string]map[string]string{
|
||||
"userhost-in-names": nil,
|
||||
"example/name": nil,
|
||||
"example/name2": {"test": "1", "test2": "true"},
|
||||
},
|
||||
var testsParseCap = []struct {
|
||||
in string
|
||||
want map[string]map[string]string
|
||||
}{
|
||||
{in: "sts=port=6697,duration=1234567890,preload", want: map[string]map[string]string{"sts": {"duration": "1234567890", "preload": "", "port": "6697"}}},
|
||||
{in: "userhost-in-names", want: map[string]map[string]string{"userhost-in-names": nil}},
|
||||
{in: "userhost-in-names test2", want: map[string]map[string]string{"userhost-in-names": nil, "test2": nil}},
|
||||
{in: "example/name=test", want: map[string]map[string]string{"example/name": {"test": ""}}},
|
||||
{
|
||||
in: "userhost-in-names example/name example/name2=test=1,test2=true",
|
||||
want: map[string]map[string]string{
|
||||
"userhost-in-names": nil,
|
||||
"example/name": nil,
|
||||
"example/name2": {"test": "1", "test2": "true"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func FuzzParseCap(f *testing.F) {
|
||||
for _, tc := range testsParseCap {
|
||||
f.Add(tc.in)
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
_ = parseCap(orig)
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseCap(t *testing.T) {
|
||||
for _, tt := range testsParseCap {
|
||||
got := parseCap(tt.in)
|
||||
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
|
@ -275,10 +274,10 @@ func (conf *Config) isValid() error {
|
|||
}
|
||||
|
||||
if !IsValidNick(conf.Nick) {
|
||||
return &ErrInvalidConfig{Conf: *conf, err: errors.New("bad nickname specified: " + conf.Nick)}
|
||||
return &ErrInvalidConfig{Conf: *conf, err: fmt.Errorf("bad nickname specified: %s", conf.Nick)}
|
||||
}
|
||||
if !IsValidUser(conf.User) {
|
||||
return &ErrInvalidConfig{Conf: *conf, err: errors.New("bad user/ident specified: " + conf.User)}
|
||||
return &ErrInvalidConfig{Conf: *conf, err: fmt.Errorf("bad user/ident specified: %s", conf.Nick)}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -320,7 +319,7 @@ func New(config Config) *Client {
|
|||
if envDebug {
|
||||
c.debug = log.New(os.Stderr, "debug:", log.Ltime|log.Lshortfile)
|
||||
} else {
|
||||
c.debug = log.New(ioutil.Discard, "", 0)
|
||||
c.debug = log.New(io.Discard, "", 0)
|
||||
}
|
||||
} else {
|
||||
if envDebug {
|
||||
|
@ -850,7 +849,7 @@ func (c *Client) debugLogEvent(e *Event, dropped bool) {
|
|||
|
||||
if pretty, ok := e.Pretty(); ok {
|
||||
|
||||
fmt.Fprintln(c.Config.Out, StripRaw(pretty))
|
||||
_, _ = fmt.Fprintln(c.Config.Out, StripRaw(pretty))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ func (cmd *Commands) Join(channels ...string) {
|
|||
continue
|
||||
}
|
||||
|
||||
if len(buffer) == 0 {
|
||||
if buffer == "" {
|
||||
buffer = channels[i]
|
||||
} else {
|
||||
buffer += "," + channels[i]
|
||||
|
@ -366,7 +366,7 @@ func (cmd *Commands) List(channels ...string) {
|
|||
continue
|
||||
}
|
||||
|
||||
if len(buffer) == 0 {
|
||||
if buffer == "" {
|
||||
buffer = channels[i]
|
||||
} else {
|
||||
buffer += "," + channels[i]
|
||||
|
|
17
conn.go
17
conn.go
|
@ -167,18 +167,6 @@ func (c *ircConn) decode() (event *Event, err error) {
|
|||
return event, nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (c *ircConn) encode(event *Event) error {
|
||||
if _, err := c.io.Write(event.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := c.io.Write(endline); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.io.Flush()
|
||||
}
|
||||
*/
|
||||
func (c *ircConn) newReadWriter() {
|
||||
c.io = bufio.NewReadWriter(bufio.NewReader(c.sock), bufio.NewWriter(c.sock))
|
||||
}
|
||||
|
@ -609,9 +597,8 @@ func (c *Client) pingLoop(ctx context.Context, errs chan error, working *int32)
|
|||
past = true
|
||||
}
|
||||
|
||||
if time.Since(c.conn.lastPong.Load().(time.Time)) > c.Config.PingDelay+(120*time.Second) {
|
||||
// It's 60 seconds over what out ping delay is, connection
|
||||
// has probably dropped.
|
||||
if time.Since(c.conn.lastPong.Load().(time.Time)) > c.Config.PingDelay+(180*time.Second) {
|
||||
// It's 180 seconds over what out ping delay is, connection has probably dropped.
|
||||
|
||||
err := ErrTimedOut{
|
||||
TimeSinceSuccess: time.Since(c.conn.lastPong.Load().(time.Time)),
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func mockBuffers() (in *bytes.Buffer, out *bytes.Buffer, irc *ircConn) {
|
||||
func mockBuffers() (in, out *bytes.Buffer, irc *ircConn) {
|
||||
in = &bytes.Buffer{}
|
||||
out = &bytes.Buffer{}
|
||||
irc = &ircConn{
|
||||
|
@ -88,7 +88,7 @@ func TestRate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func genMockConn() (client *Client, clientConn net.Conn, serverConn net.Conn) {
|
||||
func genMockConn() (client *Client, clientConn, serverConn net.Conn) {
|
||||
client = New(Config{
|
||||
Server: "dummy.int",
|
||||
Port: 6667,
|
||||
|
@ -107,7 +107,7 @@ func mockReadBuffer(conn net.Conn) {
|
|||
// Accept all outgoing writes from the client.
|
||||
b := bufio.NewReader(conn)
|
||||
for {
|
||||
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
|
||||
_, err := b.ReadString(byte('\n'))
|
||||
if err != nil {
|
||||
return
|
||||
|
|
7
ctcp.go
7
ctcp.go
|
@ -104,8 +104,8 @@ func EncodeCTCP(ctcp *CTCPEvent) (out string) {
|
|||
// EncodeCTCPRaw is much like EncodeCTCP, however accepts a raw command and
|
||||
// string as input.
|
||||
func EncodeCTCPRaw(cmd, text string) (out string) {
|
||||
if len(cmd) <= 0 {
|
||||
return ""
|
||||
if cmd == "" {
|
||||
return cmd
|
||||
}
|
||||
|
||||
out = string(ctcpDelim) + cmd
|
||||
|
@ -191,9 +191,8 @@ func (c *CTCP) Set(cmd string, handler func(client *Client, ctcp CTCPEvent)) {
|
|||
return
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.handlers[cmd] = handler
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// SetBg is much like Set, however the handler is executed in the background,
|
||||
|
|
61
ctcp_test.go
61
ctcp_test.go
|
@ -9,26 +9,40 @@ import (
|
|||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var testsEncodeCTCP = []struct {
|
||||
name string
|
||||
test *CTCPEvent
|
||||
want string
|
||||
}{
|
||||
{name: "command only", test: &CTCPEvent{Command: "TEST", Text: ""}, want: "\001TEST\001"},
|
||||
{name: "command with args", test: &CTCPEvent{Command: "TEST", Text: "TEST"}, want: "\001TEST TEST\001"},
|
||||
{name: "nil command", test: &CTCPEvent{Command: "", Text: "TEST"}, want: ""},
|
||||
{name: "nil event", test: nil, want: ""},
|
||||
}
|
||||
|
||||
func FuzzEncodeCTCP(f *testing.F) {
|
||||
for _, tc := range testsEncodeCTCP {
|
||||
if tc.test == nil {
|
||||
continue
|
||||
}
|
||||
f.Add(tc.test.Command, tc.test.Text)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, cmd, text string) {
|
||||
got := EncodeCTCP(&CTCPEvent{Command: cmd, Text: text})
|
||||
|
||||
if utf8.ValidString(cmd) && utf8.ValidString(text) && !utf8.ValidString(got) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestEncodeCTCP(t *testing.T) {
|
||||
type args struct {
|
||||
ctcp *CTCPEvent
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{name: "command only", args: args{ctcp: &CTCPEvent{Command: "TEST", Text: ""}}, want: "\001TEST\001"},
|
||||
{name: "command with args", args: args{ctcp: &CTCPEvent{Command: "TEST", Text: "TEST"}}, want: "\001TEST TEST\001"},
|
||||
{name: "nil command", args: args{ctcp: &CTCPEvent{Command: "", Text: "TEST"}}, want: ""},
|
||||
{name: "nil event", args: args{ctcp: nil}, want: ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := EncodeCTCP(tt.args.ctcp); got != tt.want {
|
||||
for _, tt := range testsEncodeCTCP {
|
||||
if got := EncodeCTCP(tt.test); got != tt.want {
|
||||
t.Errorf("%s: encodeCTCP() = %q, want %q", tt.name, got, tt.want)
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +124,8 @@ func TestCall(t *testing.T) {
|
|||
atomic.AddUint64(&counter, 1)
|
||||
})
|
||||
|
||||
if ctcp.call(New(Config{}), &CTCPEvent{Command: "TEST"}); atomic.LoadUint64(&counter) != 1 {
|
||||
ctcp.call(New(Config{}), &CTCPEvent{Command: "TEST"})
|
||||
if atomic.LoadUint64(&counter) != 1 {
|
||||
t.Fatal("regular execution: call() didn't increase counter")
|
||||
}
|
||||
ctcp.Clear("TEST")
|
||||
|
@ -120,7 +135,8 @@ func TestCall(t *testing.T) {
|
|||
})
|
||||
|
||||
ctcp.call(New(Config{}), &CTCPEvent{Command: "TEST"})
|
||||
if time.Sleep(250 * time.Millisecond); atomic.LoadUint64(&counter) != 2 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
if atomic.LoadUint64(&counter) != 2 {
|
||||
t.Fatal("goroutine execution: call() in goroutine didn't increase counter")
|
||||
}
|
||||
ctcp.Clear("TEST")
|
||||
|
@ -129,14 +145,15 @@ func TestCall(t *testing.T) {
|
|||
atomic.AddUint64(&counter, 1)
|
||||
})
|
||||
|
||||
if ctcp.call(New(Config{}), &CTCPEvent{Command: "TEST"}); atomic.LoadUint64(&counter) != 3 {
|
||||
ctcp.call(New(Config{}), &CTCPEvent{Command: "TEST"})
|
||||
if atomic.LoadUint64(&counter) != 3 {
|
||||
t.Fatal("wildcard execution: call() didn't increase counter")
|
||||
}
|
||||
ctcp.Clear("*")
|
||||
|
||||
ctcp.Clear("TEST")
|
||||
|
||||
if ctcp.call(New(Config{}), &CTCPEvent{Command: "TEST"}); atomic.LoadUint64(&counter) != 3 {
|
||||
ctcp.call(New(Config{}), &CTCPEvent{Command: "TEST"})
|
||||
if atomic.LoadUint64(&counter) != 3 {
|
||||
t.Fatal("empty execution: call() with no handler incremented the counter")
|
||||
}
|
||||
}
|
||||
|
|
8
event.go
8
event.go
|
@ -52,7 +52,7 @@ func ParseEvent(raw string) (e *Event) {
|
|||
i = 0
|
||||
}
|
||||
|
||||
if raw[0] == messagePrefix {
|
||||
if raw != "" && raw[0] == messagePrefix {
|
||||
// Prefix ends with a space.
|
||||
i = strings.IndexByte(raw, eventSpace)
|
||||
|
||||
|
@ -313,7 +313,9 @@ func (e *Event) Bytes() []byte {
|
|||
buffer.Truncate(maxLength)
|
||||
}
|
||||
|
||||
out := buffer.Bytes()
|
||||
// If we truncated in the middle of a utf8 character, we need to remove
|
||||
// the other (now invalid) bytes.
|
||||
out := bytes.ToValidUTF8(buffer.Bytes(), nil)
|
||||
|
||||
// Strip newlines and carriage returns.
|
||||
for i := 0; i < len(out); i++ {
|
||||
|
@ -638,7 +640,7 @@ func (s *Source) IsHostmask() bool {
|
|||
|
||||
// IsServer returns true if this source looks like a server name.
|
||||
func (s *Source) IsServer() bool {
|
||||
return len(s.Ident) <= 0 && len(s.Host) <= 0
|
||||
return s.Ident == "" && s.Host == ""
|
||||
}
|
||||
|
||||
// writeTo is an utility function to write the source to the bytes.Buffer
|
||||
|
|
12
format.go
12
format.go
|
@ -127,10 +127,10 @@ func Fmt(text string) string {
|
|||
// See Fmt() for more information.
|
||||
func TrimFmt(text string) string {
|
||||
for color := range fmtColors {
|
||||
text = strings.Replace(text, string(fmtOpenChar)+color+string(fmtCloseChar), "", -1)
|
||||
text = strings.ReplaceAll(text, string(fmtOpenChar)+color+string(fmtCloseChar), "")
|
||||
}
|
||||
for code := range fmtCodes {
|
||||
text = strings.Replace(text, string(fmtOpenChar)+code+string(fmtCloseChar), "", -1)
|
||||
text = strings.ReplaceAll(text, string(fmtOpenChar)+code+string(fmtCloseChar), "")
|
||||
}
|
||||
|
||||
return text
|
||||
|
@ -138,7 +138,7 @@ func TrimFmt(text string) string {
|
|||
|
||||
// This is really the only fastest way of doing this (marginally better than
|
||||
// actually trying to parse it manually.)
|
||||
var reStripColor = regexp.MustCompile(`\x03([019]?[0-9](,[019]?[0-9])?)?`)
|
||||
var reStripColor = regexp.MustCompile(`\x03([019]?\d(,[019]?\d)?)?`)
|
||||
|
||||
// StripRaw tries to strip all ASCII format codes that are used for IRC.
|
||||
// Primarily, foreground/background colors, and other control bytes like
|
||||
|
@ -148,7 +148,7 @@ func StripRaw(text string) string {
|
|||
text = reStripColor.ReplaceAllString(text, "")
|
||||
|
||||
for _, code := range fmtCodes {
|
||||
text = strings.Replace(text, code, "", -1)
|
||||
text = strings.ReplaceAll(text, code, "")
|
||||
}
|
||||
|
||||
return text
|
||||
|
@ -219,7 +219,7 @@ func IsValidChannel(channel string) bool {
|
|||
// digit = 0x30-0x39
|
||||
// special = 0x5B-0x60 / 0x7B-0x7D
|
||||
func IsValidNick(nick string) bool {
|
||||
if len(nick) <= 0 {
|
||||
if nick == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ func IsValidNick(nick string) bool {
|
|||
// user = 1*( %x01-09 / %x0B-0C / %x0E-1F / %x21-3F / %x41-FF )
|
||||
// ; any octet except NUL, CR, LF, " " and "@"
|
||||
func IsValidUser(name string) bool {
|
||||
if len(name) <= 0 {
|
||||
if name == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
456
format_test.go
456
format_test.go
|
@ -7,6 +7,7 @@ package girc
|
|||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func BenchmarkFormat(b *testing.B) {
|
||||
|
@ -47,207 +48,294 @@ func BenchmarkStripRawLong(b *testing.B) {
|
|||
}
|
||||
}
|
||||
|
||||
var testsFormat = []struct {
|
||||
name string
|
||||
test string
|
||||
want string
|
||||
}{
|
||||
{name: "middle", test: "test{red}test{c}test", want: "test\x0304test\x03test"},
|
||||
{name: "middle with bold", test: "test{red}{b}test{c}test", want: "test\x0304\x02test\x03test"},
|
||||
{name: "start, end", test: "{red}test{c}", want: "\x0304test\x03"},
|
||||
{name: "start, middle, end", test: "{red}te{red}st{c}", want: "\x0304te\x0304st\x03"},
|
||||
{name: "partial", test: "{redtest{c}", want: "{redtest\x03"},
|
||||
{name: "inside", test: "{re{c}d}test{c}", want: "{re\x03d}test\x03"},
|
||||
{name: "nothing", test: "this is a test.", want: "this is a test."},
|
||||
{name: "fg and bg", test: "{red,yellow}test{c}", want: "\x0304,08test\x03"},
|
||||
{name: "just bg", test: "{,yellow}test{c}", want: "test\x03"},
|
||||
{name: "just red", test: "{red}test", want: "\x0304test"},
|
||||
{name: "just cyan", test: "{cyan}test", want: "\x0311test"},
|
||||
}
|
||||
|
||||
func FuzzFormat(f *testing.F) {
|
||||
for _, tc := range testsFormat {
|
||||
f.Add(tc.test)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
got := Fmt(orig)
|
||||
got2 := Fmt(got)
|
||||
|
||||
if utf8.ValidString(orig) {
|
||||
if !utf8.ValidString(got) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got)
|
||||
}
|
||||
|
||||
if !utf8.ValidString(got2) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormat(t *testing.T) {
|
||||
type args struct {
|
||||
text string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{name: "middle", args: args{text: "test{red}test{c}test"}, want: "test\x0304test\x03test"},
|
||||
{name: "middle with bold", args: args{text: "test{red}{b}test{c}test"}, want: "test\x0304\x02test\x03test"},
|
||||
{name: "start, end", args: args{text: "{red}test{c}"}, want: "\x0304test\x03"},
|
||||
{name: "start, middle, end", args: args{text: "{red}te{red}st{c}"}, want: "\x0304te\x0304st\x03"},
|
||||
{name: "partial", args: args{text: "{redtest{c}"}, want: "{redtest\x03"},
|
||||
{name: "inside", args: args{text: "{re{c}d}test{c}"}, want: "{re\x03d}test\x03"},
|
||||
{name: "nothing", args: args{text: "this is a test."}, want: "this is a test."},
|
||||
{name: "fg and bg", args: args{text: "{red,yellow}test{c}"}, want: "\x0304,08test\x03"},
|
||||
{name: "just bg", args: args{text: "{,yellow}test{c}"}, want: "test\x03"},
|
||||
{name: "just red", args: args{text: "{red}test"}, want: "\x0304test"},
|
||||
{name: "just cyan", args: args{text: "{cyan}test"}, want: "\x0311test"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := Fmt(tt.args.text); got != tt.want {
|
||||
t.Errorf("%s: Format(%q) = %q, want %q", tt.name, tt.args.text, got, tt.want)
|
||||
for _, tt := range testsFormat {
|
||||
if got := Fmt(tt.test); got != tt.want {
|
||||
t.Errorf("%s: Format(%q) = %q, want %q", tt.name, tt.test, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testsStripFormat = []struct {
|
||||
name string
|
||||
test string
|
||||
want string
|
||||
}{
|
||||
{name: "start, end", test: "{red}test{c}", want: "test"},
|
||||
{name: "start, middle, end", test: "{red}te{red}st{c}", want: "test"},
|
||||
{name: "partial", test: "{redtest{c}", want: "{redtest"},
|
||||
{name: "inside", test: "{re{c}d}test{c}", want: "{red}test"},
|
||||
{name: "nothing", test: "this is a test.", want: "this is a test."},
|
||||
}
|
||||
|
||||
func FuzzStripFormat(f *testing.F) {
|
||||
for _, tc := range testsStripFormat {
|
||||
f.Add(tc.test)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
got := TrimFmt(orig)
|
||||
got2 := TrimFmt(got)
|
||||
|
||||
if utf8.ValidString(orig) {
|
||||
if !utf8.ValidString(got) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got)
|
||||
}
|
||||
|
||||
if !utf8.ValidString(got2) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestStripFormat(t *testing.T) {
|
||||
type args struct {
|
||||
text string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{name: "start, end", args: args{text: "{red}test{c}"}, want: "test"},
|
||||
{name: "start, middle, end", args: args{text: "{red}te{red}st{c}"}, want: "test"},
|
||||
{name: "partial", args: args{text: "{redtest{c}"}, want: "{redtest"},
|
||||
{name: "inside", args: args{text: "{re{c}d}test{c}"}, want: "{red}test"},
|
||||
{name: "nothing", args: args{text: "this is a test."}, want: "this is a test."},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := TrimFmt(tt.args.text); got != tt.want {
|
||||
t.Errorf("%s: StripFormat(%q) = %q, want %q", tt.name, tt.args.text, got, tt.want)
|
||||
for _, tt := range testsStripFormat {
|
||||
if got := TrimFmt(tt.test); got != tt.want {
|
||||
t.Errorf("%s: StripFormat(%q) = %q, want %q", tt.name, tt.test, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testsStripRaw = []struct {
|
||||
name string
|
||||
test string // gets passed to Format() before sent
|
||||
want string
|
||||
}{
|
||||
{name: "start, end", test: "{red}{b}test{c}", want: "test"},
|
||||
{name: "start, end in numbers", test: "{red}1234{c}", want: "1234"},
|
||||
{name: "start, middle, end", test: "{red}te{red}st{c}", want: "test"},
|
||||
{name: "partial", test: "{redtest{c}", want: "{redtest"},
|
||||
{name: "inside", test: "{re{c}d}test{c}", want: "{red}test"},
|
||||
{name: "fg+bg colors start", test: "{red,yellow}test{c}", want: "test"},
|
||||
{name: "fg+bg colors start in numbers", test: "{red,yellow}1234{c}", want: "1234"},
|
||||
{name: "fg+bg colors end", test: "test{,yellow}", want: "test"},
|
||||
{name: "bg colors start", test: "{,yellow}test{c}", want: "test"},
|
||||
{name: "inside", test: "{re{c}d}test{c}", want: "{red}test"},
|
||||
{name: "nothing", test: "this is a test.", want: "this is a test."},
|
||||
}
|
||||
|
||||
func FuzzStripRaw(f *testing.F) {
|
||||
for _, tc := range testsStripRaw {
|
||||
f.Add(tc.test)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
got := StripRaw(orig)
|
||||
got2 := StripRaw(got)
|
||||
|
||||
if utf8.ValidString(orig) {
|
||||
if !utf8.ValidString(got) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got)
|
||||
}
|
||||
|
||||
if !utf8.ValidString(got2) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestStripRaw(t *testing.T) {
|
||||
type args struct {
|
||||
text string
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args // gets passed to Format() before sent
|
||||
want string
|
||||
}{
|
||||
{name: "start, end", args: args{text: "{red}{b}test{c}"}, want: "test"},
|
||||
{name: "start, end in numbers", args: args{text: "{red}1234{c}"}, want: "1234"},
|
||||
{name: "start, middle, end", args: args{text: "{red}te{red}st{c}"}, want: "test"},
|
||||
{name: "partial", args: args{text: "{redtest{c}"}, want: "{redtest"},
|
||||
{name: "inside", args: args{text: "{re{c}d}test{c}"}, want: "{red}test"},
|
||||
{name: "fg+bg colors start", args: args{text: "{red,yellow}test{c}"}, want: "test"},
|
||||
{name: "fg+bg colors start in numbers", args: args{text: "{red,yellow}1234{c}"}, want: "1234"},
|
||||
{name: "fg+bg colors end", args: args{text: "test{,yellow}"}, want: "test"},
|
||||
{name: "bg colors start", args: args{text: "{,yellow}test{c}"}, want: "test"},
|
||||
{name: "inside", args: args{text: "{re{c}d}test{c}"}, want: "{red}test"},
|
||||
{name: "nothing", args: args{text: "this is a test."}, want: "this is a test."},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := StripRaw(Fmt(tt.args.text)); got != tt.want {
|
||||
t.Fatalf("%s: StripRaw(%q) = %q, want %q", tt.name, tt.args.text, got, tt.want)
|
||||
for _, tt := range testsStripRaw {
|
||||
if got := StripRaw(Fmt(tt.test)); got != tt.want {
|
||||
t.Fatalf("%s: StripRaw(%q) = %q, want %q", tt.name, tt.test, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testsValidNick = []struct {
|
||||
name string
|
||||
test string
|
||||
want bool
|
||||
}{
|
||||
{name: "normal", test: "test", want: true},
|
||||
{name: "empty", test: "", want: false},
|
||||
{name: "hyphen and special", test: "test[-]", want: true},
|
||||
{name: "invalid middle", test: "test!test", want: false},
|
||||
{name: "invalid dot middle", test: "test.test", want: false},
|
||||
{name: "end", test: "test!", want: false},
|
||||
{name: "invalid start", test: "!test", want: false},
|
||||
{name: "backslash and numeric", test: "test[\\0", want: true},
|
||||
{name: "long", test: "test123456789AZBKASDLASMDLKM", want: true},
|
||||
{name: "index 0 dash", test: "-test", want: false},
|
||||
{name: "index 0 numeric", test: "0test", want: false},
|
||||
{name: "RFC1459 non-lowercase-converted", test: "test^", want: true},
|
||||
{name: "RFC1459 non-lowercase-converted", test: "test~", want: false},
|
||||
}
|
||||
|
||||
func FuzzValidNick(f *testing.F) {
|
||||
for _, tc := range testsValidNick {
|
||||
f.Add(tc.test)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
_ = IsValidNick(orig)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsValidNick(t *testing.T) {
|
||||
type args struct {
|
||||
nick string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{name: "normal", args: args{nick: "test"}, want: true},
|
||||
{name: "empty", args: args{nick: ""}, want: false},
|
||||
{name: "hyphen and special", args: args{nick: "test[-]"}, want: true},
|
||||
{name: "invalid middle", args: args{nick: "test!test"}, want: false},
|
||||
{name: "invalid dot middle", args: args{nick: "test.test"}, want: false},
|
||||
{name: "end", args: args{nick: "test!"}, want: false},
|
||||
{name: "invalid start", args: args{nick: "!test"}, want: false},
|
||||
{name: "backslash and numeric", args: args{nick: "test[\\0"}, want: true},
|
||||
{name: "long", args: args{nick: "test123456789AZBKASDLASMDLKM"}, want: true},
|
||||
{name: "index 0 dash", args: args{nick: "-test"}, want: false},
|
||||
{name: "index 0 numeric", args: args{nick: "0test"}, want: false},
|
||||
{name: "RFC1459 non-lowercase-converted", args: args{nick: "test^"}, want: true},
|
||||
{name: "RFC1459 non-lowercase-converted", args: args{nick: "test~"}, want: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := IsValidNick(tt.args.nick); got != tt.want {
|
||||
t.Errorf("%s: IsValidNick(%q) = %v, want %v", tt.name, tt.args.nick, got, tt.want)
|
||||
for _, tt := range testsValidNick {
|
||||
if got := IsValidNick(tt.test); got != tt.want {
|
||||
t.Errorf("%s: IsValidNick(%q) = %v, want %v", tt.name, tt.test, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testsValidChannel = []struct {
|
||||
name string
|
||||
test string
|
||||
want bool
|
||||
}{
|
||||
{name: "valid channel", test: "#valid", want: true},
|
||||
{name: "invalid channel comma", test: "#invalid,", want: false},
|
||||
{name: "invalid channel space", test: "#inva lid", want: false},
|
||||
{name: "valid channel with numerics", test: "#1valid0", want: true},
|
||||
{name: "valid channel with special", test: "#valid[]test", want: true},
|
||||
{name: "valid channel with special", test: "#[]valid[]test[]", want: true},
|
||||
{name: "just hash", test: "#", want: false},
|
||||
{name: "empty", test: "", want: false},
|
||||
{name: "invalid prefix", test: "$invalid", want: false},
|
||||
{name: "too long", test: "#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", want: false},
|
||||
{name: "valid id prefix", test: "!12345test", want: true},
|
||||
{name: "invalid id length", test: "!1234", want: false},
|
||||
{name: "invalid id length", test: "!12345", want: false},
|
||||
{name: "invalid id prefix", test: "!test1invalid", want: false},
|
||||
}
|
||||
|
||||
func FuzzValidChannel(f *testing.F) {
|
||||
for _, tc := range testsValidChannel {
|
||||
f.Add(tc.test)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
_ = IsValidChannel(orig)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsValidChannel(t *testing.T) {
|
||||
type args struct {
|
||||
channel string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{name: "valid channel", args: args{channel: "#valid"}, want: true},
|
||||
{name: "invalid channel comma", args: args{channel: "#invalid,"}, want: false},
|
||||
{name: "invalid channel space", args: args{channel: "#inva lid"}, want: false},
|
||||
{name: "valid channel with numerics", args: args{channel: "#1valid0"}, want: true},
|
||||
{name: "valid channel with special", args: args{channel: "#valid[]test"}, want: true},
|
||||
{name: "valid channel with special", args: args{channel: "#[]valid[]test[]"}, want: true},
|
||||
{name: "just hash", args: args{channel: "#"}, want: false},
|
||||
{name: "empty", args: args{channel: ""}, want: false},
|
||||
{name: "invalid prefix", args: args{channel: "$invalid"}, want: false},
|
||||
{name: "too long", args: args{channel: "#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, want: false},
|
||||
{name: "valid id prefix", args: args{channel: "!12345test"}, want: true},
|
||||
{name: "invalid id length", args: args{channel: "!1234"}, want: false},
|
||||
{name: "invalid id length", args: args{channel: "!12345"}, want: false},
|
||||
{name: "invalid id prefix", args: args{channel: "!test1invalid"}, want: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := IsValidChannel(tt.args.channel); got != tt.want {
|
||||
t.Errorf("%s: IsValidChannel(%q) = %v, want %v", tt.name, tt.args.channel, got, tt.want)
|
||||
for _, tt := range testsValidChannel {
|
||||
if got := IsValidChannel(tt.test); got != tt.want {
|
||||
t.Errorf("%s: IsValidChannel(%q) = %v, want %v", tt.name, tt.test, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testsValidUser = []struct {
|
||||
name string
|
||||
test string
|
||||
want bool
|
||||
}{
|
||||
{name: "user without ident server", test: "~test", want: true},
|
||||
{name: "user with ident server", test: "test", want: true},
|
||||
{name: "non-alphanumeric first index", test: "-test", want: false},
|
||||
{name: "non-alphanumeric first index", test: "[test]", want: false},
|
||||
{name: "numeric first index", test: "0test", want: true},
|
||||
{name: "blank", test: "", want: false},
|
||||
{name: "just tilde", test: "~", want: false},
|
||||
{name: "special chars", test: "test-----", want: true},
|
||||
{name: "special chars", test: "test-[]-", want: true},
|
||||
{name: "special chars, invalid after first index", test: "t!--", want: false},
|
||||
}
|
||||
|
||||
func FuzzValidUser(f *testing.F) {
|
||||
for _, tc := range testsValidUser {
|
||||
f.Add(tc.test)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
_ = IsValidUser(orig)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsValidUser(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{name: "user without ident server", args: args{name: "~test"}, want: true},
|
||||
{name: "user with ident server", args: args{name: "test"}, want: true},
|
||||
{name: "non-alphanumeric first index", args: args{name: "-test"}, want: false},
|
||||
{name: "non-alphanumeric first index", args: args{name: "[test]"}, want: false},
|
||||
{name: "numeric first index", args: args{name: "0test"}, want: true},
|
||||
{name: "blank", args: args{name: ""}, want: false},
|
||||
{name: "just tilde", args: args{name: "~"}, want: false},
|
||||
{name: "special chars", args: args{name: "test-----"}, want: true},
|
||||
{name: "special chars", args: args{name: "test-[]-"}, want: true},
|
||||
{name: "special chars, invalid after first index", args: args{name: "t!--"}, want: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := IsValidUser(tt.args.name); got != tt.want {
|
||||
t.Errorf("%s: IsValidUser(%q) = %v, want %v", tt.name, tt.args.name, got, tt.want)
|
||||
for _, tt := range testsValidUser {
|
||||
if got := IsValidUser(tt.test); got != tt.want {
|
||||
t.Errorf("%s: IsValidUser(%q) = %v, want %v", tt.name, tt.test, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestToRFC1459(t *testing.T) {
|
||||
cases := []struct {
|
||||
in string
|
||||
want string
|
||||
}{
|
||||
{"", ""},
|
||||
{"a", "a"},
|
||||
{"abcd", "abcd"},
|
||||
{"AbcD", "abcd"},
|
||||
{"!@#$%^&*()_+-=", "!@#$%~&*()_+-="},
|
||||
{"Abcd[]", "abcd{}"},
|
||||
var testsToRFC1459 = []struct {
|
||||
in string
|
||||
want string
|
||||
}{
|
||||
{"", ""},
|
||||
{"a", "a"},
|
||||
{"abcd", "abcd"},
|
||||
{"AbcD", "abcd"},
|
||||
{"!@#$%^&*()_+-=", "!@#$%~&*()_+-="},
|
||||
{"Abcd[]", "abcd{}"},
|
||||
}
|
||||
|
||||
func FuzzToRFC1459(f *testing.F) {
|
||||
for _, tc := range testsToRFC1459 {
|
||||
f.Add(tc.in)
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
f.Fuzz(func(t *testing.T, orig string) {
|
||||
got := ToRFC1459(orig)
|
||||
|
||||
if utf8.ValidString(orig) && !utf8.ValidString(got) {
|
||||
t.Errorf("produced invalid UTF-8 string %q", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestToRFC1459(t *testing.T) {
|
||||
for _, tt := range testsToRFC1459 {
|
||||
if got := ToRFC1459(tt.in); got != tt.want {
|
||||
t.Errorf("ToRFC1459() = %q, want %q", got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//func BenchmarkGlob(b *testing.B) {
|
||||
// for i := 0; i < b.N; i++ {
|
||||
// if !Glob("*quick*fox*dog", "The quick brown fox jumped over the lazy dog") {
|
||||
// b.Fatalf("should match")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return
|
||||
//}
|
||||
func BenchmarkGlob(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
if !Glob("*quick*fox*dog", "The quick brown fox jumped over the lazy dog") {
|
||||
b.Fatalf("should match")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGlobMatch(t *testing.T, subj, pattern string) {
|
||||
if !Glob(subj, pattern) {
|
||||
|
@ -310,27 +398,37 @@ func TestPatternWithoutGlobs(t *testing.T) {
|
|||
testGlobMatch(t, "test", "test")
|
||||
}
|
||||
|
||||
func TestGlob(t *testing.T) {
|
||||
cases := []string{
|
||||
"*test", // Leading.
|
||||
"this*", // Trailing.
|
||||
"this*test", // Middle.
|
||||
"*is *", // String in between two.
|
||||
"*is*a*", // Lots.
|
||||
"**test**", // Double glob characters.
|
||||
"**is**a***test*", // Varying number.
|
||||
"* *", // White space between.
|
||||
"*", // Lone.
|
||||
"**********", // Nothing but globs.
|
||||
"*Ѿ*", // Unicode.
|
||||
"*is a ϗѾ *", // Mixed ASCII/unicode.
|
||||
var testsGlob = []string{
|
||||
"*test", // Leading.
|
||||
"this*", // Trailing.
|
||||
"this*test", // Middle.
|
||||
"*is *", // String in between two.
|
||||
"*is*a*", // Lots.
|
||||
"**test**", // Double glob characters.
|
||||
"**is**a***test*", // Varying number.
|
||||
"* *", // White space between.
|
||||
"*", // Lone.
|
||||
"**********", // Nothing but globs.
|
||||
"*Ѿ*", // Unicode.
|
||||
"*is a ϗѾ *", // Mixed ASCII/unicode.
|
||||
}
|
||||
|
||||
func FuzzGlob(f *testing.F) {
|
||||
for _, tc := range testsGlob {
|
||||
f.Add(tc, tc)
|
||||
}
|
||||
|
||||
for _, pattern := range cases {
|
||||
f.Fuzz(func(t *testing.T, orig, orig2 string) {
|
||||
_ = Glob(orig, orig2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGlob(t *testing.T) {
|
||||
for _, pattern := range testsGlob {
|
||||
testGlobMatch(t, "this is a ϗѾ test", pattern)
|
||||
}
|
||||
|
||||
cases = []string{
|
||||
cases := []string{
|
||||
"test*", // Implicit substring match.
|
||||
"*is", // Partial match.
|
||||
"*no*", // Globs without a match between them.
|
||||
|
|
Loading…
Reference in New Issue