From c6d7a0bff97f4239873addab53194dbc10d99071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fan=20Can=20Bak=C4=B1r?= Date: Tue, 30 Jul 2024 15:12:59 +0300 Subject: [PATCH 1/2] introduce safewriter --- io/io.go | 26 ++++++++++++++++++++++++++ io/io_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 io/io.go create mode 100644 io/io_test.go diff --git a/io/io.go b/io/io.go new file mode 100644 index 0000000..9aef945 --- /dev/null +++ b/io/io.go @@ -0,0 +1,26 @@ +package ioutil + +import ( + "io" + "sync" +) + +type SafeWriter struct { + writer io.Writer + mutex sync.Mutex +} + +func NewSafeWriter(writer io.Writer) *SafeWriter { + return &SafeWriter{ + writer: writer, + } +} + +func (sw *SafeWriter) Write(p []byte) (n int, err error) { + sw.mutex.Lock() + defer sw.mutex.Unlock() + if sw.writer == nil { + return 0, io.ErrClosedPipe + } + return sw.writer.Write(p) +} diff --git a/io/io_test.go b/io/io_test.go new file mode 100644 index 0000000..c34135f --- /dev/null +++ b/io/io_test.go @@ -0,0 +1,28 @@ +package ioutil + +import ( + "strings" + "testing" +) + +func TestSafeWriter(t *testing.T) { + t.Run("success", func(t *testing.T) { + var sb strings.Builder + sw := NewSafeWriter(&sb) + _, err := sw.Write([]byte("test")) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if sb.String() != "test" { + t.Fatalf("expected 'test', got '%s'", sb.String()) + } + }) + + t.Run("failure", func(t *testing.T) { + sw := NewSafeWriter(nil) + _, err := sw.Write([]byte("test")) + if err == nil { + t.Fatalf("expected error, got nil") + } + }) +} From 5fba4efc1ed6913c1d50a5d8e65a126379134bdf Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 30 Jul 2024 15:18:44 +0200 Subject: [PATCH 2/2] moving error to new --- io/io.go | 20 ++++++++++++++++---- io/io_test.go | 23 ++++++++++------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/io/io.go b/io/io.go index 9aef945..4ea74ad 100644 --- a/io/io.go +++ b/io/io.go @@ -1,24 +1,36 @@ package ioutil import ( + "errors" "io" "sync" ) +// SafeWriter is a thread-safe wrapper for io.Writer type SafeWriter struct { - writer io.Writer - mutex sync.Mutex + writer io.Writer // The underlying writer + mutex *sync.Mutex // Mutex for ensuring thread-safety } -func NewSafeWriter(writer io.Writer) *SafeWriter { - return &SafeWriter{ +// NewSafeWriter creates and returns a new SafeWriter +func NewSafeWriter(writer io.Writer) (*SafeWriter, error) { + // Check if the provided writer is nil + if writer == nil { + return nil, errors.New("writer is nil") + } + + safeWriter := &SafeWriter{ writer: writer, + mutex: &sync.Mutex{}, } + return safeWriter, nil } +// Write implements the io.Writer interface in a thread-safe manner func (sw *SafeWriter) Write(p []byte) (n int, err error) { sw.mutex.Lock() defer sw.mutex.Unlock() + if sw.writer == nil { return 0, io.ErrClosedPipe } diff --git a/io/io_test.go b/io/io_test.go index c34135f..a40d591 100644 --- a/io/io_test.go +++ b/io/io_test.go @@ -3,26 +3,23 @@ package ioutil import ( "strings" "testing" + + "github.com/stretchr/testify/require" ) func TestSafeWriter(t *testing.T) { t.Run("success", func(t *testing.T) { var sb strings.Builder - sw := NewSafeWriter(&sb) - _, err := sw.Write([]byte("test")) - if err != nil { - t.Fatalf("expected no error, got %v", err) - } - if sb.String() != "test" { - t.Fatalf("expected 'test', got '%s'", sb.String()) - } + sw, err := NewSafeWriter(&sb) + require.Nil(t, err) + _, err = sw.Write([]byte("test")) + require.Nil(t, err) + require.Equal(t, "test", sb.String()) }) t.Run("failure", func(t *testing.T) { - sw := NewSafeWriter(nil) - _, err := sw.Write([]byte("test")) - if err == nil { - t.Fatalf("expected error, got nil") - } + sw, err := NewSafeWriter(nil) + require.NotNil(t, err) + require.Nil(t, sw) }) }