more tests and db fixes

This commit is contained in:
2023-03-26 13:29:33 +02:00
parent 3964ffc7cb
commit 0af31bb0d9
10 changed files with 205 additions and 28 deletions

View File

@@ -195,7 +195,7 @@ Upload:
| expire | string | when the upload has to expire, either "asap" or a Duration using numbers and the letters d,h,m,s (days,hours,minutes,seconds), e.g. 2d4h30m |
| file | string | filename after uploading, this is what a consumer gets when downloading it |
| members | array of strings | list of the original filenames |
| uploaded | timestamp | time of object creation |
| created | timestamp | time of object creation |
| context | string | the API context the upload has been created under |
| url | string | the download URL |

View File

@@ -42,7 +42,7 @@ func DeleteExpiredUploads(conf *cfg.Config, db *Db) error {
return fmt.Errorf("unable to unmarshal json: %s", err)
}
if IsExpired(conf, upload.Uploaded.Time, upload.Expire) {
if IsExpired(conf, upload.Created.Time, upload.Expire) {
if err := bucket.Delete([]byte(id)); err != nil {
return nil
}

View File

@@ -102,7 +102,7 @@ func (db *Db) Delete(apicontext string, id string) error {
return err
}
func (db *Db) UploadsList(apicontext string, filter string, t int) (*common.Response, error) {
func (db *Db) List(apicontext string, filter string, t int) (*common.Response, error) {
response := &common.Response{}
err := db.bolt.View(func(tx *bolt.Tx) error {
@@ -119,12 +119,12 @@ func (db *Db) UploadsList(apicontext string, filter string, t int) (*common.Resp
var entryContext string
if t == common.TypeUpload {
entryContext = entry.(common.Upload).Context
entryContext = entry.(*common.Upload).Context
} else {
entryContext = entry.(common.Form).Context
entryContext = entry.(*common.Form).Context
}
fmt.Printf("apicontext: %s, filter: %s\n", apicontext, filter)
//fmt.Printf("apicontext: %s, filter: %s\n", apicontext, filter)
if apicontext != "" && db.cfg.Super != apicontext {
// only return the uploads for this context
if apicontext == entryContext {
@@ -150,6 +150,7 @@ func (db *Db) UploadsList(apicontext string, filter string, t int) (*common.Resp
}
// we only return one obj here, but could return more later
// FIXME: turn the id into a filter and call (Uploads|Forms)List(), same code!
func (db *Db) Get(apicontext string, id string, t int) (*common.Response, error) {
response := &common.Response{}

View File

@@ -18,9 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package api
import (
//"github.com/alecthomas/repr"
"github.com/maxatome/go-testdeep/td"
"github.com/tlinden/cenophane/cfg"
"github.com/tlinden/cenophane/common"
"os"
"testing"
"time"
)
func finalize(db *Db) {
@@ -35,7 +39,7 @@ func finalize(db *Db) {
func TestNew(t *testing.T) {
var tests = []struct {
name string
file string
dbfile string
wantfail bool
}{
{"opennew", "test.db", false},
@@ -43,7 +47,7 @@ func TestNew(t *testing.T) {
}
for _, tt := range tests {
c := &cfg.Config{DbFile: tt.file}
c := &cfg.Config{DbFile: tt.dbfile}
t.Run(tt.name, func(t *testing.T) {
db, err := NewDb(c)
defer finalize(db)
@@ -57,3 +61,171 @@ func TestNew(t *testing.T) {
})
}
}
const timeformat string = "2006-01-02T15:04:05.000Z"
var dbtests = []struct {
name string
dbfile string
wantfail bool
id string
context string
ts string
filter string
upload common.Upload
form common.Form
}{
{
"upload", "test.db", false, "1", "foo",
"2023-03-10T11:45:00.000Z", "",
common.Upload{
Id: "1", Expire: "asap", File: "none", Context: "foo",
Created: common.Timestamp{}},
common.Form{},
},
{
"form", "test.db", false, "2", "foo",
"2023-03-10T11:45:00.000Z", "",
common.Upload{},
common.Form{
Id: "1", Expire: "asap", Description: "none", Context: "foo",
Created: common.Timestamp{}},
},
}
/*
We need to test the whole Db operation in one run, because it
doesn't work well if using a global Db.
*/
func TestDboperation(t *testing.T) {
for _, tt := range dbtests {
c := &cfg.Config{DbFile: tt.dbfile}
t.Run(tt.name, func(t *testing.T) {
// create new bbolt db
db, err := NewDb(c)
defer finalize(db)
if err != nil {
t.Errorf("Could not open new DB: " + err.Error())
}
if tt.upload.Id != "" {
// set ts
ts, err := time.Parse(timeformat, tt.ts)
tt.upload.Created = common.Timestamp{Time: ts}
// create new upload db object
err = db.Insert(tt.id, tt.upload)
if err != nil {
t.Errorf("Could not insert new upload object: " + err.Error())
}
// fetch it
response, err := db.Get(tt.context, tt.id, common.TypeUpload)
if err != nil {
t.Errorf("Could not fetch upload object: " + err.Error())
}
// is it there?
if len(response.Uploads) != 1 {
t.Errorf("db.Get() did not return an upload obj")
}
// compare times
if !tt.upload.Created.Time.Equal(response.Uploads[0].Created.Time) {
t.Errorf("Timestamps don't match!\ngot: %s\nexp: %s\n",
response.Uploads[0].Created, tt.upload.Created)
}
// equal them artificially, because otherwise td will
// fail because of time.Time.wall+ext, or TZ is missing
response.Uploads[0].Created = tt.upload.Created
// compare
td.Cmp(t, response.Uploads[0], &tt.upload, tt.name)
// fetch list
response, err = db.List(tt.context, tt.filter, common.TypeUpload)
if err != nil {
t.Errorf("Could not fetch uploads list: " + err.Error())
}
// is it there?
if len(response.Uploads) != 1 {
t.Errorf("db.List() did not return upload obj[s]")
}
// delete
err = db.Delete(tt.context, tt.id)
if err != nil {
t.Errorf("Could not delete upload obj: " + err.Error())
}
// fetch again, shall return empty
response, err = db.Get(tt.context, tt.id, common.TypeUpload)
if err == nil {
t.Errorf("Could fetch upload object again although we deleted it")
}
}
if tt.form.Id != "" {
// set ts
ts, err := time.Parse(timeformat, tt.ts)
tt.form.Created = common.Timestamp{Time: ts}
// create new form db object
err = db.Insert(tt.id, tt.form)
if err != nil {
t.Errorf("Could not insert new form object: " + err.Error())
}
// fetch it
response, err := db.Get(tt.context, tt.id, common.TypeForm)
if err != nil {
t.Errorf("Could not fetch form object: " + err.Error())
}
// is it there?
if len(response.Forms) != 1 {
t.Errorf("db.Get() did not return an form obj")
}
// compare times
if !tt.form.Created.Time.Equal(response.Forms[0].Created.Time) {
t.Errorf("Timestamps don't match!\ngot: %s\nexp: %s\n",
response.Forms[0].Created, tt.form.Created)
}
// equal them artificially, because otherwise td will
// fail because of time.Time.wall+ext, or TZ is missing
response.Forms[0].Created = tt.form.Created
// compare
td.Cmp(t, response.Forms[0], &tt.form, tt.name)
// fetch list
response, err = db.List(tt.context, tt.filter, common.TypeForm)
if err != nil {
t.Errorf("Could not fetch forms list: " + err.Error())
}
// is it there?
if len(response.Forms) != 1 {
t.Errorf("db.FormsList() did not return form obj[s]")
}
// delete
err = db.Delete(tt.context, tt.id)
if err != nil {
t.Errorf("Could not delete form obj: " + err.Error())
}
// fetch again, shall return empty
response, err = db.Get(tt.context, tt.id, common.TypeForm)
if err == nil {
t.Errorf("Could fetch form object again although we deleted it")
}
}
})
}
}

View File

@@ -62,7 +62,7 @@ func UploadPost(c *fiber.Ctx, cfg *cfg.Config, db *Db) error {
}
// init upload obj
entry := &common.Upload{Id: id, Uploaded: common.Timestamp{Time: time.Now()}}
entry := &common.Upload{Id: id, Created: common.Timestamp{Time: time.Now()}}
// retrieve the API Context name from the session
apicontext, err := GetApicontext(c)
@@ -233,7 +233,7 @@ func UploadsList(c *fiber.Ctx, cfg *cfg.Config, db *Db) error {
}
// get list
uploads, err := db.UploadsList(apicontext, filter, common.TypeUpload)
uploads, err := db.List(apicontext, filter, common.TypeUpload)
if err != nil {
return JsonStatus(c, fiber.StatusForbidden,
"Unable to list uploads: "+err.Error())

View File

@@ -36,13 +36,13 @@ type Dbentry interface {
}
type Upload struct {
Id string `json:"id"`
Expire string `json:"expire"`
File string `json:"file"` // final filename (visible to the downloader)
Members []string `json:"members"` // contains multiple files, so File is an archive
Uploaded Timestamp `json:"uploaded"`
Context string `json:"context"`
Url string `json:"url"`
Id string `json:"id"`
Expire string `json:"expire"`
File string `json:"file"` // final filename (visible to the downloader)
Members []string `json:"members"` // contains multiple files, so File is an archive
Created Timestamp `json:"uploaded"`
Context string `json:"context"`
Url string `json:"url"`
}
// this one is also used for marshalling to the client

2
go.mod
View File

@@ -19,6 +19,7 @@ require (
require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/klauspost/compress v1.15.9 // indirect
@@ -26,6 +27,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/maxatome/go-testdeep v1.13.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect

2
go.sum
View File

@@ -35,6 +35,8 @@ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPn
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/maxatome/go-testdeep v1.13.0 h1:EBmRelH7MhMfPvA+0kXAeOeJUXn3mzul5NmvjLDcQZI=
github.com/maxatome/go-testdeep v1.13.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=

View File

@@ -111,7 +111,7 @@ func TestUploadFiles(t *testing.T) {
name: "upload-file",
apikey: "token",
wantfail: false,
route: "/uploads/",
route: "/uploads",
sendcode: 200,
sendjson: `{"success": true}`,
files: []string{"../t/t1"}, // pwd is lib/ !
@@ -121,7 +121,7 @@ func TestUploadFiles(t *testing.T) {
name: "upload-dir",
apikey: "token",
wantfail: false,
route: "/uploads/",
route: "/uploads",
sendcode: 200,
sendjson: `{"success": true}`,
files: []string{"../t"}, // pwd is lib/ !
@@ -131,7 +131,7 @@ func TestUploadFiles(t *testing.T) {
name: "upload-catch-nonexistent-file",
apikey: "token",
wantfail: true,
route: "/uploads/",
route: "/uploads",
sendcode: 200,
sendjson: `{"success": false}`,
files: []string{"../t/none"},
@@ -141,7 +141,7 @@ func TestUploadFiles(t *testing.T) {
name: "upload-catch-no-access",
apikey: "token",
wantfail: true,
route: "/uploads/",
route: "/uploads",
sendcode: 403,
sendjson: `{"success": false}`,
files: []string{"../t/t1"},
@@ -151,7 +151,7 @@ func TestUploadFiles(t *testing.T) {
name: "upload-check-output",
apikey: "token",
wantfail: false,
route: "/uploads/",
route: "/uploads",
sendcode: 200,
sendjson: `{"uploads":[
{
@@ -266,7 +266,7 @@ func TestDescribe(t *testing.T) {
sendjson: listing,
files: []string{"cc2c965a"},
method: "GET",
expect: `Uploaded: 2023-03-21 12:06:54.890501888`,
expect: `Created: 2023-03-21 12:06:54.890501888`,
},
{
name: "describe-catch-empty-json",
@@ -292,7 +292,7 @@ func TestDescribe(t *testing.T) {
for _, unit := range tests {
var w bytes.Buffer
unit.route += unit.files[0] + "/"
unit.route += unit.files[0]
Intercept(unit)
Check(t, unit, &w, Describe(&w, conf, unit.files))
}

View File

@@ -77,11 +77,11 @@ func WriteExtended(w io.Writer, response *common.Response) {
// we shall only have 1 element, however, if we ever support more, here we go
for _, entry := range response.Uploads {
expire := prepareExpire(entry.Expire, entry.Uploaded)
expire := prepareExpire(entry.Expire, entry.Created)
fmt.Fprintf(w, format, "Id", entry.Id)
fmt.Fprintf(w, format, "Expire", expire)
fmt.Fprintf(w, format, "Context", entry.Context)
fmt.Fprintf(w, format, "Uploaded", entry.Uploaded)
fmt.Fprintf(w, format, "Created", entry.Created)
fmt.Fprintf(w, format, "Filename", entry.File)
fmt.Fprintf(w, format, "Url", entry.Url)
fmt.Fprintln(w)
@@ -120,11 +120,11 @@ func UploadsRespondTable(w io.Writer, resp *req.Response) error {
data := [][]string{}
for _, entry := range response.Uploads {
data = append(data, []string{
entry.Id, entry.Expire, entry.Context, entry.Uploaded.Format("2006-01-02 15:04:05"),
entry.Id, entry.Expire, entry.Context, entry.Created.Format("2006-01-02 15:04:05"),
})
}
WriteTable(w, []string{"ID", "EXPIRE", "CONTEXT", "UPLOADED"}, data)
WriteTable(w, []string{"ID", "EXPIRE", "CONTEXT", "CREATED"}, data)
return nil
}