From ffc086e75f6a9d8b4873a3c882fd5b301cd69914 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 8 Sep 2022 11:47:11 +0200 Subject: [PATCH 1/5] #42: Better test coverage for b64linebreaker.go. Also we return errors now --- b64linebreaker.go | 18 +++++++++++++----- b64linebreaker_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/b64linebreaker.go b/b64linebreaker.go index ff99696..ecad47d 100644 --- a/b64linebreaker.go +++ b/b64linebreaker.go @@ -4,7 +4,12 @@ package mail -import "io" +import ( + "fmt" + "io" +) + +const ErrNoOutWriter = "no io.Writer set for Base64LineBreaker" // Base64LineBreaker is a io.WriteCloser that writes Base64 encoded data streams // with line breaks at a given line length @@ -19,6 +24,9 @@ var nl = []byte(SingleNewLine) // Write writes the data stream and inserts a SingleNewLine when the maximum // line length is reached func (l *Base64LineBreaker) Write(b []byte) (n int, err error) { + if l.out == nil { + return 0, fmt.Errorf(ErrNoOutWriter) + } if l.used+len(b) < MaxBodyLength { copy(l.line[l.used:], b) l.used += len(b) @@ -27,19 +35,19 @@ func (l *Base64LineBreaker) Write(b []byte) (n int, err error) { n, err = l.out.Write(l.line[0:l.used]) if err != nil { - return + return 0, err } excess := MaxBodyLength - l.used l.used = 0 n, err = l.out.Write(b[0:excess]) if err != nil { - return + return 0, err } n, err = l.out.Write(nl) if err != nil { - return + return 0, err } return l.Write(b[excess:]) @@ -51,7 +59,7 @@ func (l *Base64LineBreaker) Close() (err error) { if l.used > 0 { _, err = l.out.Write(l.line[0:l.used]) if err != nil { - return + return err } _, err = l.out.Write(nl) } diff --git a/b64linebreaker_test.go b/b64linebreaker_test.go index 05c61c3..f2b3891 100644 --- a/b64linebreaker_test.go +++ b/b64linebreaker_test.go @@ -7,6 +7,7 @@ package mail import ( "bytes" "encoding/base64" + "fmt" "io" "os" "testing" @@ -410,6 +411,31 @@ func TestBase64LineBreaker(t *testing.T) { } } +// TestBase64LineBreakerFailures tests the cases in which the Base64LineBreaker would fail +func TestBase64LineBreakerFailures(t *testing.T) { + stt := []byte("short") + ltt := []byte(logoB64) + + // No output writer defined + lb := Base64LineBreaker{} + if _, err := lb.Write(stt); err == nil { + t.Errorf("writing to Base64LineBreaker with no output io.Writer was supposed to failed, but didn't") + } + if err := lb.Close(); err != nil { + t.Errorf("failed to close Base64LineBreaker: %s", err) + } + + // Closed output writer + wbuf := errorWriter{} + fb := Base64LineBreaker{out: wbuf} + if _, err := fb.Write(ltt); err == nil { + t.Errorf("writing to Base64LineBreaker with errorWriter was supposed to failed, but didn't") + } + if err := fb.Close(); err != nil { + t.Errorf("failed to close Base64LineBreaker: %s", err) + } +} + // removeNewLines removes any newline characters from the given data func removeNewLines(data []byte) []byte { result := make([]byte, len(data)) @@ -425,3 +451,13 @@ func removeNewLines(data []byte) []byte { return result[0:n] } + +type errorWriter struct{} + +func (e errorWriter) Write([]byte) (int, error) { + return 0, fmt.Errorf("supposed to always fail") +} + +func (e errorWriter) Close() error { + return fmt.Errorf("supposed to always fail") +} From 333c3970e7cb5ab6addff8f3cae7f39194faa286 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 8 Sep 2022 15:08:03 +0200 Subject: [PATCH 2/5] #42: Add test for Msg.EnvelopeFromFormat --- msg_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/msg_test.go b/msg_test.go index ed70a73..14178e8 100644 --- a/msg_test.go +++ b/msg_test.go @@ -617,7 +617,7 @@ func TestMsg_SetMessageIDWithValue(t *testing.T) { } } -// TestMsg_FromFormat tests the FromFormat() method for the Msg object +// TestMsg_FromFormat tests the FromFormat and EnvelopeFrom methods for the Msg object func TestMsg_FromFormat(t *testing.T) { tests := []struct { tname string @@ -641,6 +641,10 @@ func TestMsg_FromFormat(t *testing.T) { t.Errorf("failed to FromFormat(): %s", err) return } + if err := m.EnvelopeFromFormat(tt.name, tt.addr); err != nil && !tt.fail { + t.Errorf("failed to EnvelopeFromFormat(): %s", err) + return + } var fa *mail.Address f, ok := m.addrHeader[HeaderFrom] From 6d22a34548b4a4436807448e6612a0daa0029710 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 8 Sep 2022 15:08:17 +0200 Subject: [PATCH 3/5] #42: Add test for Msg.WriteToSendmail --- msg_nowin_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/msg_nowin_test.go b/msg_nowin_test.go index 965b6f3..9eec2eb 100644 --- a/msg_nowin_test.go +++ b/msg_nowin_test.go @@ -9,6 +9,7 @@ package mail import ( "context" + "os" "testing" "time" ) @@ -38,3 +39,19 @@ func TestMsg_WriteToSendmailWithContext(t *testing.T) { }) } } + +// TestMsg_WriteToSendmail will test the output to the local sendmail command +func TestMsg_WriteToSendmail(t *testing.T) { + _, err := os.Stat(SendmailPath) + if err != nil { + t.Skipf("local sendmail command not found in expected path. Skipping") + } + + m := NewMsg() + _ = m.From("Toni Tester ") + _ = m.To(TestRcpt) + m.SetBodyString(TypeTextPlain, "This is a test") + if err := m.WriteToSendmail(); err != nil { + t.Errorf("WriteToSendmail failed: %s", err) + } +} From 3eb4bc9c5294fe1d9caad6da879999d5722d24ba Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 8 Sep 2022 15:40:42 +0200 Subject: [PATCH 4/5] #42: Reverting return values in b64linebreaker.go since return values were defined in signature --- b64linebreaker.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/b64linebreaker.go b/b64linebreaker.go index ecad47d..5a4b2bc 100644 --- a/b64linebreaker.go +++ b/b64linebreaker.go @@ -5,12 +5,9 @@ package mail import ( - "fmt" "io" ) -const ErrNoOutWriter = "no io.Writer set for Base64LineBreaker" - // Base64LineBreaker is a io.WriteCloser that writes Base64 encoded data streams // with line breaks at a given line length type Base64LineBreaker struct { @@ -25,7 +22,7 @@ var nl = []byte(SingleNewLine) // line length is reached func (l *Base64LineBreaker) Write(b []byte) (n int, err error) { if l.out == nil { - return 0, fmt.Errorf(ErrNoOutWriter) + return } if l.used+len(b) < MaxBodyLength { copy(l.line[l.used:], b) @@ -35,19 +32,19 @@ func (l *Base64LineBreaker) Write(b []byte) (n int, err error) { n, err = l.out.Write(l.line[0:l.used]) if err != nil { - return 0, err + return } excess := MaxBodyLength - l.used l.used = 0 n, err = l.out.Write(b[0:excess]) if err != nil { - return 0, err + return } n, err = l.out.Write(nl) if err != nil { - return 0, err + return } return l.Write(b[excess:]) @@ -59,7 +56,7 @@ func (l *Base64LineBreaker) Close() (err error) { if l.used > 0 { _, err = l.out.Write(l.line[0:l.used]) if err != nil { - return err + return } _, err = l.out.Write(nl) } From 910248d9996c0f29f04fc6bf3d59f182a03968ba Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Thu, 8 Sep 2022 15:43:14 +0200 Subject: [PATCH 5/5] #42: Return error in b64linebreaker.go when no out is set --- b64linebreaker.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/b64linebreaker.go b/b64linebreaker.go index 5a4b2bc..f471fe5 100644 --- a/b64linebreaker.go +++ b/b64linebreaker.go @@ -5,9 +5,13 @@ package mail import ( + "fmt" "io" ) +// ErrNoOutWriter is an error message that should be used if a Base64LineBreaker has no out io.Writer set +const ErrNoOutWriter = "no io.Writer set for Base64LineBreaker" + // Base64LineBreaker is a io.WriteCloser that writes Base64 encoded data streams // with line breaks at a given line length type Base64LineBreaker struct { @@ -22,6 +26,7 @@ var nl = []byte(SingleNewLine) // line length is reached func (l *Base64LineBreaker) Write(b []byte) (n int, err error) { if l.out == nil { + err = fmt.Errorf(ErrNoOutWriter) return } if l.used+len(b) < MaxBodyLength {