File: client_multiline_test.go

package info (click to toggle)
golang-github-jlaffaye-ftp 0.0~git20170707.0.a05056b-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, buster-backports
  • size: 132 kB
  • ctags: 137
  • sloc: sh: 14; makefile: 4
file content (107 lines) | stat: -rw-r--r-- 2,184 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package ftp

import (
	"net"
	"net/textproto"
	"reflect"
	"strings"
	"sync"
	"testing"
)

type ftpMock struct {
	listener net.Listener
	commands []string // list of received commands
	sync.WaitGroup
}

func newFtpMock(t *testing.T, addresss string) *ftpMock {
	var err error
	mock := &ftpMock{}
	mock.listener, err = net.Listen("tcp", addresss)
	if err != nil {
		t.Fatal(err)
	}

	go func() {
		// Listen for an incoming connection.
		conn, err := mock.listener.Accept()
		if err != nil {
			t.Fatal(err)
		}

		mock.Add(1)
		defer mock.Done()
		defer conn.Close()

		proto := textproto.NewConn(conn)
		proto.Writer.PrintfLine("220 FTP Server ready.")

		for {
			command, _ := proto.ReadLine()

			// Strip the arguments
			if i := strings.Index(command, " "); i > 0 {
				command = command[:i]
			}

			// Append to list of received commands
			mock.commands = append(mock.commands, command)

			// At least one command must have a multiline response
			switch command {
			case "FEAT":
				proto.Writer.PrintfLine("211-Features:\r\nFEAT\r\nPASV\r\nSIZE\r\n211 End")
			case "USER":
				proto.Writer.PrintfLine("331 Please send your password")
			case "PASS":
				proto.Writer.PrintfLine("230-Hey,\r\nWelcome to my FTP\r\n230 Access granted")
			case "TYPE":
				proto.Writer.PrintfLine("200 Type set ok")
			case "QUIT":
				proto.Writer.PrintfLine("221 Goodbye.")
				return
			default:
				t.Fatal("unknown command:", command)
			}
		}
	}()

	return mock
}

// Closes the listening socket
func (mock *ftpMock) Close() {
	mock.listener.Close()
}

// ftp.mozilla.org uses multiline 220 response
func TestMultiline(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	address := "localhost:2121"
	mock := newFtpMock(t, address)
	defer mock.Close()

	c, err := Dial(address)
	if err != nil {
		t.Fatal(err)
	}

	err = c.Login("anonymous", "anonymous")
	if err != nil {
		t.Fatal(err)
	}

	c.Quit()

	// Wait for the connection to close
	mock.Wait()

	expected := []string{"FEAT", "USER", "PASS", "TYPE", "QUIT"}
	if !reflect.DeepEqual(mock.commands, expected) {
		t.Fatal("unexpected sequence of commands:", mock.commands, "expected:", expected)
	}
}