Files
tinygo/src/os/os_test.go
T
Dan Kegel a29e1d43f1 Kludge: provide stub for syscall.seek on 386 and arm, #1906
This replaces an earlier kludge which was at the wrong level
and caused "GOARCH=386 tinygo test os" to fail to compile on linux.

Stubbing just the one missing function, syscall.seek, lets
os tests compile on linux 386, and skipping tests of seek and Fstat
(which has a cryptic dependency on syscall.Seek via time)
lets os tests pass on linux 386.

The stub can be removed once tinygo implements go assembly and picks up the real definition.
2022-01-24 18:23:40 +01:00

252 lines
5.7 KiB
Go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package os_test
import (
"io"
"io/ioutil"
. "os"
"runtime"
"strings"
"syscall"
"testing"
)
// localTmp returns a local temporary directory not on NFS.
func localTmp() string {
return TempDir()
}
func newFile(testName string, t *testing.T) (f *File) {
f, err := CreateTemp("", testName)
if err != nil {
t.Fatalf("newFile %s: CreateTemp fails with %s", testName, err)
}
return
}
// Read with length 0 should not return EOF.
func TestRead0(t *testing.T) {
f := newFile("TestRead0", t)
defer Remove(f.Name())
defer f.Close()
const data = "hello, world\n"
io.WriteString(f, data)
f.Close()
f, err := Open(f.Name())
if err != nil {
t.Errorf("failed to reopen")
}
b := make([]byte, 0)
n, err := f.Read(b)
if n != 0 || err != nil {
t.Errorf("Read(0) = %d, %v, want 0, nil", n, err)
}
b = make([]byte, 5)
n, err = f.Read(b)
if n <= 0 || err != nil {
t.Errorf("Read(5) = %d, %v, want >0, nil", n, err)
}
}
// ReadAt with length 0 should not return EOF.
func TestReadAt0(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("TODO: implement Pread for Windows")
return
}
f := newFile("TestReadAt0", t)
defer Remove(f.Name())
defer f.Close()
const data = "hello, world\n"
io.WriteString(f, data)
b := make([]byte, 0)
n, err := f.ReadAt(b, 0)
if n != 0 || err != nil {
t.Errorf("ReadAt(0,0) = %d, %v, want 0, nil", n, err)
}
b = make([]byte, 5)
n, err = f.ReadAt(b, 0)
if n <= 0 || err != nil {
t.Errorf("ReadAt(5,0) = %d, %v, want >0, nil", n, err)
}
}
func checkMode(t *testing.T, path string, mode FileMode) {
dir, err := Stat(path)
if err != nil {
t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
}
if dir.Mode()&ModePerm != mode {
t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
}
}
func TestSeek(t *testing.T) {
if runtime.GOARCH == "386" || runtime.GOARCH == "arm" {
t.Log("TODO: implement seek for 386 and arm")
return
}
f := newFile("TestSeek", t)
if f == nil {
t.Fatalf("f is nil")
return // TODO: remove
}
defer Remove(f.Name())
defer f.Close()
const data = "hello, world\n"
io.WriteString(f, data)
type test struct {
in int64
whence int
out int64
}
var tests = []test{
{0, io.SeekCurrent, int64(len(data))},
{0, io.SeekStart, 0},
{5, io.SeekStart, 5},
{0, io.SeekEnd, int64(len(data))},
{0, io.SeekStart, 0},
{-1, io.SeekEnd, int64(len(data)) - 1},
{1 << 33, io.SeekStart, 1 << 33},
{1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
// Issue 21681, Windows 4G-1, etc:
{1<<32 - 1, io.SeekStart, 1<<32 - 1},
{0, io.SeekCurrent, 1<<32 - 1},
{2<<32 - 1, io.SeekStart, 2<<32 - 1},
{0, io.SeekCurrent, 2<<32 - 1},
}
for i, tt := range tests {
off, err := f.Seek(tt.in, tt.whence)
if off != tt.out || err != nil {
if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" {
mounts, _ := ioutil.ReadFile("/proc/mounts")
if strings.Contains(string(mounts), "reiserfs") {
// Reiserfs rejects the big seeks.
t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
}
}
t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
}
}
}
func TestReadAt(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("TODO: implement Pread for Windows")
return
}
f := newFile("TestReadAt", t)
defer Remove(f.Name())
defer f.Close()
const data = "hello, world\n"
io.WriteString(f, data)
b := make([]byte, 5)
n, err := f.ReadAt(b, 7)
if err != nil || n != len(b) {
t.Fatalf("ReadAt 7: %d, %v", n, err)
}
if string(b) != "world" {
t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
}
}
// Verify that ReadAt doesn't affect seek offset.
// In the Plan 9 kernel, there used to be a bug in the implementation of
// the pread syscall, where the channel offset was erroneously updated after
// calling pread on a file.
func TestReadAtOffset(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("TODO: implement Pread for Windows")
return
}
f := newFile("TestReadAtOffset", t)
defer Remove(f.Name())
defer f.Close()
const data = "hello, world\n"
io.WriteString(f, data)
f.Close()
f, err := Open(f.Name())
if err != nil {
t.Errorf("failed to reopen")
}
b := make([]byte, 5)
n, err := f.ReadAt(b, 7)
if err != nil || n != len(b) {
t.Fatalf("ReadAt 7: %d, %v", n, err)
}
if string(b) != "world" {
t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
}
n, err = f.Read(b)
if err != nil || n != len(b) {
t.Fatalf("Read: %d, %v", n, err)
}
if string(b) != "hello" {
t.Fatalf("Read: have %q want %q", string(b), "hello")
}
}
// Verify that ReadAt doesn't allow negative offset.
func TestReadAtNegativeOffset(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("TODO: implement Pread for Windows")
return
}
f := newFile("TestReadAtNegativeOffset", t)
defer Remove(f.Name())
defer f.Close()
const data = "hello, world\n"
io.WriteString(f, data)
f.Close()
f, err := Open(f.Name())
if err != nil {
t.Errorf("failed to reopen")
}
b := make([]byte, 5)
n, err := f.ReadAt(b, -10)
const wantsub = "negative offset"
if !strings.Contains(err.Error(), wantsub) || n != 0 {
t.Errorf("ReadAt(-10) = %v, %v; want 0, ...%q...", n, err, wantsub)
}
}
func TestReadAtEOF(t *testing.T) {
if runtime.GOOS == "windows" {
t.Log("TODO: implement Pread for Windows")
return
}
f := newFile("TestReadAtEOF", t)
defer Remove(f.Name())
defer f.Close()
_, err := f.ReadAt(make([]byte, 10), 0)
switch err {
case io.EOF:
// all good
case nil:
t.Fatalf("ReadAt succeeded")
default:
t.Fatalf("ReadAt failed: %s", err)
}
}