File: dotreader_test.go

package info (click to toggle)
chasquid 1.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,636 kB
  • sloc: sh: 1,262; python: 325; makefile: 78
file content (89 lines) | stat: -rw-r--r-- 2,505 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
package smtpsrv

import (
	"bufio"
	"bytes"
	"io"
	"strings"
	"testing"
)

func TestReadUntilDot(t *testing.T) {
	cases := []struct {
		input   string
		max     int64
		want    string
		wantErr error
	}{
		// EOF before any input -> unexpected EOF.
		{"", 0, "", io.ErrUnexpectedEOF},
		{"", 1, "", io.ErrUnexpectedEOF},

		// EOF after exceeding max -> unexpected EOF.
		{"abcdef", 2, "ab", io.ErrUnexpectedEOF},

		// \n at the beginning of the buffer are just as invalid, and the
		// error takes precedence over the unexpected EOF.
		{"\n", 0, "", errInvalidLineEnding},
		{"\n", 1, "", errInvalidLineEnding},
		{"\n", 2, "", errInvalidLineEnding},
		{"\n\r\n.\r\n", 10, "", errInvalidLineEnding},

		// \r and then EOF -> unexpected EOF, because we never had a chance to
		// assess if the line ending is valid or not.
		{"\r", 2, "", io.ErrUnexpectedEOF},

		// Lonely \r -> invalid line ending.
		{"abc\rdef", 10, "abc", errInvalidLineEnding},
		{"abc\r\rdef", 10, "abc", errInvalidLineEnding},

		// Lonely \n -> invalid line ending.
		{"abc\ndef", 10, "abc", errInvalidLineEnding},

		// Various valid cases.
		{"abc\r\n.\r\n", 10, "abc\n", nil},
		{"\r\n.\r\n", 10, "\n", nil},

		// Start with the final dot - the smallest "message" (empty).
		{".\r\n", 10, "", nil},

		// Max bytes reached -> message too large.
		{"abc\r\n.\r\n", 5, "abc\n", errMessageTooLarge},
		{"abcdefg\r\n.\r\n", 5, "abcde", errMessageTooLarge},
		{"ab\r\ncdefg\r\n.\r\n", 5, "ab\ncd", errMessageTooLarge},

		// Dot-stuffing.
		// https://www.rfc-editor.org/rfc/rfc5321#section-4.5.2
		{"abc\r\n.def\r\n.\r\n", 20, "abc\ndef\n", nil},
		{"abc\r\n..def\r\n.\r\n", 20, "abc\n.def\n", nil},
		{"abc\r\n..\r\n.\r\n", 20, "abc\n.\n", nil},
		{".x\r\n.\r\n", 20, "x\n", nil},
		{"..\r\n.\r\n", 20, ".\n", nil},
	}

	for i, c := range cases {
		r := bufio.NewReader(strings.NewReader(c.input))
		got, err := readUntilDot(r, c.max)
		if err != c.wantErr {
			t.Errorf("case %d %q: got error %v, want %v", i, c.input, err, c.wantErr)
		}
		if !bytes.Equal(got, []byte(c.want)) {
			t.Errorf("case %d %q: got %q, want %q", i, c.input, got, c.want)
		}
	}
}

type badBuffer bytes.Buffer

func (b *badBuffer) Read(p []byte) (int, error) {
	// Return an arbitrary non-EOF error for testing.
	return 0, io.ErrNoProgress
}

func TestReadUntilDotReadError(t *testing.T) {
	r := bufio.NewReader(&badBuffer{})
	_, err := readUntilDot(r, 10)
	if err != io.ErrNoProgress {
		t.Errorf("got error %v, want %v", err, io.ErrNoProgress)
	}
}