mirror of
https://codeberg.org/scip/ephemerup.git
synced 2025-12-16 20:20:58 +01:00
more tests and db fixes
This commit is contained in:
@@ -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 |
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{}
|
||||
|
||||
|
||||
176
api/db_test.go
176
api/db_test.go
@@ -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")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
2
go.mod
@@ -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
2
go.sum
@@ -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=
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user