Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,232 @@
|
||||
import io
|
||||
import rand
|
||||
|
||||
fn small_amount() int {
|
||||
return int(rand.u8()) + 1
|
||||
}
|
||||
|
||||
struct ArrayWriter {
|
||||
pub mut:
|
||||
result []u8
|
||||
}
|
||||
|
||||
// implement io.Writer
|
||||
fn (mut aw ArrayWriter) write(buf []u8) !int {
|
||||
len := buf.len
|
||||
mut res := 0
|
||||
for i := 0; i < len; i++ {
|
||||
aw.result << buf[i]
|
||||
res++
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
struct ChunkedArrayWriter {
|
||||
chunk int
|
||||
pub mut:
|
||||
result []u8
|
||||
}
|
||||
|
||||
fn (mut cw ChunkedArrayWriter) write(buf []u8) !int {
|
||||
if buf.len == 0 {
|
||||
return 0
|
||||
}
|
||||
n := if buf.len < cw.chunk { buf.len } else { cw.chunk }
|
||||
for i := 0; i < n; i++ {
|
||||
cw.result << buf[i]
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
struct FailOnceChunkedWriter {
|
||||
chunk int
|
||||
pub mut:
|
||||
result []u8
|
||||
mut:
|
||||
writes int
|
||||
}
|
||||
|
||||
fn (mut fw FailOnceChunkedWriter) write(buf []u8) !int {
|
||||
if fw.writes == 1 {
|
||||
fw.writes++
|
||||
return error('forced write failure')
|
||||
}
|
||||
fw.writes++
|
||||
n := if buf.len < fw.chunk { buf.len } else { fw.chunk }
|
||||
for i := 0; i < n; i++ {
|
||||
fw.result << buf[i]
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
struct ZeroProgressWriter {}
|
||||
|
||||
fn (mut w ZeroProgressWriter) write(buf []u8) !int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// write less than max bytes, returns number of bytes written
|
||||
// data is written in chunks.
|
||||
fn write_random_data(mut aw ArrayWriter, mut bw io.BufferedWriter, max int) !int {
|
||||
less_than_max := max - 255 // guarantee 1 full u8 less than max
|
||||
mut total := 0
|
||||
for total < less_than_max {
|
||||
r := rand.u8()
|
||||
d := rand.bytes(r)!
|
||||
w := bw.write(d)!
|
||||
total += w
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
fn test_flush() {
|
||||
mut aw := ArrayWriter{}
|
||||
max := 65536
|
||||
mut bw := io.new_buffered_writer(writer: &aw, cap: max)!
|
||||
|
||||
// write less data than buffer capacity, the underlying writer should receive no data.
|
||||
written := write_random_data(mut aw, mut bw, 65536)!
|
||||
assert written == bw.buffered()
|
||||
assert aw.result.len == 0
|
||||
|
||||
bw.flush()!
|
||||
assert aw.result.len == written
|
||||
assert bw.buffered() == 0
|
||||
assert bw.available() == max
|
||||
}
|
||||
|
||||
fn test_write() {
|
||||
mut aw := ArrayWriter{}
|
||||
max := 65536
|
||||
mut bw := io.new_buffered_writer(writer: &aw, cap: max)!
|
||||
|
||||
// write less data than buffer capacity, the underlying writer should receive no data.
|
||||
written := write_random_data(mut aw, mut bw, 65536)!
|
||||
|
||||
// now exceed buffer capacity by a little
|
||||
little := small_amount()
|
||||
excess := bw.available() + little
|
||||
excess_data := rand.bytes(excess)!
|
||||
w := bw.write(excess_data)!
|
||||
assert bw.buffered() == little
|
||||
assert bw.available() == max - little
|
||||
assert aw.result.len == max
|
||||
}
|
||||
|
||||
fn test_write_big() {
|
||||
mut aw := ArrayWriter{}
|
||||
max := 65536
|
||||
mut bw := io.new_buffered_writer(writer: &aw, cap: max)!
|
||||
|
||||
more_than_max := max + small_amount()
|
||||
big_source := rand.bytes(more_than_max)!
|
||||
w := bw.write(big_source)!
|
||||
assert w == more_than_max
|
||||
assert bw.buffered() == 0
|
||||
assert bw.available() == max
|
||||
assert aw.result.len == more_than_max
|
||||
}
|
||||
|
||||
// create_data returns an array with `n` elements plus `\n` as last character.
|
||||
fn create_data(n int) []u8 {
|
||||
mut res := []u8{}
|
||||
for i := 0; i < n; i++ {
|
||||
res << `X`
|
||||
}
|
||||
res << `\n`
|
||||
return res
|
||||
}
|
||||
|
||||
fn test_simple_write() {
|
||||
mut aw := ArrayWriter{}
|
||||
mut bw := io.new_buffered_writer(writer: &aw, cap: 10)!
|
||||
mut data := create_data(6)
|
||||
w1 := bw.write(data)!
|
||||
|
||||
// add data to buffer, less than cap
|
||||
// data is written to buffer, not to underlying writer.
|
||||
assert w1 == 7 // 6*x + \n
|
||||
assert bw.buffered() == 7
|
||||
assert aw.result.len == 0
|
||||
|
||||
// add more data, exceed cap
|
||||
// data is flushed to underlying writer when buffer is full, then more data is written to buffer.
|
||||
w2 := bw.write(data)!
|
||||
assert w2 == 7
|
||||
assert bw.buffered() == 4
|
||||
assert aw.result.len == 10
|
||||
|
||||
// exceed cap immediately
|
||||
// all data is written without buffering
|
||||
aw.result = []u8{}
|
||||
data = create_data(33)
|
||||
bw.reset()
|
||||
w3 := bw.write(data)!
|
||||
assert bw.buffered() == 0
|
||||
assert aw.result.len == 34 // 33*x + \n
|
||||
}
|
||||
|
||||
fn test_simple_flush() {
|
||||
mut aw := ArrayWriter{}
|
||||
mut bw := io.new_buffered_writer(writer: &aw, cap: 10)!
|
||||
data := create_data(6)
|
||||
w := bw.write(data)!
|
||||
|
||||
assert w == 7 // 6*x + \n
|
||||
assert bw.buffered() == 7
|
||||
|
||||
bw.flush()!
|
||||
assert bw.buffered() == 0
|
||||
assert aw.result.len == 7
|
||||
}
|
||||
|
||||
fn test_flush_handles_partial_writes() {
|
||||
mut cw := ChunkedArrayWriter{
|
||||
chunk: 2
|
||||
}
|
||||
mut bw := io.new_buffered_writer(writer: &cw, cap: 8)!
|
||||
data := 'abcdefg'.bytes()
|
||||
|
||||
written := bw.write(data)!
|
||||
assert written == data.len
|
||||
assert bw.buffered() == data.len
|
||||
assert cw.result.len == 0
|
||||
|
||||
bw.flush()!
|
||||
assert bw.buffered() == 0
|
||||
assert cw.result == data
|
||||
}
|
||||
|
||||
fn test_flush_preserves_unwritten_data_on_error() {
|
||||
mut fw := FailOnceChunkedWriter{
|
||||
chunk: 3
|
||||
}
|
||||
mut bw := io.new_buffered_writer(writer: &fw, cap: 8)!
|
||||
data := 'abcdefg'.bytes()
|
||||
_ = bw.write(data)!
|
||||
|
||||
if _ := bw.flush() {
|
||||
assert false
|
||||
} else {
|
||||
assert err.msg() == 'forced write failure'
|
||||
}
|
||||
assert fw.result == 'abc'.bytes()
|
||||
assert bw.buffered() == 4
|
||||
assert bw.buf[..bw.buffered()] == 'defg'.bytes()
|
||||
|
||||
bw.flush()!
|
||||
assert bw.buffered() == 0
|
||||
assert fw.result == data
|
||||
}
|
||||
|
||||
fn test_write_returns_error_for_zero_progress_writes() {
|
||||
mut zw := ZeroProgressWriter{}
|
||||
mut bw := io.new_buffered_writer(writer: &zw, cap: 4)!
|
||||
|
||||
if _ := bw.write('12345'.bytes()) {
|
||||
assert false
|
||||
} else {
|
||||
assert err.msg() == 'writer returned an invalid number of bytes while writing'
|
||||
}
|
||||
assert bw.buffered() == 0
|
||||
}
|
||||
Reference in new issue
Block a user