Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Lyse
Kraftwerk
Commits
e640352d
Commit
e640352d
authored
Aug 05, 2022
by
Lysander Trischler
Browse files
Implement weights in storages
parent
a796021a
Changes
9
Hide whitespace changes
Inline
Side-by-side
models/user
s
.go
→
models/user.go
View file @
e640352d
File moved
models/weight.go
0 → 100644
View file @
e640352d
package
models
import
(
"time"
)
type
WeightID
int
type
Weight
struct
{
ID
WeightID
Timestamp
time
.
Time
Grams
int
}
storage/memory/storage.go
View file @
e640352d
...
...
@@ -5,7 +5,10 @@ import (
"golang.org/x/crypto/bcrypt"
"kraftwerk/models"
"kraftwerk/storage"
"kraftwerk/utils"
"sort"
"sync"
"time"
)
// Storage implements a storage.Storage in RAM. Data are not persisted anywhere
...
...
@@ -13,14 +16,22 @@ import (
type
Storage
struct
{
mutex
sync
.
RWMutex
sequenceGenerator
utils
.
SequenceGenerator
// users maps the username to a user object. Using User values over
// pointers helps with the modification and stripping of irrelevant
// information for any operation.
users
map
[
string
]
models
.
User
// weight maps the username to all their weights in chronological order.
weights
map
[
string
][]
models
.
Weight
}
func
NewStorage
()
*
Storage
{
return
&
Storage
{
users
:
make
(
map
[
string
]
models
.
User
)}
return
&
Storage
{
users
:
make
(
map
[
string
]
models
.
User
),
weights
:
make
(
map
[
string
][]
models
.
Weight
),
}
}
func
(
s
*
Storage
)
Close
()
error
{
...
...
@@ -115,3 +126,106 @@ func (s *Storage) ChangePassword(username, password string) error {
}
return
storage
.
ErrNotFound
}
func
(
s
*
Storage
)
ListWeights
(
username
string
,
from
,
until
time
.
Time
)
([]
*
models
.
Weight
,
error
)
{
var
include
func
(
t
time
.
Time
)
bool
if
from
.
IsZero
()
{
if
until
.
IsZero
()
{
include
=
func
(
t
time
.
Time
)
bool
{
return
true
}
}
else
{
include
=
func
(
t
time
.
Time
)
bool
{
return
!
t
.
After
(
until
)
}
}
}
else
{
if
until
.
IsZero
()
{
include
=
func
(
t
time
.
Time
)
bool
{
return
!
t
.
Before
(
from
)
}
}
else
{
include
=
func
(
t
time
.
Time
)
bool
{
return
!
t
.
After
(
until
)
&&
!
t
.
Before
(
from
)
}
}
}
s
.
mutex
.
RLock
()
userWeights
,
ok
:=
s
.
weights
[
username
]
s
.
mutex
.
RUnlock
()
if
!
ok
{
if
_
,
ok
:=
s
.
users
[
username
];
!
ok
{
return
nil
,
storage
.
ErrNotFound
}
}
var
weights
[]
*
models
.
Weight
for
i
:=
range
userWeights
{
weight
:=
userWeights
[
i
]
if
include
(
weight
.
Timestamp
)
{
weights
=
append
(
weights
,
&
weight
)
}
}
sort
.
Slice
(
weights
,
func
(
i
,
j
int
)
bool
{
return
weights
[
i
]
.
Timestamp
.
Before
(
weights
[
j
]
.
Timestamp
)
})
return
weights
,
nil
}
func
(
s
*
Storage
)
GetWeight
(
username
string
,
weightID
models
.
WeightID
)
(
*
models
.
Weight
,
error
)
{
s
.
mutex
.
RLock
()
userWeights
,
ok
:=
s
.
weights
[
username
]
s
.
mutex
.
RUnlock
()
if
!
ok
{
return
nil
,
storage
.
ErrNotFound
}
for
_
,
weight
:=
range
userWeights
{
if
weight
.
ID
==
weightID
{
return
&
weight
,
nil
}
}
return
nil
,
storage
.
ErrNotFound
}
func
(
s
*
Storage
)
AddWeight
(
username
string
,
weight
*
models
.
Weight
)
error
{
weight
.
ID
=
models
.
WeightID
(
s
.
sequenceGenerator
.
Next
())
s
.
mutex
.
Lock
()
defer
s
.
mutex
.
Unlock
()
s
.
weights
[
username
]
=
append
(
s
.
weights
[
username
],
*
weight
)
return
nil
}
func
(
s
*
Storage
)
UpdateWeight
(
username
string
,
weight
*
models
.
Weight
)
error
{
s
.
mutex
.
Lock
()
defer
s
.
mutex
.
Unlock
()
weights
,
ok
:=
s
.
weights
[
username
]
if
!
ok
{
return
storage
.
ErrNotFound
}
for
i
,
w
:=
range
weights
{
if
w
.
ID
==
weight
.
ID
{
s
.
weights
[
username
][
i
]
=
*
weight
return
nil
}
}
return
storage
.
ErrNotFound
}
func
(
s
*
Storage
)
RemoveWeight
(
username
string
,
weightID
models
.
WeightID
)
error
{
s
.
mutex
.
Lock
()
defer
s
.
mutex
.
Unlock
()
weights
,
ok
:=
s
.
weights
[
username
]
if
!
ok
{
return
nil
}
for
i
,
w
:=
range
weights
{
if
w
.
ID
==
weightID
{
s
.
weights
[
username
]
=
append
(
weights
[
:
i
],
weights
[
i
+
1
:
]
...
)
return
nil
}
}
return
nil
}
storage/mock/storage.go
View file @
e640352d
...
...
@@ -5,6 +5,7 @@ import (
"kraftwerk/models"
"kraftwerk/storage/memory"
"sync"
"time"
)
// Storage implements a storage.Storage with mocking capabilities for testing
...
...
@@ -18,6 +19,8 @@ type Storage struct {
// modification will have no effect.
Users
[]
*
models
.
User
Weights
map
[
string
][]
*
models
.
Weight
MockClose
func
()
error
MockListUsers
func
()
([]
*
models
.
User
,
error
)
...
...
@@ -27,6 +30,12 @@ type Storage struct {
MockRemoveUser
func
(
username
string
)
error
MockAuthenticateUser
func
(
username
,
password
string
)
(
*
models
.
User
,
error
)
MockChangePassword
func
(
username
,
password
string
)
error
MockListWeights
func
(
username
string
,
from
,
until
time
.
Time
)
([]
*
models
.
Weight
,
error
)
MockGetWeight
func
(
username
string
,
weightID
models
.
WeightID
)
(
*
models
.
Weight
,
error
)
MockAddWeight
func
(
username
string
,
weight
*
models
.
Weight
)
error
MockUpdateWeight
func
(
username
string
,
weight
*
models
.
Weight
)
error
MockRemoveWeight
func
(
username
string
,
weightID
models
.
WeightID
)
error
}
func
(
s
*
Storage
)
init
()
{
...
...
@@ -38,6 +47,15 @@ func (s *Storage) init() {
}
}
s
.
Users
=
nil
for
username
,
weights
:=
range
s
.
Weights
{
for
_
,
weight
:=
range
weights
{
if
err
:=
s
.
mem
.
AddWeight
(
username
,
weight
);
err
!=
nil
{
panic
(
fmt
.
Errorf
(
"adding weight failed: %w"
,
err
))
}
}
}
s
.
Weights
=
nil
})
}
...
...
@@ -104,3 +122,43 @@ func (s *Storage) ChangePassword(username, password string) error {
}
return
s
.
mem
.
ChangePassword
(
username
,
password
)
}
func
(
s
*
Storage
)
ListWeights
(
username
string
,
from
,
until
time
.
Time
)
([]
*
models
.
Weight
,
error
)
{
s
.
init
()
if
s
.
MockListWeights
!=
nil
{
return
s
.
MockListWeights
(
username
,
from
,
until
)
}
return
s
.
mem
.
ListWeights
(
username
,
from
,
until
)
}
func
(
s
*
Storage
)
GetWeight
(
username
string
,
weightID
models
.
WeightID
)
(
*
models
.
Weight
,
error
)
{
s
.
init
()
if
s
.
MockGetWeight
!=
nil
{
return
s
.
MockGetWeight
(
username
,
weightID
)
}
return
s
.
mem
.
GetWeight
(
username
,
weightID
)
}
func
(
s
*
Storage
)
AddWeight
(
username
string
,
weight
*
models
.
Weight
)
error
{
s
.
init
()
if
s
.
MockAddWeight
!=
nil
{
return
s
.
MockAddWeight
(
username
,
weight
)
}
return
s
.
mem
.
AddWeight
(
username
,
weight
)
}
func
(
s
*
Storage
)
UpdateWeight
(
username
string
,
weight
*
models
.
Weight
)
error
{
s
.
init
()
if
s
.
MockUpdateWeight
!=
nil
{
return
s
.
MockUpdateWeight
(
username
,
weight
)
}
return
s
.
mem
.
UpdateWeight
(
username
,
weight
)
}
func
(
s
*
Storage
)
RemoveWeight
(
username
string
,
weightID
models
.
WeightID
)
error
{
s
.
init
()
if
s
.
MockRemoveWeight
!=
nil
{
return
s
.
MockRemoveWeight
(
username
,
weightID
)
}
return
s
.
mem
.
RemoveWeight
(
username
,
weightID
)
}
storage/mock/storage_test.go
View file @
e640352d
...
...
@@ -8,6 +8,7 @@ import (
"kraftwerk/storage"
"reflect"
"testing"
"time"
)
var
Eugen
=
testusers
.
Eugen
...
...
@@ -24,6 +25,15 @@ var methods map[string]method = map[string]method{
"RemoveUser"
:
func
(
store
storage
.
Storage
)
{
_
=
store
.
RemoveUser
(
"username"
)
},
"AuthenticateUser"
:
func
(
store
storage
.
Storage
)
{
_
,
_
=
store
.
AuthenticateUser
(
"username"
,
"password"
)
},
"ChangePassword"
:
func
(
store
storage
.
Storage
)
{
_
=
store
.
ChangePassword
(
"username"
,
"password"
)
},
"ListWeights"
:
func
(
store
storage
.
Storage
)
{
_
,
_
=
store
.
ListWeights
(
"username"
,
time
.
Time
{},
time
.
Time
{})
},
"GetWeight"
:
func
(
store
storage
.
Storage
)
{
_
,
_
=
store
.
GetWeight
(
"username"
,
models
.
WeightID
(
1
))
},
"AddWeight"
:
func
(
store
storage
.
Storage
)
{
_
=
store
.
AddWeight
(
"username"
,
&
models
.
Weight
{
Timestamp
:
time
.
Now
(),
Grams
:
71
_000
})
},
"UpdateWeight"
:
func
(
store
storage
.
Storage
)
{
_
=
store
.
UpdateWeight
(
"username"
,
&
models
.
Weight
{
ID
:
models
.
WeightID
(
1
),
Timestamp
:
time
.
Now
(),
Grams
:
72
_000
})
},
"RemoveWeight"
:
func
(
store
storage
.
Storage
)
{
_
=
store
.
RemoveWeight
(
"usernama"
,
models
.
WeightID
(
1
))
},
}
func
TestTestSetup
(
t
*
testing
.
T
)
{
...
...
storage/sqlite/storage.go
View file @
e640352d
...
...
@@ -11,6 +11,7 @@ import (
kraftwerkVersion
"kraftwerk/version"
sqlite3
"modernc.org/sqlite"
sqlite3Lib
"modernc.org/sqlite/lib"
"time"
)
var
ErrNotImplemented
=
errors
.
New
(
"not implemented"
)
...
...
@@ -69,6 +70,22 @@ var schemaPatches []schemaPatch = []schemaPatch{
VALUES(0, 1)`
,
},
},
{
schemaVersion
{
0
,
2
},
[]
string
{
` CREATE TABLE weights (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
username VARCHAR(256) NOT NULL,
timestamp TIMESTAMP NOT NULL,
grams INTEGER NOT NULL,
FOREIGN KEY (username)
REFERENCES users (username)
)`
,
` UPDATE metadata
SET db_schema_version_major = 0, db_schema_version_minor = 2`
,
},
},
// Schema changes must use the version number of the release that
// introduced them. Also the schema patches have to be sorted by schema
...
...
@@ -77,11 +94,15 @@ var schemaPatches []schemaPatch = []schemaPatch{
}
func
NewStorage
(
cfg
Config
,
logger
logrus
.
FieldLogger
)
(
*
Storage
,
error
)
{
db
,
err
:=
sql
.
Open
(
"sqlite"
,
cfg
.
Filename
)
db
,
err
:=
sql
.
Open
(
"sqlite"
,
cfg
.
Filename
+
"?_time_format=sqlite"
)
if
err
!=
nil
{
return
nil
,
err
}
if
_
,
err
:=
db
.
Exec
(
`PRAGMA foreign_keys = ON`
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"enabling foreign keys failed: %w"
,
err
)
}
store
:=
&
Storage
{
db
:
db
}
dbVersion
:=
store
.
getSchemaVersion
()
...
...
@@ -247,3 +268,109 @@ func (s *Storage) ChangePassword(username, password string) error {
}
return
nil
}
func
(
s
*
Storage
)
ListWeights
(
username
string
,
from
,
until
time
.
Time
)
([]
*
models
.
Weight
,
error
)
{
args
:=
[]
interface
{}{
username
}
query
:=
`
SELECT id, timestamp, grams
FROM weights
WHERE username = ?`
if
!
from
.
IsZero
()
{
query
+=
` AND ? <= timestamp`
args
=
append
(
args
,
from
)
}
if
!
until
.
IsZero
()
{
query
+=
` AND timestamp <= ?`
args
=
append
(
args
,
until
)
}
query
+=
` ORDER BY timestamp`
rows
,
err
:=
s
.
db
.
Query
(
query
,
args
...
)
if
err
!=
nil
{
return
nil
,
err
}
defer
rows
.
Close
()
var
weights
[]
*
models
.
Weight
for
rows
.
Next
()
{
weight
:=
&
models
.
Weight
{}
if
err
:=
rows
.
Scan
(
&
weight
.
ID
,
&
weight
.
Timestamp
,
&
weight
.
Grams
);
err
!=
nil
{
return
nil
,
err
}
weights
=
append
(
weights
,
weight
)
}
if
len
(
weights
)
==
0
{
row
:=
s
.
db
.
QueryRow
(
`
SELECT 1
FROM users
WHERE username = ?`
,
username
)
var
ignored
int
if
err
:=
row
.
Scan
(
&
ignored
);
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
return
nil
,
storage
.
ErrNotFound
}
return
nil
,
err
}
}
return
weights
,
nil
}
func
(
s
*
Storage
)
GetWeight
(
username
string
,
weightID
models
.
WeightID
)
(
*
models
.
Weight
,
error
)
{
row
:=
s
.
db
.
QueryRow
(
`
SELECT timestamp, grams
FROM weights
WHERE username = ? AND id = ?`
,
username
,
weightID
)
weight
:=
&
models
.
Weight
{
ID
:
weightID
}
if
err
:=
row
.
Scan
(
&
weight
.
Timestamp
,
&
weight
.
Grams
);
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
return
nil
,
storage
.
ErrNotFound
}
return
nil
,
err
}
return
weight
,
nil
}
func
(
s
*
Storage
)
AddWeight
(
username
string
,
weight
*
models
.
Weight
)
error
{
result
,
err
:=
s
.
db
.
Exec
(
`
INSERT INTO weights (username, timestamp, grams)
VALUES (?, ?, ?)`
,
username
,
weight
.
Timestamp
,
weight
.
Grams
)
if
err
!=
nil
{
return
err
}
id
,
err
:=
result
.
LastInsertId
()
if
err
!=
nil
{
return
err
}
weight
.
ID
=
models
.
WeightID
(
id
)
return
nil
}
func
(
s
*
Storage
)
UpdateWeight
(
username
string
,
weight
*
models
.
Weight
)
error
{
result
,
err
:=
s
.
db
.
Exec
(
`
UPDATE weights
SET timestamp = ?, grams = ?
WHERE username = ? AND id = ?`
,
weight
.
Timestamp
,
weight
.
Grams
,
username
,
weight
.
ID
)
if
err
!=
nil
{
return
err
}
rowsAffected
,
err
:=
result
.
RowsAffected
()
if
err
!=
nil
{
return
err
}
if
rowsAffected
!=
1
{
return
storage
.
ErrNotFound
}
return
nil
}
func
(
s
*
Storage
)
RemoveWeight
(
username
string
,
weightID
models
.
WeightID
)
error
{
_
,
err
:=
s
.
db
.
Exec
(
`
DELETE FROM weights
WHERE username = ? AND id = ?`
,
username
,
weightID
)
if
err
!=
nil
{
return
err
}
return
nil
}
storage/sqlite/storage_test.go
View file @
e640352d
...
...
@@ -250,7 +250,7 @@ func assertTablesExist(t *testing.T, store *Storage, additionalTableNames ...str
actualTableNames
=
append
(
actualTableNames
,
name
)
}
expectedTableNames
:=
append
(
additionalTableNames
,
"users"
,
"metadata"
)
expectedTableNames
:=
append
(
additionalTableNames
,
"users"
,
"metadata"
,
"weights"
)
assert
.
ElementsMatch
(
t
,
expectedTableNames
,
actualTableNames
,
"tables names do not match"
)
}
...
...
storage/storage.go
View file @
e640352d
...
...
@@ -6,6 +6,7 @@ import (
"github.com/mitchellh/mapstructure"
"gopkg.in/yaml.v3"
"kraftwerk/models"
"time"
)
var
(
...
...
@@ -52,6 +53,19 @@ type Storage interface {
// user does not exist, storage.ErrNotFound is returned. Other errors are
// of technical reason.
ChangePassword
(
username
,
password
string
)
error
ListWeights
(
username
string
,
from
,
until
time
.
Time
)
([]
*
models
.
Weight
,
error
)
GetWeight
(
username
string
,
weightID
models
.
WeightID
)
(
*
models
.
Weight
,
error
)
// AddWeight adds a weight for a user. The weight's ID must be empty and
// will be set by the storage implemenation, so the caller then knows the
// generated ID.
AddWeight
(
username
string
,
weight
*
models
.
Weight
)
error
UpdateWeight
(
username
string
,
weight
*
models
.
Weight
)
error
RemoveWeight
(
username
string
,
weightID
models
.
WeightID
)
error
}
type
Config
struct
{
...
...
storage/test/conformance_test.go
View file @
e640352d
...
...
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"kraftwerk/models"
"kraftwerk/models/testusers"
"kraftwerk/storage"
...
...
@@ -15,6 +16,7 @@ import (
"kraftwerk/storage/sqlite"
"os"
"testing"
"time"
)
var
(
...
...
@@ -22,6 +24,17 @@ var (
EugenWithPassword
=
testusers
.
EugenWithPassword
Karla
=
testusers
.
Karla
KarlaWithPassword
=
testusers
.
KarlaWithPassword
CEST
,
_
=
time
.
LoadLocation
(
"Europe/Berlin"
)
Aug_02_12_54_20_297_CEST
=
time
.
Date
(
2022
,
time
.
August
,
2
,
12
,
54
,
20
,
297
,
CEST
)
Aug_03_22_21_03_654_CEST
=
time
.
Date
(
2022
,
time
.
August
,
3
,
22
,
21
,
3
,
654
,
CEST
)
Aug_03_22_21_03_655_CEST
=
time
.
Date
(
2022
,
time
.
August
,
3
,
22
,
21
,
3
,
655
,
CEST
)
Aug_03_22_21_03_656_CEST
=
time
.
Date
(
2022
,
time
.
August
,
3
,
22
,
21
,
3
,
656
,
CEST
)
Aug_04_08_07_00_937_CEST
=
time
.
Date
(
2022
,
time
.
August
,
4
,
8
,
7
,
0
,
937
,
CEST
)
Aug_04_08_07_00_938_CEST
=
time
.
Date
(
2022
,
time
.
August
,
4
,
8
,
7
,
0
,
938
,
CEST
)
Aug_04_08_07_00_939_CEST
=
time
.
Date
(
2022
,
time
.
August
,
4
,
8
,
7
,
0
,
939
,
CEST
)
Aug_05_17_20_00_000_CEST
=
time
.
Date
(
2022
,
time
.
August
,
5
,
17
,
0
,
0
,
0
,
CEST
)
)
type
storageImplementation
struct
{
...
...
@@ -428,3 +441,467 @@ func TestChangePassword(t *testing.T) {
}
}
}
func
TestListWeights
(
t
*
testing
.
T
)
{
testCases
:=
[]
struct
{
name
string
setup
func
(
t
*
testing
.
T
,
store
storage
.
Storage
)
username
string
from
,
until
time
.
Time
expectedError
error
expectedWeights
[]
*
models
.
Weight
}{
{
name
:
"when user does not exist then return ErrNotFound"
,
username
:
"eugen"
,
expectedError
:
storage
.
ErrNotFound
,
},
{
name
:
"when user exists but has no weights then return nil slice"
,
username
:
"eugen"
,
setup
:
func
(
t
*
testing
.
T
,
store
storage
.
Storage
)
{
require
.
NoError
(
t
,
store
.
AddUser
(
EugenWithPassword
()))
},
expectedWeights
:
nil
,
},
{
name
:
"when from and until are zero then return all weights sorted by ascending timestamp"
,
username
:
"eugen"
,
setup
:
func
(
t
*
testing
.
T
,
store
storage
.
Storage
)
{
require
.
NoError
(
t
,
store
.
AddUser
(
EugenWithPassword
()))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_654_CEST
,
Grams
:
72
_000
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_02_12_54_20_297_CEST
,
Grams
:
73
_500
}))
},
expectedWeights
:
[]
*
models
.
Weight
{
{
Timestamp
:
Aug_02_12_54_20_297_CEST
,
Grams
:
73
_500
},
{
Timestamp
:
Aug_03_22_21_03_654_CEST
,
Grams
:
72
_000
},
},
},
{
name
:
"when from is zero and until is non-zero then return all weights up to until sorted by ascending timestamp"
,
username
:
"eugen"
,
until
:
Aug_03_22_21_03_655_CEST
,
setup
:
func
(
t
*
testing
.
T
,
store
storage
.
Storage
)
{
require
.
NoError
(
t
,
store
.
AddUser
(
EugenWithPassword
()))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_656_CEST
,
Grams
:
72
_550
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_655_CEST
,
Grams
:
72
_540
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_654_CEST
,
Grams
:
72
_000
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_02_12_54_20_297_CEST
,
Grams
:
73
_500
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_05_17_20_00_000_CEST
,
Grams
:
74
_700
}))
},
expectedWeights
:
[]
*
models
.
Weight
{
{
Timestamp
:
Aug_02_12_54_20_297_CEST
,
Grams
:
73
_500
},
{
Timestamp
:
Aug_03_22_21_03_654_CEST
,
Grams
:
72
_000
},
{
Timestamp
:
Aug_03_22_21_03_655_CEST
,
Grams
:
72
_540
},
},
},
{
name
:
"when from is non-zero and until is zero then return all weights from from on sorted by ascending timestamp"
,
username
:
"eugen"
,
from
:
Aug_03_22_21_03_655_CEST
,
setup
:
func
(
t
*
testing
.
T
,
store
storage
.
Storage
)
{
require
.
NoError
(
t
,
store
.
AddUser
(
EugenWithPassword
()))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_656_CEST
,
Grams
:
72
_550
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_655_CEST
,
Grams
:
72
_540
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_654_CEST
,
Grams
:
72
_000
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_02_12_54_20_297_CEST
,
Grams
:
73
_500
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_05_17_20_00_000_CEST
,
Grams
:
74
_700
}))
},
expectedWeights
:
[]
*
models
.
Weight
{
{
Timestamp
:
Aug_03_22_21_03_655_CEST
,
Grams
:
72
_540
},
{
Timestamp
:
Aug_03_22_21_03_656_CEST
,
Grams
:
72
_550
},
{
Timestamp
:
Aug_05_17_20_00_000_CEST
,
Grams
:
74
_700
},
},
},
{
name
:
"when from and until are non-zero then return all weights from from on up to until sorted by ascending timestamp"
,
username
:
"eugen"
,
from
:
Aug_03_22_21_03_655_CEST
,
until
:
Aug_04_08_07_00_938_CEST
,
setup
:
func
(
t
*
testing
.
T
,
store
storage
.
Storage
)
{
require
.
NoError
(
t
,
store
.
AddUser
(
EugenWithPassword
()))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_656_CEST
,
Grams
:
72
_550
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_655_CEST
,
Grams
:
72
_540
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_03_22_21_03_654_CEST
,
Grams
:
72
_000
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_02_12_54_20_297_CEST
,
Grams
:
73
_500
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_04_08_07_00_939_CEST
,
Grams
:
74
_900
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_04_08_07_00_938_CEST
,
Grams
:
74
_800
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_04_08_07_00_937_CEST
,
Grams
:
74
_600
}))
require
.
NoError
(
t
,
store
.
AddWeight
(
"eugen"
,
&
models
.
Weight
{
Timestamp
:
Aug_05_17_20_00_000_CEST
,
Grams
:
74
_700
}))
},
expectedWeights
:
[]
*
models
.
Weight
{
{
Timestamp
:
Aug_03_22_21_03_655_CEST
,
Grams
:
72
_540
},
{
Timestamp
:
Aug_03_22_21_03_656_CEST
,
Grams
:
72
_550
},
{
Timestamp
:
Aug_04_08_07_00_937_CEST
,
Grams
:
74
_600
},
{
Timestamp
:
Aug_04_08_07_00_938_CEST
,
Grams
:
74
_800
},
},
},
}
for
_
,
impl
:=
range
storageImplementations
{
for
_
,
testCase
:=
range
testCases
{
t
.
Run
(
fmt
.
Sprintf
(
"%s - %s"
,
impl
.
name
,
testCase
.
name
),
func
(
t
*
testing
.
T
)
{
store
:=
impl
.
setupStorage
(
t
)