Skip to content

Commit

Permalink
Merge pull request #81 from xushiwei/q
Browse files Browse the repository at this point in the history
TestHttpFile
  • Loading branch information
xushiwei authored Sep 15, 2023
2 parents f75d7ed + 3b69aba commit 0fc9c39
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
88 changes: 88 additions & 0 deletions http/fs/fs_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package fs

import (
"context"
"fmt"
"io"
"io/fs"
"net/http"
Expand All @@ -9,9 +11,91 @@ import (
"testing"
"time"

"github.com/qiniu/x/mockhttp"
"github.com/qiniu/x/ts"
)

// -----------------------------------------------------------------------------------------

type statCloser interface {
io.Closer
Stat() (fs.FileInfo, error)
}

type dirReader interface {
ReadDir(n int) ([]fs.DirEntry, error)
}

type expectFile struct {
name string
close error
openErr error
statErr error
readdirFIs []fs.FileInfo
readdirDEs []fs.DirEntry
readdirErr error
readErr error
seekOff int64
seekNewOff int64
seekErr error
seekWhence int
readN int
}

func testSC(ts *ts.Testing, f statCloser, exp *expectFile) {
ts.Case("f.Close", f.Close()).Equal(exp.close)
ts.New("f.Stat").Init(f.Stat()).Next().Equal(exp.statErr)
}

func testHF(ts *ts.Testing, f http.File, exp *expectFile) {
testSC(ts, f, exp)
ts.New("f.Read").Init(f.Read(make([]byte, 1))).Equal(exp.readN, exp.readErr)
ts.New("f.Readdir").Init(f.Readdir(-1)).Equal(exp.readdirFIs, exp.readdirErr)
ts.New("f.ReadDir").Init(f.(dirReader).ReadDir(-1)).Equal(exp.readdirDEs, exp.readdirErr)
ts.New("f.Seek").Init(f.Seek(exp.seekOff, exp.seekWhence)).Equal(exp.seekNewOff, exp.seekErr)
}

func testFile(t *testing.T, v interface{}, exp *expectFile) {
ts := ts.New(t)
switch f := v.(type) {
case http.FileSystem:
file, err := f.Open(exp.name)
ts.New("f.Open").Init(err).Equal(exp.openErr)
if err == nil {
testHF(ts, file, exp)
}
case http.File:
testHF(ts, f, exp)
case statCloser:
testSC(ts, f, exp)
}
}

func TestHttpFile(t *testing.T) {
testFile(t, FilesWithContent("foo/a.txt", "a"), &expectFile{name: "/foo/a.txt", readdirErr: fs.ErrInvalid, readN: 1})
testFile(t, Root(), &expectFile{name: "/", readdirErr: io.EOF, readErr: io.EOF})
mock.ListenAndServe("a.com", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "a")
}))
mock.ListenAndServe("b.com", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404)
}))
mock.ListenAndServe("c.com", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
}))
err500 := fmt.Errorf("http.Get %s error: status %d (%s)", "http://c.com/", 500, "")
testFile(t, Http("http://a.com", context.TODO()).With(mockClient, nil), &expectFile{name: "/", readdirErr: fs.ErrInvalid, readN: 1})
testFile(t, Http("http://b.com").With(mockClient, nil), &expectFile{name: "/", openErr: &fs.PathError{Op: "http.Get", Path: "http://b.com/", Err: fs.ErrNotExist}})
testFile(t, Http("http://c.com").With(mockClient, nil), &expectFile{name: "/", openErr: &fs.PathError{Op: "http.Get", Path: "http://c.com/", Err: err500}})
}

var (
mockClient = mockhttp.DefaultClient
mock = mockhttp.DefaultTransport
)

// -----------------------------------------------------------------------------------------

func testFI(t *testing.T, fi fs.FileInfo, name string, size int64, mode fs.FileMode, zeroTime, isDir bool, sys interface{}) {
ts := ts.New(t)
ts.Case("fi.Name", fi.Name()).Equal(name)
Expand All @@ -35,6 +119,8 @@ func TestFileInfo(t *testing.T) {
testFI(t, SequenceFile("/foo/a.txt", nil).(*stream), "a.txt", -1, fs.ModeIrregular, false, false, nil)
}

// -----------------------------------------------------------------------------------------

func TestUnionFS(t *testing.T) {
fs := Union(Root(), Files("fs/file.go", "/not-exist/noop.nil"), FilesWithContent("fs/file.go", "a"))
f, err := fs.Open("/fs/file.go")
Expand Down Expand Up @@ -80,3 +166,5 @@ func TestSubFS(t *testing.T) {
t.Fatal(err)
}
}

// -----------------------------------------------------------------------------------------
9 changes: 7 additions & 2 deletions ts/case.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,21 @@ func (p *Testing) New(name string) *TestCase {
return &TestCase{name: name, t: p.t}
}

// Call creates a test case, and then calls a function.
// Call creates a test case without name, and calls a function.
func (p *Testing) Call(fn interface{}, args ...interface{}) *TestCase {
return p.New("").Call(fn, args...)
}

// Case creates a test case and sets its output parameters.
// Case creates a test case with name and sets its output parameters.
func (p *Testing) Case(name string, result ...interface{}) *TestCase {
return p.New(name).Init(result...)
}

// Init creates a test case without name and sets its output parameters.
func (p *Testing) Init(result ...interface{}) *TestCase {
return p.New("").Init(result...)
}

// ----------------------------------------------------------------------------

// TestCase represents a test case.
Expand Down

0 comments on commit 0fc9c39

Please sign in to comment.