[600] | 1 | package soju
|
---|
| 2 |
|
---|
| 3 | import (
|
---|
| 4 | "net"
|
---|
| 5 | "testing"
|
---|
| 6 |
|
---|
| 7 | "golang.org/x/crypto/bcrypt"
|
---|
| 8 | "gopkg.in/irc.v3"
|
---|
| 9 | )
|
---|
| 10 |
|
---|
| 11 | const (
|
---|
| 12 | testUsername = "soju-test-user"
|
---|
| 13 | testPassword = testUsername
|
---|
| 14 | )
|
---|
| 15 |
|
---|
| 16 | func ircPipe() (ircConn, ircConn) {
|
---|
| 17 | c1, c2 := net.Pipe()
|
---|
| 18 | return newNetIRCConn(c1), newNetIRCConn(c2)
|
---|
| 19 | }
|
---|
| 20 |
|
---|
| 21 | func createTempDB(t *testing.T) Database {
|
---|
| 22 | db, err := OpenSqliteDB("sqlite3", ":memory:")
|
---|
| 23 | if err != nil {
|
---|
| 24 | t.Fatalf("failed to create temporary SQLite database: %v", err)
|
---|
| 25 | }
|
---|
| 26 | // :memory: will open a separate database for each new connection. Make
|
---|
| 27 | // sure the sql package only uses a single connection. An alternative
|
---|
| 28 | // solution is to use "file::memory:?cache=shared".
|
---|
| 29 | db.(*SqliteDB).db.SetMaxOpenConns(1)
|
---|
| 30 | return db
|
---|
| 31 | }
|
---|
| 32 |
|
---|
| 33 | func createTestUser(t *testing.T) *Server {
|
---|
| 34 | db := createTempDB(t)
|
---|
| 35 |
|
---|
| 36 | hashed, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost)
|
---|
| 37 | if err != nil {
|
---|
| 38 | t.Fatalf("failed to generate bcrypt hash: %v", err)
|
---|
| 39 | }
|
---|
| 40 |
|
---|
| 41 | record := &User{Username: testUsername, Password: string(hashed)}
|
---|
| 42 | if err := db.StoreUser(record); err != nil {
|
---|
| 43 | t.Fatalf("failed to store test user: %v", err)
|
---|
| 44 | }
|
---|
| 45 |
|
---|
| 46 | return NewServer(db)
|
---|
| 47 | }
|
---|
| 48 |
|
---|
| 49 | func expectMessage(t *testing.T, c ircConn, cmd string) *irc.Message {
|
---|
| 50 | msg, err := c.ReadMessage()
|
---|
| 51 | if err != nil {
|
---|
| 52 | t.Fatalf("failed to read IRC message (want %q): %v", cmd, err)
|
---|
| 53 | }
|
---|
| 54 | if msg.Command != cmd {
|
---|
| 55 | t.Fatalf("invalid message received: want %q, got: %v", cmd, msg)
|
---|
| 56 | }
|
---|
| 57 | return msg
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | func authTestUser(t *testing.T, c ircConn) {
|
---|
| 61 | c.WriteMessage(&irc.Message{
|
---|
| 62 | Command: "PASS",
|
---|
| 63 | Params: []string{testPassword},
|
---|
| 64 | })
|
---|
| 65 | c.WriteMessage(&irc.Message{
|
---|
| 66 | Command: "NICK",
|
---|
| 67 | Params: []string{testUsername},
|
---|
| 68 | })
|
---|
| 69 | c.WriteMessage(&irc.Message{
|
---|
| 70 | Command: "USER",
|
---|
| 71 | Params: []string{testUsername, "0", "*", testUsername},
|
---|
| 72 | })
|
---|
| 73 |
|
---|
| 74 | expectMessage(t, c, irc.RPL_WELCOME)
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | func TestServer(t *testing.T) {
|
---|
| 78 | srv := createTestUser(t)
|
---|
| 79 | if err := srv.Start(); err != nil {
|
---|
| 80 | t.Fatalf("failed to start server: %v", err)
|
---|
| 81 | }
|
---|
| 82 | defer srv.Shutdown()
|
---|
| 83 |
|
---|
| 84 | c, srvConn := ircPipe()
|
---|
| 85 | defer c.Close()
|
---|
| 86 | go srv.handle(srvConn)
|
---|
| 87 |
|
---|
| 88 | authTestUser(t, c)
|
---|
| 89 | }
|
---|