From 946ad294cebe682fa8c82889973f056a8ed5bd85 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Sun, 27 Oct 2024 15:54:39 +0100 Subject: [PATCH] Add tests for Msg attachment handling Introduce new unit tests for verifying the `AttachReader` method and enhancing error handling in attachment functions. These tests cover scenarios for success, file permissions, and early file closure errors. --- msg_nowin_test.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++ msg_test.go | 67 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/msg_nowin_test.go b/msg_nowin_test.go index b0ef87b..e56e65e 100644 --- a/msg_nowin_test.go +++ b/msg_nowin_test.go @@ -8,12 +8,83 @@ package mail import ( + "bytes" "context" + "errors" "os" "testing" "time" ) +func TestMsg_AttachFile_unixOnly(t *testing.T) { + t.Run("AttachFile with fileFromFS fails on open", func(t *testing.T) { + tempfile, err := os.CreateTemp("", "attachfile-unable-to-open.*.txt") + if err != nil { + t.Fatalf("failed to create temp file: %s", err) + } + t.Cleanup(func() { + if err := os.Remove(tempfile.Name()); err != nil { + t.Errorf("failed to remove temp file: %s", err) + } + }) + if err = os.Chmod(tempfile.Name(), 0000); err != nil { + t.Fatalf("failed to chmod temp file to 0000: %s", err) + } + message := NewMsg() + if message == nil { + t.Fatal("message is nil") + } + message.AttachFile(tempfile.Name()) + attachments := message.GetAttachments() + if len(attachments) != 1 { + t.Fatalf("failed to get attachments, expected 1, got: %d", len(attachments)) + } + messageBuf := bytes.NewBuffer(nil) + _, err = attachments[0].Writer(messageBuf) + if err == nil { + t.Error("writer func expected to fail, but didn't") + } + if !errors.Is(err, os.ErrPermission) { + t.Errorf("expected error to be %s, got: %s", os.ErrPermission, err) + } + }) + t.Run("AttachFile with fileFromFS fails on copy", func(t *testing.T) { + tempfile, err := os.CreateTemp("", "attachfile-close-early.*.txt") + if err != nil { + t.Fatalf("failed to create temp file: %s", err) + } + t.Cleanup(func() { + if err := os.Remove(tempfile.Name()); err != nil { + t.Errorf("failed to remove temp file: %s", err) + } + }) + message := NewMsg() + if message == nil { + t.Fatal("message is nil") + } + message.AttachFile("testdata/attachment.txt") + attachments := message.GetAttachments() + if len(attachments) != 1 { + t.Fatalf("failed to get attachments, expected 1, got: %d", len(attachments)) + } + messageBuf, err := os.Open(tempfile.Name()) + if err != nil { + t.Fatalf("failed to open temp file: %s", err) + } + // We close early to cause an error during io.Copy + if err = messageBuf.Close(); err != nil { + t.Fatalf("failed to close temp file: %s", err) + } + _, err = attachments[0].Writer(messageBuf) + if err == nil { + t.Error("writer func expected to fail, but didn't") + } + if !errors.Is(err, os.ErrClosed) { + t.Errorf("expected error to be %s, got: %s", os.ErrClosed, err) + } + }) +} + // TestMsg_WriteToSendmailWithContext tests the WriteToSendmailWithContext() method of the Msg func TestMsg_WriteToSendmailWithContext(t *testing.T) { if os.Getenv("TEST_SENDMAIL") != "true" { diff --git a/msg_test.go b/msg_test.go index c940c84..09e0465 100644 --- a/msg_test.go +++ b/msg_test.go @@ -12,6 +12,7 @@ import ( ht "html/template" "io" "net" + "os" "reflect" "strings" "testing" @@ -4491,6 +4492,15 @@ func TestMsg_AttachFile(t *testing.T) { if attachments[0].Name != "attachment.txt" { t.Errorf("expected attachment name to be %s, got: %s", "attachment.txt", attachments[0].Name) } + messageBuf := bytes.NewBuffer(nil) + _, err := attachments[0].Writer(messageBuf) + if err != nil { + t.Errorf("writer func failed: %s", err) + } + got := strings.TrimSpace(messageBuf.String()) + if !strings.EqualFold(got, "This is a test attachment") { + t.Errorf("expected message body to be %s, got: %s", "This is a test attachment", got) + } }) t.Run("AttachFile with non-existant file", func(t *testing.T) { message := NewMsg() @@ -4508,6 +4518,63 @@ func TestMsg_AttachFile(t *testing.T) { }) } +func TestMsg_AttachReader(t *testing.T) { + t.Run("AttachReader with file", func(t *testing.T) { + message := NewMsg() + if message == nil { + t.Fatal("message is nil") + } + file, err := os.Open("testdata/attachment.txt") + if err != nil { + t.Fatalf("failed to open file: %s", err) + } + t.Cleanup(func() { + if err := file.Close(); err != nil { + t.Errorf("failed to close file: %s", err) + } + }) + if err := message.AttachReader("attachment.txt", file); err != nil { + t.Fatalf("failed to attach reader: %s", err) + } + attachments := message.GetAttachments() + if len(attachments) != 1 { + t.Fatalf("failed to retrieve attachments list") + } + if attachments[0] == nil { + t.Fatal("expected attachment to be not nil") + } + if attachments[0].Name != "attachment.txt" { + t.Errorf("expected attachment name to be %s, got: %s", "attachment.txt", attachments[0].Name) + } + messageBuf := bytes.NewBuffer(nil) + _, err = attachments[0].Writer(messageBuf) + if err != nil { + t.Errorf("writer func failed: %s", err) + } + got := strings.TrimSpace(messageBuf.String()) + if !strings.EqualFold(got, "This is a test attachment") { + t.Errorf("expected message body to be %s, got: %s", "This is a test attachment", got) + } + }) + /* + t.Run("AttachReader with non-existant file", func(t *testing.T) { + message := NewMsg() + if message == nil { + t.Fatal("message is nil") + } + message.AttachReader("testdata/non-existant-file.txt") + attachments := message.GetAttachments() + if len(attachments) != 0 { + t.Fatalf("failed to retrieve attachments list") + } + }) + t.Run("AttachReader with options", func(t *testing.T) { + t.Log("all options have already been tested in file_test.go") + }) + + */ +} + /* // TestNewMsgWithMiddleware tests WithMiddleware