source: code/trunk/server_test.go@ 602

Last change on this file since 602 was 602, checked in by contact, 4 years ago

test: add upstream

File size: 4.2 KB
RevLine 
[600]1package soju
2
3import (
4 "net"
5 "testing"
6
7 "golang.org/x/crypto/bcrypt"
8 "gopkg.in/irc.v3"
9)
10
[602]11var testServerPrefix = &irc.Prefix{Name: "soju-test-server"}
12
[600]13const (
14 testUsername = "soju-test-user"
15 testPassword = testUsername
16)
17
[602]18func createTestDownstream(t *testing.T, srv *Server) ircConn {
[600]19 c1, c2 := net.Pipe()
[602]20 go srv.handle(newNetIRCConn(c1))
21 return newNetIRCConn(c2)
[600]22}
23
24func createTempDB(t *testing.T) Database {
25 db, err := OpenSqliteDB("sqlite3", ":memory:")
26 if err != nil {
27 t.Fatalf("failed to create temporary SQLite database: %v", err)
28 }
29 // :memory: will open a separate database for each new connection. Make
30 // sure the sql package only uses a single connection. An alternative
31 // solution is to use "file::memory:?cache=shared".
32 db.(*SqliteDB).db.SetMaxOpenConns(1)
33 return db
34}
35
[602]36func createTestUser(t *testing.T, db Database) *User {
[600]37 hashed, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost)
38 if err != nil {
39 t.Fatalf("failed to generate bcrypt hash: %v", err)
40 }
41
42 record := &User{Username: testUsername, Password: string(hashed)}
43 if err := db.StoreUser(record); err != nil {
44 t.Fatalf("failed to store test user: %v", err)
45 }
46
[602]47 return record
[600]48}
49
[602]50type testUpstream struct {
51 net.Listener
52 Accept chan ircConn
53}
54
55func createTestUpstream(t *testing.T, db Database, user *User) (*Network, *testUpstream) {
56 ln, err := net.Listen("tcp", "localhost:0")
57 if err != nil {
58 t.Fatalf("failed to create TCP listener: %v", err)
59 }
60
61 tu := &testUpstream{
62 Listener: ln,
63 Accept: make(chan ircConn),
64 }
65
66 go func() {
67 defer close(tu.Accept)
68
69 for {
70 c, err := ln.Accept()
71 if isErrClosed(err) {
72 break
73 } else if err != nil {
74 t.Fatalf("failed accepting connection: %v", err)
75 }
76 tu.Accept <- newNetIRCConn(c)
77 }
78 }()
79
80 network := &Network{
81 Name: "testnet",
82 Addr: "irc+insecure://" + ln.Addr().String(),
83 Nick: user.Username,
84 Enabled: true,
85 }
86 if err := db.StoreNetwork(user.ID, network); err != nil {
87 t.Fatalf("failed to store test network: %v", err)
88 }
89
90 return network, tu
91}
92
[600]93func expectMessage(t *testing.T, c ircConn, cmd string) *irc.Message {
94 msg, err := c.ReadMessage()
95 if err != nil {
96 t.Fatalf("failed to read IRC message (want %q): %v", cmd, err)
97 }
98 if msg.Command != cmd {
99 t.Fatalf("invalid message received: want %q, got: %v", cmd, msg)
100 }
101 return msg
102}
103
[602]104func registerDownstreamConn(t *testing.T, c ircConn, network *Network) {
[600]105 c.WriteMessage(&irc.Message{
106 Command: "PASS",
107 Params: []string{testPassword},
108 })
109 c.WriteMessage(&irc.Message{
110 Command: "NICK",
111 Params: []string{testUsername},
112 })
113 c.WriteMessage(&irc.Message{
114 Command: "USER",
[602]115 Params: []string{testUsername + "/" + network.Name, "0", "*", testUsername},
[600]116 })
117
118 expectMessage(t, c, irc.RPL_WELCOME)
119}
120
[602]121func registerUpstreamConn(t *testing.T, c ircConn) {
122 msg := expectMessage(t, c, "CAP")
123 if msg.Params[0] != "LS" {
124 t.Fatalf("invalid CAP LS: got: %v", msg)
125 }
126 msg = expectMessage(t, c, "NICK")
127 nick := msg.Params[0]
128 if nick != testUsername {
129 t.Fatalf("invalid NICK: want %q, got: %v", testUsername, msg)
130 }
131 expectMessage(t, c, "USER")
132
133 c.WriteMessage(&irc.Message{
134 Prefix: testServerPrefix,
135 Command: irc.RPL_WELCOME,
136 Params: []string{nick, "Welcome!"},
137 })
138 c.WriteMessage(&irc.Message{
139 Prefix: testServerPrefix,
140 Command: irc.RPL_YOURHOST,
141 Params: []string{nick, "Your host is soju-test-server"},
142 })
143 c.WriteMessage(&irc.Message{
144 Prefix: testServerPrefix,
145 Command: irc.RPL_CREATED,
146 Params: []string{nick, "Who cares when the server was created?"},
147 })
148 c.WriteMessage(&irc.Message{
149 Prefix: testServerPrefix,
150 Command: irc.RPL_MYINFO,
151 Params: []string{nick, testServerPrefix.Name, "soju", "aiwroO", "OovaimnqpsrtklbeI"},
152 })
153 c.WriteMessage(&irc.Message{
154 Prefix: testServerPrefix,
155 Command: irc.ERR_NOMOTD,
156 Params: []string{nick, "No MOTD"},
157 })
158}
159
[600]160func TestServer(t *testing.T) {
[602]161 db := createTempDB(t)
162 user := createTestUser(t, db)
163 network, upstream := createTestUpstream(t, db, user)
164 defer upstream.Close()
165
166 srv := NewServer(db)
[600]167 if err := srv.Start(); err != nil {
168 t.Fatalf("failed to start server: %v", err)
169 }
170 defer srv.Shutdown()
171
[602]172 uc := <-upstream.Accept
173 defer uc.Close()
174 registerUpstreamConn(t, uc)
[600]175
[602]176 dc := createTestDownstream(t, srv)
177 defer dc.Close()
178
179 registerDownstreamConn(t, dc, network)
[600]180}
Note: See TracBrowser for help on using the repository browser.