Browse Source

Update `core:io` tests

- Relax return value requirements on errors. Only the error is checked,
  as there are multiple conflicting return styles throughout the `os`
  API.

  Some return the error along with `0`, `-1`, or another value. This can
  be smoothed out later.

- Test `os2` files now.
- No longer test streams after closing; this is considered similar to a
  use-after-free in `os2`.
Feoramund 1 year ago
parent
commit
8b40be50b9
1 changed files with 44 additions and 48 deletions
  1. 44 48
      tests/core/io/test_core_io.odin

+ 44 - 48
tests/core/io/test_core_io.odin

@@ -4,6 +4,7 @@ import "core:bytes"
 import "core:io"
 import "core:io"
 import "core:log"
 import "core:log"
 import "core:os"
 import "core:os"
+import "core:os/os2"
 import "core:strings"
 import "core:strings"
 import "core:testing"
 import "core:testing"
 
 
@@ -34,7 +35,7 @@ _test_stream :: proc(
 	// Do some basic Seek sanity testing.
 	// Do some basic Seek sanity testing.
 	if .Seek in mode_set {
 	if .Seek in mode_set {
 		pos, err := io.seek(stream, 0, io.Seek_From(-1))
 		pos, err := io.seek(stream, 0, io.Seek_From(-1))
-		testing.expectf(t, pos == 0 && err == .Invalid_Whence,
+		testing.expectf(t, err == .Invalid_Whence,
 			"Seek(-1) didn't fail with Invalid_Whence: %v, %v", pos, err, loc = loc) or_return
 			"Seek(-1) didn't fail with Invalid_Whence: %v, %v", pos, err, loc = loc) or_return
 
 
 		pos, err = io.seek(stream, 0, .Start)
 		pos, err = io.seek(stream, 0, .Start)
@@ -46,11 +47,11 @@ _test_stream :: proc(
 			"Seek Current isn't 0 at the start: %v, %v", pos, err, loc = loc) or_return
 			"Seek Current isn't 0 at the start: %v, %v", pos, err, loc = loc) or_return
 
 
 		pos, err = io.seek(stream, -1, .Start)
 		pos, err = io.seek(stream, -1, .Start)
-		testing.expectf(t, pos == 0 && err == .Invalid_Offset,
+		testing.expectf(t, err == .Invalid_Offset,
 			"Seek Start-1 wasn't Invalid_Offset: %v, %v", pos, err, loc = loc) or_return
 			"Seek Start-1 wasn't Invalid_Offset: %v, %v", pos, err, loc = loc) or_return
 
 
 		pos, err = io.seek(stream, -1, .Current)
 		pos, err = io.seek(stream, -1, .Current)
-		testing.expectf(t, pos == 0 && err == .Invalid_Offset,
+		testing.expectf(t, err == .Invalid_Offset,
 			"Seek Current-1 wasn't Invalid_Offset: %v, %v", pos, err, loc = loc) or_return
 			"Seek Current-1 wasn't Invalid_Offset: %v, %v", pos, err, loc = loc) or_return
 
 
 		pos, err = io.seek(stream, 0, .End)
 		pos, err = io.seek(stream, 0, .End)
@@ -107,7 +108,7 @@ _test_stream :: proc(
 		// Test empty streams and EOF.
 		// Test empty streams and EOF.
 		one_buf: [1]u8
 		one_buf: [1]u8
 		bytes_read, err := io.read_at(stream, one_buf[:], size)
 		bytes_read, err := io.read_at(stream, one_buf[:], size)
-		testing.expectf(t, bytes_read == 0 && err == .EOF,
+		testing.expectf(t, err == .EOF,
 			"Read_At at end of stream failed: %v, %v", bytes_read, err, loc = loc) or_return
 			"Read_At at end of stream failed: %v, %v", bytes_read, err, loc = loc) or_return
 
 
 		// Make sure size is still sane.
 		// Make sure size is still sane.
@@ -172,7 +173,7 @@ _test_stream :: proc(
 		// Test empty streams and EOF.
 		// Test empty streams and EOF.
 		one_buf: [1]u8
 		one_buf: [1]u8
 		bytes_read, err := io.read(stream, one_buf[:])
 		bytes_read, err := io.read(stream, one_buf[:])
-		testing.expectf(t, bytes_read == 0 && err == .EOF,
+		testing.expectf(t, err == .EOF,
 			"Read at end of stream failed: %v, %v", bytes_read, err, loc = loc) or_return
 			"Read at end of stream failed: %v, %v", bytes_read, err, loc = loc) or_return
 
 
 		if !resets_on_empty && .Size in mode_set {
 		if !resets_on_empty && .Size in mode_set {
@@ -320,49 +321,6 @@ _test_stream :: proc(
 		close_err := io.close(stream)
 		close_err := io.close(stream)
 		testing.expectf(t, close_err == nil, "stream failed to Close: %v", close_err, loc = loc) or_return
 		testing.expectf(t, close_err == nil, "stream failed to Close: %v", close_err, loc = loc) or_return
 		passed += { .Close }
 		passed += { .Close }
-
-		// TODO(Feoramund): The OS<->IO interface will need updating for more
-		// specific error messages.
-		//
-		// This test will catch it when they start using them, but so long as
-		// they actually error, it should be okay for now.
-		//
-		// .EOF would be a better message for all of these.
-
-		if .Seek in mode_set {
-			pos, err := io.seek(stream, 0, .Start)
-
-			testing.expectf(t, pos == 0 && err == .Invalid_Offset,
-				"Seek after Close unexpected output: pos<%v>, %v", pos, err, loc = loc) or_return
-		}
-
-		if .Read in mode_set {
-			eof_buf: [1]u8
-			bytes_read, err := io.read(stream, eof_buf[:])
-			testing.expectf(t, bytes_read == 0 && err == .Unknown,
-				"Read after Close unexpected output: bytes_read<%v>, %v", bytes_read, err, loc = loc) or_return
-		}
-
-		if size > 0 && .Read_At in mode_set {
-			eof_buf: [1]u8
-			bytes_read, err := io.read_at(stream, eof_buf[:], 0)
-			testing.expectf(t, bytes_read == 0 && err == .Unknown,
-				"Read_At after Close unexpected output: bytes_read<%v>, %v", bytes_read, err, loc = loc) or_return
-		}
-
-		if .Write in mode_set {
-			eof_buf: [1]u8 = {'Z'}
-			bytes_written, err := io.write(stream, eof_buf[:])
-			testing.expectf(t, bytes_written == 0 && err == .Unknown,
-				"Write after Close unexpected output: bytes_written<%v>, %v", bytes_written, err, loc = loc) or_return
-		}
-
-		if .Write_At in mode_set {
-			eof_buf: [1]u8 = {'Z'}
-			bytes_written, err := io.write_at(stream, eof_buf[:], 0)
-			testing.expectf(t, bytes_written == 0 && err == .Unknown,
-				"Write after Close unexpected output: bytes_written<%v>, %v", bytes_written, err, loc = loc) or_return
-		}
 	}
 	}
 
 
 	if do_destroy && .Destroy in mode_set {
 	if do_destroy && .Destroy in mode_set {
@@ -547,3 +505,41 @@ test_os_file_stream :: proc(t: ^testing.T) {
 
 
 	log.debugf("%#v", results)
 	log.debugf("%#v", results)
 }
 }
+
+@test
+test_os2_file_stream :: proc(t: ^testing.T) {
+	defer if !testing.failed(t) {
+		testing.expect_value(t, os2.remove(TEMPORARY_FILENAME), nil)
+	}
+
+	buf: [32]u8
+	for i in 0..<u8(len(buf)) {
+		buf[i] = 'A' + i
+	}
+
+	TEMPORARY_FILENAME :: "test_core_io_os2_file_stream"
+
+	fd, open_err := os2.open(TEMPORARY_FILENAME, {.Read, .Write, .Create, .Trunc})
+	if !testing.expectf(t, open_err == nil, "error on opening %q: %v", TEMPORARY_FILENAME, open_err) {
+		return
+	}
+	
+	stream := os2.to_stream(fd)
+
+	bytes_written, write_err := io.write(stream, buf[:])
+	if !testing.expectf(t, bytes_written == len(buf) && write_err == nil,
+		"failed to Write initial buffer: bytes_written<%v> != len_buf<%v>, %v", bytes_written, len(buf), write_err) {
+		return
+	}
+
+	flush_err := io.flush(stream)
+	if !testing.expectf(t, flush_err == nil,
+		"failed to Flush initial buffer: %v", write_err) {
+		return
+	}
+
+	// os2 file stream proc close and destroy are the same.
+	results, _ := _test_stream(t, stream, buf[:], do_destroy = false)
+
+	log.debugf("%#v", results)
+}