aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/vlib/os/file_test.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/vlib/os/file_test.v')
-rw-r--r--v_windows/v/vlib/os/file_test.v372
1 files changed, 372 insertions, 0 deletions
diff --git a/v_windows/v/vlib/os/file_test.v b/v_windows/v/vlib/os/file_test.v
new file mode 100644
index 0000000..3339ad8
--- /dev/null
+++ b/v_windows/v/vlib/os/file_test.v
@@ -0,0 +1,372 @@
+import os
+
+struct Point {
+ x f64
+ y f64
+ z f64
+}
+
+struct Extended_Point {
+ a f64
+ b f64
+ c f64
+ d f64
+ e f64
+ f f64
+ g f64
+ h f64
+ i f64
+}
+
+enum Color {
+ red
+ green
+ blue
+}
+
+[flag]
+enum Permissions {
+ read
+ write
+ execute
+}
+
+const (
+ unit_point = Point{1.0, 1.0, 1.0}
+ another_point = Point{0.25, 2.25, 6.25}
+ extended_point = Extended_Point{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}
+ another_byte = byte(123)
+ another_color = Color.red
+ another_permission = Permissions.read | .write
+)
+
+const (
+ tfolder = os.join_path(os.temp_dir(), 'os_file_test')
+ tfile = os.join_path(tfolder, 'test_file')
+)
+
+fn testsuite_begin() ? {
+ os.rmdir_all(tfolder) or {}
+ assert !os.is_dir(tfolder)
+ os.mkdir_all(tfolder) ?
+ os.chdir(tfolder) ?
+ assert os.is_dir(tfolder)
+}
+
+fn testsuite_end() ? {
+ os.chdir(os.wd_at_startup) ?
+ os.rmdir_all(tfolder) ?
+ assert !os.is_dir(tfolder)
+}
+
+// test_read_bytes_into_newline_text tests reading text from a file with newlines.
+// This test simulates reading a larger text file step by step into a buffer and
+// returning on each newline, even before the buffer is full, and reaching EOF before
+// the buffer is completely filled.
+fn test_read_bytes_into_newline_text() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_string('Hello World!\nGood\r morning.') ?
+ f.close()
+
+ f = os.open_file(tfile, 'r') ?
+ mut buf := []byte{len: 8}
+
+ n0 := f.read_bytes_into_newline(mut buf) ?
+ assert n0 == 8
+
+ n1 := f.read_bytes_into_newline(mut buf) ?
+ assert n1 == 5
+
+ n2 := f.read_bytes_into_newline(mut buf) ?
+ assert n2 == 8
+
+ n3 := f.read_bytes_into_newline(mut buf) ?
+ assert n3 == 6
+
+ f.close()
+}
+
+// test_read_bytes_into_newline_binary tests reading a binary file with NUL bytes.
+// This test simulates the scenario when a byte stream is read and a newline byte
+// appears in that stream and an EOF occurs before the buffer is full.
+fn test_read_bytes_into_newline_binary() ? {
+ os.rm(tfile) or {} // FIXME This is a workaround for macos, because the file isn't truncated when open with 'w'
+ mut bw := []byte{len: 15}
+ bw[9] = 0xff
+ bw[12] = 10 // newline
+
+ n0_bytes := bw[0..10]
+ n1_bytes := bw[10..13]
+ n2_bytes := bw[13..]
+
+ mut f := os.open_file(tfile, 'w') ?
+ f.write(bw) ?
+ f.close()
+
+ f = os.open_file(tfile, 'r') ?
+ mut buf := []byte{len: 10}
+
+ n0 := f.read_bytes_into_newline(mut buf) ?
+ assert n0 == 10
+ assert buf[..n0] == n0_bytes
+
+ n1 := f.read_bytes_into_newline(mut buf) ?
+ assert n1 == 3
+ assert buf[..n1] == n1_bytes
+
+ n2 := f.read_bytes_into_newline(mut buf) ?
+ assert n2 == 2
+ assert buf[..n2] == n2_bytes
+ f.close()
+}
+
+// test_read_eof_last_read_partial_buffer_fill tests that when reading a file
+// the end-of-file is detected and results in a none error being returned. This
+// test simulates file reading where the end-of-file is reached inside an fread
+// containing data.
+fn test_read_eof_last_read_partial_buffer_fill() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ bw := []byte{len: 199, init: 5}
+ f.write(bw) ?
+ f.close()
+
+ f = os.open_file(tfile, 'r') ?
+ mut br := []byte{len: 100}
+ // Read first 100 bytes of 199 byte file, should fill buffer with no error.
+ n0 := f.read(mut br) ?
+ assert n0 == 100
+ // Read remaining 99 bytes of 199 byte file, should fill buffer with no
+ // error, even though end-of-file was reached.
+ n1 := f.read(mut br) ?
+ assert n1 == 99
+ // Read again, end-of-file was previously reached so should return none
+ // error.
+ if _ := f.read(mut br) {
+ // This is not intended behavior because the read function should
+ // not return a number of bytes read when end-of-file is reached.
+ assert false
+ } else {
+ // Expect none to have been returned when end-of-file.
+ assert err is none
+ }
+ f.close()
+}
+
+// test_read_eof_last_read_full_buffer_fill tests that when reading a file the
+// end-of-file is detected and results in a none error being returned. This test
+// simulates file reading where the end-of-file is reached at the beinning of an
+// fread that returns no data.
+fn test_read_eof_last_read_full_buffer_fill() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ bw := []byte{len: 200, init: 5}
+ f.write(bw) ?
+ f.close()
+
+ f = os.open_file(tfile, 'r') ?
+ mut br := []byte{len: 100}
+ // Read first 100 bytes of 200 byte file, should fill buffer with no error.
+ n0 := f.read(mut br) ?
+ assert n0 == 100
+ // Read remaining 100 bytes of 200 byte file, should fill buffer with no
+ // error. The end-of-file isn't reached yet, but there is no more data.
+ n1 := f.read(mut br) ?
+ assert n1 == 100
+ // Read again, end-of-file was previously reached so should return none
+ // error.
+ if _ := f.read(mut br) {
+ // This is not intended behavior because the read function should
+ // not return a number of bytes read when end-of-file is reached.
+ assert false
+ } else {
+ // Expect none to have been returned when end-of-file.
+ assert err is none
+ }
+ f.close()
+}
+
+fn test_write_struct() ? {
+ os.rm(tfile) or {} // FIXME This is a workaround for macos, because the file isn't truncated when open with 'w'
+ size_of_point := int(sizeof(Point))
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_struct(another_point) ?
+ f.close()
+ x := os.read_file(tfile) ?
+ pcopy := unsafe { &byte(memdup(&another_point, size_of_point)) }
+ y := unsafe { pcopy.vstring_with_len(size_of_point) }
+ assert x == y
+ $if debug {
+ eprintln(x.bytes())
+ eprintln(y.bytes())
+ }
+}
+
+fn test_write_struct_at() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_struct(extended_point) ?
+ f.write_struct_at(another_point, 3) ?
+ f.close()
+ f = os.open_file(tfile, 'r') ?
+ mut p := Point{}
+ f.read_struct_at(mut p, 3) ?
+ f.close()
+
+ assert p == another_point
+}
+
+fn test_read_struct() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_struct(another_point) ?
+ f.close()
+
+ f = os.open_file(tfile, 'r') ?
+ mut p := Point{}
+ f.read_struct(mut p) ?
+ f.close()
+
+ assert p == another_point
+}
+
+fn test_read_struct_at() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write([byte(1), 2, 3]) ?
+ f.write_struct(another_point) ?
+ f.close()
+ f = os.open_file(tfile, 'r') ?
+ mut p := Point{}
+ f.read_struct_at(mut p, 3) ?
+ f.close()
+
+ assert p == another_point
+}
+
+fn test_write_raw() ? {
+ os.rm(tfile) or {} // FIXME This is a workaround for macos, because the file isn't truncated when open with 'w'
+ size_of_point := int(sizeof(Point))
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_raw(another_point) ?
+ f.close()
+ x := os.read_file(tfile) ?
+ pcopy := unsafe { &byte(memdup(&another_point, size_of_point)) }
+ y := unsafe { pcopy.vstring_with_len(size_of_point) }
+ assert x == y
+ $if debug {
+ eprintln(x.bytes())
+ eprintln(y.bytes())
+ }
+}
+
+fn test_write_raw_at() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_raw(extended_point) ?
+ f.write_raw_at(another_point, 3) ?
+ f.close()
+ f = os.open_file(tfile, 'r') ?
+ mut p := Point{}
+ f.read_struct_at(mut p, 3) ?
+ f.close()
+
+ assert p == another_point
+}
+
+fn test_write_raw_at_negative_pos() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ if _ := f.write_raw_at(another_point, -1) {
+ assert false
+ }
+ f.write_raw_at(another_point, -234) or { assert err.msg == 'Invalid argument' }
+ f.close()
+}
+
+fn test_read_raw() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_raw(another_point) ?
+ f.write_raw(another_byte) ?
+ f.write_raw(another_color) ?
+ f.write_raw(another_permission) ?
+ f.close()
+ f = os.open_file(tfile, 'r') ?
+ p := f.read_raw<Point>() ?
+ b := f.read_raw<byte>() ?
+ c := f.read_raw<Color>() ?
+ x := f.read_raw<Permissions>() ?
+ f.close()
+
+ assert p == another_point
+ assert b == another_byte
+ assert c == another_color
+ assert x == another_permission
+}
+
+fn test_read_raw_at() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write([byte(1), 2, 3]) ?
+ f.write_raw(another_point) ?
+ f.write_raw(another_byte) ?
+ f.write_raw(another_color) ?
+ f.write_raw(another_permission) ?
+ f.close()
+ f = os.open_file(tfile, 'r') ?
+ mut at := u64(3)
+ p := f.read_raw_at<Point>(at) ?
+ at += sizeof(Point)
+ b := f.read_raw_at<byte>(at) ?
+ at += sizeof(byte)
+ c := f.read_raw_at<Color>(at) ?
+ at += sizeof(Color)
+ x := f.read_raw_at<Permissions>(at) ?
+ at += sizeof(Permissions)
+ f.close()
+
+ assert p == another_point
+ assert b == another_byte
+ assert c == another_color
+ assert x == another_permission
+}
+
+fn test_read_raw_at_negative_pos() ? {
+ mut f := os.open_file(tfile, 'r') ?
+ if _ := f.read_raw_at<Point>(-1) {
+ assert false
+ }
+ f.read_raw_at<Point>(-234) or { assert err.msg == 'Invalid argument' }
+ f.close()
+}
+
+fn test_seek() ? {
+ mut f := os.open_file(tfile, 'w') ?
+ f.write_raw(another_point) ?
+ f.write_raw(another_byte) ?
+ f.write_raw(another_color) ?
+ f.write_raw(another_permission) ?
+ f.close()
+
+ // println('> ${sizeof(Point)} ${sizeof(byte)} ${sizeof(Color)} ${sizeof(Permissions)}')
+ f = os.open_file(tfile, 'r') ?
+ //
+ f.seek(i64(sizeof(Point)), .start) ?
+ assert f.tell() ? == sizeof(Point)
+ b := f.read_raw<byte>() ?
+ assert b == another_byte
+
+ f.seek(i64(sizeof(Color)), .current) ?
+ x := f.read_raw<Permissions>() ?
+ assert x == another_permission
+ //
+ f.close()
+}
+
+fn test_tell() ? {
+ for size in 10 .. 30 {
+ s := 'x'.repeat(size)
+ os.write_file(tfile, s) ?
+ fs := os.file_size(tfile)
+ assert int(fs) == size
+ //
+ mut f := os.open_file(tfile, 'r') ?
+ f.seek(-5, .end) ?
+ pos := f.tell() ?
+ f.close()
+ // dump(pos)
+ assert pos == size - 5
+ }
+}