test(files, users): add e2e test and fix issues

This commit is contained in:
hexxa 2020-12-10 22:22:38 +08:00
parent b065684a47
commit 0265baf1b1
15 changed files with 5015 additions and 5327 deletions

View file

@ -3,6 +3,7 @@ package client
import (
"encoding/json"
"fmt"
"net/http"
"github.com/ihexxa/quickshare/src/handlers/fileshdr"
"github.com/parnurzeal/gorequest"
@ -25,7 +26,7 @@ func (cl *FilesClient) url(urlpath string) string {
return fmt.Sprintf("%s%s", cl.addr, urlpath)
}
func (cl *FilesClient) Create(filepath string, size int64) (gorequest.Response, string, []error) {
func (cl *FilesClient) Create(filepath string, size int64) (*http.Response, string, []error) {
return cl.r.Post(cl.url("/v1/fs/files")).
Send(fileshdr.CreateReq{
Path: filepath,
@ -34,13 +35,13 @@ func (cl *FilesClient) Create(filepath string, size int64) (gorequest.Response,
End()
}
func (cl *FilesClient) Delete(filepath string) (gorequest.Response, string, []error) {
func (cl *FilesClient) Delete(filepath string) (*http.Response, string, []error) {
return cl.r.Delete(cl.url("/v1/fs/files")).
Param(fileshdr.FilePathQuery, filepath).
End()
}
func (cl *FilesClient) Metadata(filepath string) (gorequest.Response, *fileshdr.MetadataResp, []error) {
func (cl *FilesClient) Metadata(filepath string) (*http.Response, *fileshdr.MetadataResp, []error) {
resp, body, errs := cl.r.Get(cl.url("/v1/fs/metadata")).
Param(fileshdr.FilePathQuery, filepath).
End()
@ -54,13 +55,13 @@ func (cl *FilesClient) Metadata(filepath string) (gorequest.Response, *fileshdr.
return resp, mResp, nil
}
func (cl *FilesClient) Mkdir(dirpath string) (gorequest.Response, string, []error) {
func (cl *FilesClient) Mkdir(dirpath string) (*http.Response, string, []error) {
return cl.r.Post(cl.url("/v1/fs/dirs")).
Send(fileshdr.MkdirReq{Path: dirpath}).
End()
}
func (cl *FilesClient) Move(oldpath, newpath string) (gorequest.Response, string, []error) {
func (cl *FilesClient) Move(oldpath, newpath string) (*http.Response, string, []error) {
return cl.r.Patch(cl.url("/v1/fs/files/move")).
Send(fileshdr.MoveReq{
OldPath: oldpath,
@ -69,7 +70,7 @@ func (cl *FilesClient) Move(oldpath, newpath string) (gorequest.Response, string
End()
}
func (cl *FilesClient) UploadChunk(filepath string, content string, offset int64) (gorequest.Response, string, []error) {
func (cl *FilesClient) UploadChunk(filepath string, content string, offset int64) (*http.Response, string, []error) {
return cl.r.Patch(cl.url("/v1/fs/files/chunks")).
Send(fileshdr.UploadChunkReq{
Path: filepath,
@ -79,7 +80,7 @@ func (cl *FilesClient) UploadChunk(filepath string, content string, offset int64
End()
}
func (cl *FilesClient) UploadStatus(filepath string) (gorequest.Response, *fileshdr.UploadStatusResp, []error) {
func (cl *FilesClient) UploadStatus(filepath string) (*http.Response, *fileshdr.UploadStatusResp, []error) {
resp, body, errs := cl.r.Get(cl.url("/v1/fs/files/chunks")).
Param(fileshdr.FilePathQuery, filepath).
End()
@ -93,8 +94,8 @@ func (cl *FilesClient) UploadStatus(filepath string) (gorequest.Response, *files
return resp, uResp, nil
}
func (cl *FilesClient) Download(filepath string, headers map[string]string) (gorequest.Response, string, []error) {
r := cl.r.Get(cl.url("/v1/fs/files/chunks")).
func (cl *FilesClient) Download(filepath string, headers map[string]string) (*http.Response, string, []error) {
r := cl.r.Get(cl.url("/v1/fs/files")).
Param(fileshdr.FilePathQuery, filepath)
for key, val := range headers {
r = r.Set(key, val)
@ -102,7 +103,7 @@ func (cl *FilesClient) Download(filepath string, headers map[string]string) (gor
return r.End()
}
func (cl *FilesClient) List(dirPath string) (gorequest.Response, *fileshdr.ListResp, []error) {
func (cl *FilesClient) List(dirPath string) (*http.Response, *fileshdr.ListResp, []error) {
resp, body, errs := cl.r.Get(cl.url("/v1/fs/dirs")).
Param(fileshdr.ListDirQuery, dirPath).
End()

30
src/client/settings.go Normal file
View file

@ -0,0 +1,30 @@
package client
import (
"fmt"
"net/http"
"github.com/parnurzeal/gorequest"
)
type SettingsClient struct {
addr string
r *gorequest.SuperAgent
}
func NewSettingsClient(addr string) *SettingsClient {
gr := gorequest.New()
return &SettingsClient{
addr: addr,
r: gr,
}
}
func (cl *SettingsClient) url(urlpath string) string {
return fmt.Sprintf("%s%s", cl.addr, urlpath)
}
func (cl *SettingsClient) Health() (*http.Response, string, []error) {
return cl.r.Options(cl.url("/v1/settings/health")).
End()
}

View file

@ -56,12 +56,16 @@ func (fs *LocalFS) Root() string {
}
// closeOpens assumes that it is called after opensMtx.Lock()
func (fs *LocalFS) closeOpens(closeAll bool) error {
func (fs *LocalFS) closeOpens(closeAll bool, exclude map[string]bool) error {
batch := fs.opensCleanSize
var err error
for key, info := range fs.opens {
if batch <= 0 && !closeAll {
if exclude[key] {
continue
}
if !closeAll && batch <= 0 {
break
}
batch--
@ -83,7 +87,7 @@ func (fs *LocalFS) closeOpens(closeAll bool) error {
func (fs *LocalFS) Sync() error {
fs.opensMtx.Lock()
defer fs.opensMtx.Unlock()
return fs.closeOpens(true)
return fs.closeOpens(true, map[string]bool{})
}
// check refers implementation of Dir.Open() in http package
@ -176,6 +180,7 @@ func (fs *LocalFS) ReadAt(path string, b []byte, off int64) (int, error) {
return nil, ErrTooManyOpens
}
// because the fd may be for other usage, its flag is not set as os.O_RDONLY
fd, err := os.OpenFile(fullpath, os.O_RDWR|os.O_APPEND, fs.defaultPerm)
if err != nil {
return nil, err
@ -185,7 +190,7 @@ func (fs *LocalFS) ReadAt(path string, b []byte, off int64) (int, error) {
lastAccess: time.Now(),
}
fs.opens[fullpath] = info
fs.closeOpens(false)
fs.closeOpens(false, map[string]bool{fullpath: true})
}
return info, nil
@ -231,7 +236,7 @@ func (fs *LocalFS) WriteAt(path string, b []byte, off int64) (int, error) {
lastAccess: time.Now(),
}
fs.opens[fullpath] = info
fs.closeOpens(false)
fs.closeOpens(false, map[string]bool{fullpath: true})
}
return info, nil

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"net/http"
"os"
"path"
"path/filepath"
@ -270,7 +271,7 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) {
fsFilePath := h.FsPath(req.Path)
err = h.deps.FS().Rename(tmpFilePath, fsFilePath)
if err != nil {
c.JSON(q.ErrResp(c, 500, err))
c.JSON(q.ErrResp(c, 500, fmt.Errorf("%s error: %w", req.Path, err)))
return
}
err = h.uploadMgr.DelInfo(tmpFilePath)
@ -328,43 +329,75 @@ func (h *FileHandlers) Download(c *gin.Context) {
filePath := c.Query(FilePathQuery)
if filePath == "" {
c.JSON(q.ErrResp(c, 400, errors.New("invalid file name")))
return
}
// concurrency relies on os's mechanism
// concurrently file accessing is managed by os
filePath = h.FsPath(filePath)
info, err := h.deps.FS().Stat(filePath)
if err != nil {
c.JSON(q.ErrResp(c, 400, err))
if os.IsNotExist(err) {
c.JSON(q.ErrResp(c, 400, os.ErrNotExist))
} else {
c.JSON(q.ErrResp(c, 500, err))
}
return
} else if info.IsDir() {
c.JSON(q.ErrResp(c, 501, errors.New("downloading a folder is not supported")))
c.JSON(q.ErrResp(c, 400, errors.New("downloading a folder is not supported")))
return
}
// https://golang.google.cn/pkg/net/http/#DetectContentType
// DetectContentType considers at most the first 512 bytes of data.
fileHeadBuf := make([]byte, 512)
read, err := h.deps.FS().ReadAt(filePath, fileHeadBuf, 0)
if err != nil && err != io.EOF {
c.JSON(q.ErrResp(c, 500, err))
return
}
contentType := http.DetectContentType(fileHeadBuf[:read])
r, err := h.deps.FS().GetFileReader(filePath)
if err != nil {
c.JSON(q.ErrResp(c, 500, err))
return
}
// defer r.Close()
// := r.(*os.File)
// respond to normal requests
fmt.Println(ifRangeVal, rangeVal)
if ifRangeVal != "" || rangeVal == "" {
c.DataFromReader(200, info.Size(), "application/octet-stream", r, map[string]string{})
c.DataFromReader(200, info.Size(), contentType, r, map[string]string{})
return
}
// respond to range requests
parts, err := multipart.RangeToParts(rangeVal, "application/octet-stream", fmt.Sprintf("%d", info.Size()))
parts, err := multipart.RangeToParts(rangeVal, contentType, fmt.Sprintf("%d", info.Size()))
if err != nil {
c.JSON(q.ErrResp(c, 400, err))
c.JSON(q.ErrResp(c, 401, err))
return
}
pr, pw := io.Pipe()
err = multipart.WriteResponse(r, pw, filePath, parts)
// pr, pw := io.Pipe()
mw, contentLength, err := multipart.NewResponseWriter(r, parts, false)
if err != nil {
c.JSON(q.ErrResp(c, 500, err))
return
}
go mw.Write()
// WriteResponse(r, pw, filePath, parts)
// if err != nil {
// c.JSON(q.ErrResp(c, 500, err))
// return
// }
extraHeaders := map[string]string{
"Content-Disposition": fmt.Sprintf(`attachment; filename="%s"`, filePath),
// "Content-Disposition": fmt.Sprintf(`attachment; filename="%s"`, filePath),
}
c.DataFromReader(206, info.Size(), "application/octet-stream", pr, extraHeaders)
// it takes the \r\n before body into account, so contentLength+2
c.DataFromReader(206, contentLength+2, contentType, mw, extraHeaders)
}
type ListResp struct {
@ -374,7 +407,7 @@ type ListResp struct {
func (h *FileHandlers) List(c *gin.Context) {
dirPath := c.Query(ListDirQuery)
if dirPath == "" {
c.JSON(q.ErrResp(c, 400, errors.New("incorrect path name")))
c.JSON(q.ErrResp(c, 402, errors.New("incorrect path name")))
return
}

View file

@ -0,0 +1,26 @@
package settings
import (
"github.com/gin-gonic/gin"
"github.com/ihexxa/gocfg"
"github.com/ihexxa/quickshare/src/depidx"
q "github.com/ihexxa/quickshare/src/handlers"
)
type SettingsSvc struct {
cfg gocfg.ICfg
deps *depidx.Deps
}
func NewSettingsSvc(cfg gocfg.ICfg, deps *depidx.Deps) (*SettingsSvc, error) {
return &SettingsSvc{
cfg: cfg,
deps: deps,
}, nil
}
func (h *SettingsSvc) Health(c *gin.Context) {
// TODO: currently it checks nothing
c.JSON(q.Resp(200))
}

View file

@ -10,6 +10,11 @@ import (
q "github.com/ihexxa/quickshare/src/handlers"
)
var exposedAPIs = map[string]bool{
"Login-fm": true,
"Health-fm": true,
}
func GetHandlerName(fullname string) (string, error) {
parts := strings.Split(fullname, ".")
if len(parts) == 0 {
@ -28,7 +33,7 @@ func (h *SimpleUserHandlers) Auth() gin.HandlerFunc {
// TODO: may also check the path
enableAuth := h.cfg.GrabBool("Users.EnableAuth")
if enableAuth && handlerName != "Login-fm" {
if enableAuth && !exposedAPIs[handlerName] {
token, err := c.Cookie(TokenCookie)
if err != nil {
c.JSON(q.ErrResp(c, 401, err))

View file

@ -49,7 +49,7 @@ func DefaultConfig() (string, error) {
OpenTTL: 60, // 1 min
},
Users: &UsersCfg{
EnableAuth: true,
EnableAuth: false,
DefaultAdmin: "",
DefaultAdminPwd: "",
CookieTTL: 3600 * 24 * 7, // 1 week

View file

@ -8,6 +8,7 @@ import (
"net/http"
"time"
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
"github.com/ihexxa/gocfg"
@ -16,6 +17,7 @@ import (
"github.com/ihexxa/quickshare/src/fs"
"github.com/ihexxa/quickshare/src/fs/local"
"github.com/ihexxa/quickshare/src/handlers/fileshdr"
"github.com/ihexxa/quickshare/src/handlers/settings"
"github.com/ihexxa/quickshare/src/handlers/singleuserhdr"
"github.com/ihexxa/quickshare/src/idgen/simpleidgen"
"github.com/ihexxa/quickshare/src/kvstore"
@ -114,31 +116,41 @@ func initHandlers(router *gin.Engine, cfg gocfg.ICfg, deps *depidx.Deps) (*gin.E
return nil, err
}
settingsSvc, err := settings.NewSettingsSvc(cfg, deps)
if err != nil {
return nil, err
}
// middleware
router.Use(userHdrs.Auth())
// tmp static server
router.Use(static.Serve("/", static.LocalFile("../static", false)))
// handler
v1 := router.Group("/v1")
users := v1.Group("/users")
users.POST("/login", userHdrs.Login)
users.POST("/logout", userHdrs.Logout)
users.PATCH("/pwd", userHdrs.SetPwd)
usersAPI := v1.Group("/users")
usersAPI.POST("/login", userHdrs.Login)
usersAPI.POST("/logout", userHdrs.Logout)
usersAPI.PATCH("/pwd", userHdrs.SetPwd)
filesSvc := v1.Group("/fs")
filesSvc.POST("/files", fileHdrs.Create)
filesSvc.DELETE("/files", fileHdrs.Delete)
filesSvc.GET("/files", fileHdrs.Download)
filesSvc.PATCH("/files/chunks", fileHdrs.UploadChunk)
filesSvc.GET("/files/chunks", fileHdrs.UploadStatus)
filesSvc.PATCH("/files/copy", fileHdrs.Copy)
filesSvc.PATCH("/files/move", fileHdrs.Move)
filesAPI := v1.Group("/fs")
filesAPI.POST("/files", fileHdrs.Create)
filesAPI.DELETE("/files", fileHdrs.Delete)
filesAPI.GET("/files", fileHdrs.Download)
filesAPI.PATCH("/files/chunks", fileHdrs.UploadChunk)
filesAPI.GET("/files/chunks", fileHdrs.UploadStatus)
filesAPI.PATCH("/files/copy", fileHdrs.Copy)
filesAPI.PATCH("/files/move", fileHdrs.Move)
filesSvc.GET("/dirs", fileHdrs.List)
filesSvc.POST("/dirs", fileHdrs.Mkdir)
filesAPI.GET("/dirs", fileHdrs.List)
filesAPI.POST("/dirs", fileHdrs.Mkdir)
// files.POST("/dirs/copy", fileHdrs.CopyDir)
filesSvc.GET("/metadata", fileHdrs.Metadata)
filesAPI.GET("/metadata", fileHdrs.Metadata)
settingsAPI := v1.Group("/settings")
settingsAPI.OPTIONS("/health", settingsSvc.Health)
return router, nil
}

View file

@ -3,11 +3,14 @@ package server
import (
"crypto/sha1"
"fmt"
"math/rand"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"sync"
"testing"
"time"
"github.com/ihexxa/quickshare/src/client"
"github.com/ihexxa/quickshare/src/handlers/fileshdr"
@ -16,7 +19,6 @@ import (
func TestFileHandlers(t *testing.T) {
addr := "http://127.0.0.1:8888"
root := "testData"
chunkSize := 2
config := `{
"users": {
"enableAuth": false
@ -29,6 +31,7 @@ func TestFileHandlers(t *testing.T) {
}
}`
os.RemoveAll(root)
err := os.MkdirAll(root, 0700)
if err != nil {
t.Fatal(err)
@ -37,17 +40,110 @@ func TestFileHandlers(t *testing.T) {
srv := startTestServer(config)
defer srv.Shutdown()
// kv := srv.depsKVStore()
fs := srv.depsFS()
cl := client.NewFilesClient(addr)
// TODO: remove this
time.Sleep(500)
if !waitForReady(addr) {
t.Fatal("fail to start server")
}
t.Run("test file APIs: Create-UploadChunk-UploadStatus-Metadata-Delete", func(t *testing.T) {
assertUploadOK := func(t *testing.T, filePath, content string) bool {
cl := client.NewFilesClient(addr)
fileSize := int64(len([]byte(content)))
res, _, errs := cl.Create(filePath, fileSize)
if len(errs) > 0 {
t.Error(errs)
return false
} else if res.StatusCode != 200 {
t.Error(res.StatusCode)
return false
}
res, _, errs = cl.UploadChunk(filePath, content, 0)
if len(errs) > 0 {
t.Error(errs)
return false
} else if res.StatusCode != 200 {
t.Error(res.StatusCode)
return false
}
return true
}
assetDownloadOK := func(t *testing.T, filePath, content string) bool {
var (
res *http.Response
body string
errs []error
fileSize = int64(len([]byte(content)))
)
cl := client.NewFilesClient(addr)
rd := rand.Intn(3)
switch rd {
case 0:
res, body, errs = cl.Download(filePath, map[string]string{})
case 1:
res, body, errs = cl.Download(filePath, map[string]string{
"Range": fmt.Sprintf("bytes=0-%d", fileSize-1),
})
case 2:
res, body, errs = cl.Download(filePath, map[string]string{
"Range": fmt.Sprintf("bytes=0-%d, %d-%d", (fileSize-1)/2, (fileSize-1)/2+1, fileSize-1),
})
}
if len(errs) > 0 {
t.Error(errs)
return false
} else if res.StatusCode != 200 && res.StatusCode != 206 {
t.Error(res.StatusCode)
return false
}
switch rd {
case 0:
if body != content {
t.Errorf("body not equal got(%s) expect(%s)\n", body, content)
return false
}
case 1:
if body[2:] != content { // body returned by gorequest contains the first CRLF
t.Errorf("body not equal got(%s) expect(%s)\n", body[2:], content)
return false
}
default:
body = body[2:] // body returned by gorequest contains the first CRLF
realBody := ""
boundaryEnd := strings.Index(body, "\r\n")
boundary := body[0:boundaryEnd]
bodyParts := strings.Split(body, boundary)
for i, bodyPart := range bodyParts {
if i == 0 || i == len(bodyParts)-1 {
continue
}
start := strings.Index(bodyPart, "\r\n\r\n")
fmt.Printf("<%s>", bodyPart[start+4:len(bodyPart)-2]) // ignore the last CRLF
realBody += bodyPart[start+4 : len(bodyPart)-2]
}
if realBody != content {
t.Errorf("multi body not equal got(%s) expect(%s)\n", realBody, content)
return false
}
}
return true
}
t.Run("test files APIs: Create-UploadChunk-UploadStatus-Metadata-Delete", func(t *testing.T) {
for filePath, content := range map[string]string{
"path1/f1.md": "11111",
"path1/path2/f2.md": "101010",
"path1/f1.md": "1111 1111 1111 1111",
"path1/path2/f2.md": "1010 1010 1111 0000 0010",
} {
fileSize := int64(len([]byte(content)))
// create a file
@ -71,7 +167,7 @@ func TestFileHandlers(t *testing.T) {
i := 0
contentBytes := []byte(content)
for i < len(contentBytes) {
right := i + chunkSize
right := i + rand.Intn(3) + 1
if right > len(contentBytes) {
right = len(contentBytes)
}
@ -127,7 +223,7 @@ func TestFileHandlers(t *testing.T) {
}
})
t.Run("test file APIs: Mkdir-Create-UploadChunk-List", func(t *testing.T) {
t.Run("test dirs APIs: Mkdir-Create-UploadChunk-List", func(t *testing.T) {
for dirPath, files := range map[string]map[string]string{
"dir/path1/": map[string]string{
"f1.md": "11111",
@ -146,22 +242,7 @@ func TestFileHandlers(t *testing.T) {
for fileName, content := range files {
filePath := filepath.Join(dirPath, fileName)
fileSize := int64(len([]byte(content)))
// create a file
res, _, errs := cl.Create(filePath, fileSize)
if len(errs) > 0 {
t.Fatal(errs)
} else if res.StatusCode != 200 {
t.Fatal(res.StatusCode)
}
res, _, errs = cl.UploadChunk(filePath, content, 0)
if len(errs) > 0 {
t.Fatal(errs)
} else if res.StatusCode != 200 {
t.Fatal(res.StatusCode)
}
assertUploadOK(t, filePath, content)
}
_, lResp, errs := cl.List(dirPath)
@ -179,7 +260,7 @@ func TestFileHandlers(t *testing.T) {
}
})
t.Run("test file APIs: Mkdir-Create-UploadChunk-Move-List", func(t *testing.T) {
t.Run("test operation APIs: Mkdir-Create-UploadChunk-Move-List", func(t *testing.T) {
srcDir := "move/src"
dstDir := "move/dst"
@ -200,24 +281,10 @@ func TestFileHandlers(t *testing.T) {
for fileName, content := range files {
oldPath := filepath.Join(srcDir, fileName)
newPath := filepath.Join(dstDir, fileName)
fileSize := int64(len([]byte(content)))
// fileSize := int64(len([]byte(content)))
assertUploadOK(t, oldPath, content)
// create a file
res, _, errs := cl.Create(oldPath, fileSize)
if len(errs) > 0 {
t.Fatal(errs)
} else if res.StatusCode != 200 {
t.Fatal(res.StatusCode)
}
res, _, errs = cl.UploadChunk(oldPath, content, 0)
if len(errs) > 0 {
t.Fatal(errs)
} else if res.StatusCode != 200 {
t.Fatal(res.StatusCode)
}
res, _, errs = cl.Move(oldPath, newPath)
res, _, errs := cl.Move(oldPath, newPath)
if len(errs) > 0 {
t.Fatal(errs)
} else if res.StatusCode != 200 {
@ -238,4 +305,69 @@ func TestFileHandlers(t *testing.T) {
}
}
})
t.Run("test download APIs: Download(normal, ranges)", func(t *testing.T) {
for filePath, content := range map[string]string{
"download/path1/f1": "123456",
"download/path1/path2": "12345678",
} {
assertUploadOK(t, filePath, content)
err = fs.Sync()
if err != nil {
t.Fatal(err)
}
assetDownloadOK(t, filePath, content)
}
})
t.Run("test concurrently uploading & downloading", func(t *testing.T) {
type mockFile struct {
FilePath string
Content string
}
wg := &sync.WaitGroup{}
startClient := func(files []*mockFile) {
for i := 0; i < 5; i++ {
for _, file := range files {
if !assertUploadOK(t, fmt.Sprintf("%s_%d", file.FilePath, i), file.Content) {
break
}
err = fs.Sync()
if err != nil {
t.Fatal(err)
}
if !assetDownloadOK(t, fmt.Sprintf("%s_%d", file.FilePath, i), file.Content) {
break
}
}
}
wg.Done()
}
for _, clientFiles := range [][]*mockFile{
[]*mockFile{
&mockFile{"concurrent/p0/f0", "00"},
&mockFile{"concurrent/f0.md", "0000 0000 0000 0"},
},
[]*mockFile{
&mockFile{"concurrent/p1/f1", "11"},
&mockFile{"concurrent/f1.md", "1111 1111 1"},
},
[]*mockFile{
&mockFile{"concurrent/p2/f2", "22"},
&mockFile{"concurrent/f2.md", "222"},
},
} {
wg.Add(1)
go startClient(clientFiles)
}
wg.Wait()
})
}

View file

@ -3,7 +3,6 @@ package server
import (
"os"
"testing"
"time"
"github.com/ihexxa/quickshare/src/client"
su "github.com/ihexxa/quickshare/src/handlers/singleuserhdr"
@ -29,6 +28,7 @@ func TestSingleUserHandlers(t *testing.T) {
os.Setenv("DEFAULTADMIN", adminName)
os.Setenv("DEFAULTADMINPWD", adminPwd)
os.RemoveAll(root)
err := os.MkdirAll(root, 0700)
if err != nil {
t.Fatal(err)
@ -39,10 +39,10 @@ func TestSingleUserHandlers(t *testing.T) {
defer srv.Shutdown()
suCl := client.NewSingleUserClient(addr)
// fCl := client.NewFilesClient(addr)
// TODO: remove this
time.Sleep(1000)
if !waitForReady(addr) {
t.Fatal("fail to start server")
}
t.Run("test single user APIs: Login-SetPwd-Logout-Login", func(t *testing.T) {
resp, _, errs := suCl.Login(adminName, adminPwd)

View file

@ -1,6 +1,11 @@
package server
import "github.com/ihexxa/gocfg"
import (
"time"
"github.com/ihexxa/gocfg"
"github.com/ihexxa/quickshare/src/client"
)
func startTestServer(config string) *Server {
defaultCfg, err := DefaultConfig()
@ -25,3 +30,20 @@ func startTestServer(config string) *Server {
go srv.Start()
return srv
}
func waitForReady(addr string) bool {
retry := 10
setCl := client.NewSettingsClient(addr)
for retry > 0 {
_, _, errs := setCl.Health()
if len(errs) > 0 {
time.Sleep(100)
} else {
return true
}
retry--
}
return false
}