mirror of
https://github.com/gissleh/irc.git
synced 2026-10-02 08:35:35 +00:00
Added test setup for the irc client with a simple mock server.
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
package irctest
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// An Interaction is a "simulated" server that will trigger the
|
||||
// client.
|
||||
type Interaction struct {
|
||||
wg sync.WaitGroup
|
||||
|
||||
Strict bool
|
||||
Lines []InteractionLine
|
||||
Log []string
|
||||
Failure *InteractionFailure
|
||||
}
|
||||
|
||||
// Listen listens for a client in a separate goroutine.
|
||||
func (interaction *Interaction) Listen() (addr string, err error) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
lines := make([]InteractionLine, len(interaction.Lines))
|
||||
copy(lines, interaction.Lines)
|
||||
|
||||
go func() {
|
||||
interaction.wg.Add(1)
|
||||
defer interaction.wg.Done()
|
||||
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
interaction.Failure = &InteractionFailure{
|
||||
Index: -1, NetErr: err,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
reader := bufio.NewReader(conn)
|
||||
|
||||
for i := 0; i < len(lines); i++ {
|
||||
line := lines[i]
|
||||
|
||||
switch line.Kind {
|
||||
case 'S':
|
||||
{
|
||||
_, err := conn.Write(append([]byte(line.Data), '\r', '\n'))
|
||||
if err != nil {
|
||||
interaction.Failure = &InteractionFailure{
|
||||
Index: i, NetErr: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
case 'C':
|
||||
{
|
||||
conn.SetReadDeadline(time.Now().Add(time.Second))
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
interaction.Failure = &InteractionFailure{
|
||||
Index: i, NetErr: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
input = strings.Replace(input, "\r", "", -1)
|
||||
input = strings.Replace(input, "\n", "", 1)
|
||||
|
||||
match := line.Data
|
||||
success := false
|
||||
|
||||
if strings.HasSuffix(match, "*") {
|
||||
success = strings.HasPrefix(input, match[:len(match)-1])
|
||||
} else {
|
||||
success = match == input
|
||||
}
|
||||
|
||||
interaction.Log = append(interaction.Log, input)
|
||||
|
||||
if !success {
|
||||
if !interaction.Strict {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
|
||||
interaction.Failure = &InteractionFailure{
|
||||
Index: i, Result: input,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return listener.Addr().String(), nil
|
||||
}
|
||||
|
||||
// Wait waits for the setup to be done. It's safe to check
|
||||
// Failure after that.
|
||||
func (interaction *Interaction) Wait() {
|
||||
interaction.wg.Wait()
|
||||
}
|
||||
|
||||
// InteractionFailure signifies a test failure.
|
||||
type InteractionFailure struct {
|
||||
Index int
|
||||
Result string
|
||||
NetErr error
|
||||
}
|
||||
|
||||
// InteractionLine is part of an interaction, whether it is a line
|
||||
// that is sent to a client or a line expected from a client.
|
||||
type InteractionLine struct {
|
||||
Kind byte
|
||||
Data string
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package irctest_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"git.aiterp.net/gisle/irc/internal/irctest"
|
||||
)
|
||||
|
||||
func TestInteraction(t *testing.T) {
|
||||
interaction := irctest.Interaction{
|
||||
Lines: []irctest.InteractionLine{
|
||||
{Kind: 'C', Data: "FIRST MESSAGE"},
|
||||
{Kind: 'S', Data: "SERVER MESSAGE"},
|
||||
{Kind: 'C', Data: "SECOND MESSAGE"},
|
||||
},
|
||||
}
|
||||
|
||||
addr, err := interaction.Listen()
|
||||
if err != nil {
|
||||
t.Fatal("Listen:", err)
|
||||
}
|
||||
|
||||
conn, err := net.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
t.Fatal("Dial:", err)
|
||||
}
|
||||
|
||||
_, err = conn.Write([]byte("FIRST MESSAGE\r\n"))
|
||||
if err != nil {
|
||||
t.Fatal("Write:", err)
|
||||
}
|
||||
|
||||
buffer := make([]byte, 64)
|
||||
n, err := conn.Read(buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Read:", err)
|
||||
}
|
||||
if string(buffer[:n]) != "SERVER MESSAGE\r\n" {
|
||||
t.Fatal("Read not correct:", string(buffer[:n]))
|
||||
}
|
||||
|
||||
_, err = conn.Write([]byte("SECOND MESSAGE\r\n"))
|
||||
if err != nil {
|
||||
t.Fatal("Write 2:", err)
|
||||
}
|
||||
|
||||
interaction.Wait()
|
||||
|
||||
if interaction.Failure != nil {
|
||||
t.Error("Index:", interaction.Failure.Index)
|
||||
t.Error("Result:", interaction.Failure.Result)
|
||||
t.Error("NetErr:", interaction.Failure.NetErr)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user