-
-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #68 from wneessen/fix-io-reader
New Reader type
- Loading branch information
Showing
4 changed files
with
194 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// SPDX-FileCopyrightText: 2022 Winni Neessen <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
package mail | ||
|
||
import ( | ||
"io" | ||
) | ||
|
||
// Reader is a type that implements the io.Reader interface for a Msg | ||
type Reader struct { | ||
buf []byte // contents are the bytes buf[off : len(buf)] | ||
off int // read at &buf[off], write at &buf[len(buf)] | ||
err error // initalization error | ||
} | ||
|
||
// Error returns an error if the Reader err field is not nil | ||
func (r *Reader) Error() error { | ||
return r.err | ||
} | ||
|
||
// Read reads the length of p of the Msg buffer to satisfy the io.Reader interface | ||
func (r *Reader) Read(p []byte) (n int, err error) { | ||
if r.err != nil { | ||
return 0, r.err | ||
} | ||
if r.empty() { | ||
r.Reset() | ||
if len(p) == 0 { | ||
return 0, nil | ||
} | ||
return 0, io.EOF | ||
} | ||
n = copy(p, r.buf[r.off:]) | ||
r.off += n | ||
return n, err | ||
} | ||
|
||
// Reset resets the Reader buffer to be empty, but it retains the underlying storage | ||
// for use by future writes. | ||
func (r *Reader) Reset() { | ||
r.buf = r.buf[:0] | ||
r.off = 0 | ||
} | ||
|
||
// empty reports whether the unread portion of the Reader buffer is empty. | ||
func (r *Reader) empty() bool { return len(r.buf) <= r.off } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// SPDX-FileCopyrightText: 2022 Winni Neessen <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
package mail | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
// TestReader_Read tests the Reader.Read method that implements the io.Reader interface | ||
func TestReader_Read(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
plen int | ||
}{ | ||
{"P length is bigger than the mail", 3200000}, | ||
{"P length is smaller than the mail", 128}, | ||
} | ||
|
||
m := NewMsg() | ||
m.SetBodyString(TypeTextPlain, "TEST123") | ||
wbuf := bytes.Buffer{} | ||
_, err := m.Write(&wbuf) | ||
if err != nil { | ||
t.Errorf("failed to write message into temporary buffer: %s", err) | ||
} | ||
elen := wbuf.Len() | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
p := make([]byte, tt.plen) | ||
mr := m.NewReader() | ||
n, err := mr.Read(p) | ||
if err != nil { | ||
t.Errorf("failed to Read(): %s", err) | ||
} | ||
if n == 0 { | ||
t.Errorf("failed to Read() - received 0 bytes of data") | ||
} | ||
if tt.plen >= elen && n != elen { | ||
t.Errorf("failed to Read() - not all data received. Expected: %d, got: %d", elen, n) | ||
} | ||
if tt.plen < elen && n != tt.plen { | ||
t.Errorf("failed to Read() - full length of p wasn't filled with data. Expected: %d, got: %d", | ||
tt.plen, n) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
// TestReader_Read_error tests the Reader.Read method with an intentional error | ||
func TestReader_Read_error(t *testing.T) { | ||
r := Reader{err: fmt.Errorf("FAILED")} | ||
var p []byte | ||
_, err := r.Read(p) | ||
if err == nil { | ||
t.Errorf("Reader was supposed to fail, but didn't") | ||
} | ||
} | ||
|
||
// TestReader_Read_empty tests the Reader.Read method with an empty buffer | ||
func TestReader_Read_empty(t *testing.T) { | ||
r := Reader{buf: []byte{}} | ||
var p []byte | ||
_, err := r.Read(p) | ||
if err != nil { | ||
t.Errorf("Reader failed: %s", err) | ||
} | ||
} |