[#116] node: Improve shard/engine construction in tests #190
No reviewers
Labels
No labels
P0
P1
P2
P3
badger
frostfs-adm
frostfs-cli
frostfs-ir
frostfs-lens
frostfs-node
good first issue
triage
Infrastructure
blocked
bug
config
discussion
documentation
duplicate
enhancement
go
help wanted
internal
invalid
kludge
observability
perfomance
question
refactoring
wontfix
No milestone
No project
No assignees
5 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: TrueCloudLab/frostfs-node#190
Loading…
Reference in a new issue
No description provided.
Delete branch "aarifullin/frostfs-node:feature/116-engine_constructor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Signed-off-by: Airat Arifullin a.arifullin@yadro.com
@ -77,0 +56,4 @@
).
WithShardsNumFromOpts(t, 2, func(id int) []shard.Option {
storages, smallFileStorage, largeFileStorage := newTestStorages(filepath.Join(dir, strconv.Itoa(id)), errSmallSize)
testShards[id] = &testShard{
I would be glad to take any suggestion about
testShards
initialization. I tried to use intoducedWithShardsNumFromOpts
but after rebase I was obliged to apply this hack withtestShards
.It's still possible to invoke
enginge.AddShard
out oftestNewEngine
@ -332,2 +322,2 @@
)
require.NoError(t, err)
te := testNewEngine(t).
WithShardsNumFromOptsOverDefault(t, num, func(id int) []shard.Option {
Maybe just
WithShardsAdditionalOpts(func(int) []shard.Option)
?@ -79,0 +79,4 @@
type testEngineWrapper struct {
engine *StorageEngine
dir string
shardIDs []*shard.ID
We already have
shards
in the engine itself, duplicating them here can lead to unexpected behaviour when writing some concurrent tests in future. Can we return them from a method? Or does this field has some special meaning?This rather has supportive meaning. It is needed to keep shardIDs in the same order as they are added to engine. Also this allows to not iterate over engine shards and get shardIDs immediatly
@ -79,0 +80,4 @@
engine *StorageEngine
dir string
shardIDs []*shard.ID
objects []*objectSDK.Object
Feels unnecessary here, what value does it provide?
Removed it
@ -79,0 +84,4 @@
isRunning bool
}
func (te *testEngineWrapper) Engine() *StorageEngine {
Not worth a method IMO,
.engine
is just as fine andEngine()
makes me wondering how is it different from theRunEngine()
@ -93,2 +160,3 @@
}
return engine
func (te *testEngineWrapper) RunEngine(t testing.TB) *testEngineWrapper {
I prefer to have a separate method for this, not using this as an option. It affects control flow and is different from creating something.
I got your point but I wouldn't say that
RunEngine
is the option. It rather consecutively changes the eninge's state and that's why I implemented this with method chaining (without options pattern). I'll get it out@ -95,0 +167,4 @@
return te
}
func (te *testEngineWrapper) WithShardObject(t testing.TB, generateObject func() *objectSDK.Object) *testEngineWrapper {
It feels like a helper, not an option.
I think creating engine, then opening on it on a separate line, then putting objects to it is more readable.
Removed
@ -95,0 +169,4 @@
func (te *testEngineWrapper) WithShardObject(t testing.TB, generateObject func() *objectSDK.Object) *testEngineWrapper {
require.True(t, te.isRunning, "engine must be run up before putting objects in shards")
require.NotEmpty(t, te.shardIDs, "there must be at least one shard")
Can we prevent this by construction?
num must be greater than 0
?It is no longer actual
@ -74,3 +52,1 @@
smallFileStorage: smallFileStorage,
largeFileStorage: largeFileStorage,
}
te := testNewEngine(t).
Can
testNewEngine
just acceptengine
opts as a varargs?0c38468fbb
to1b874919e5
1b874919e5
to2d2ecf52fe
@ -338,4 +342,3 @@
require.Equal(t, num, len(e.shards))
require.Equal(t, num, len(e.shardPools))
require.NoError(t, e.Open())
Why move these lines?
My fault. Removed them because of
RunEngine(t)
, then removed this method and got these requires back@ -7,7 +7,6 @@ import (
"os"
"path/filepath"
"strconv"
"sync/atomic"
Please, rebase on master.
@ -95,0 +131,4 @@
func (te *testEngineWrapper) WithShardsNumAdditionalOpts(t testing.TB, num int, shardOpts func(id int) []shard.Option) *testEngineWrapper {
for i := 0; i < num; i++ {
defaultOpts := testDefaultShardOptions(t, i)
opts := append(shardOpts(i), defaultOpts...)
If we want our function to override defaults,
defaultOpts
should come first.Just a question, why have you decided to go with
(e *engine) WithX(t) *engine
instead of(e *engine) setX(t)
?Fair point. I changed implementation few times: initially this wasn't method chaining but
testNewEngine(t, With...)
. I'll fix it2d2ecf52fe
to2c8002e6ed
Just my opinion. If something is required, it is better to create a
New
method, which explicitly pass the required dependencies. AllWithXXX
&SetXXX
methods should be used only for parameters that have default values.That is still true for engine (
testNewEngine(t, WithShardPoolSize(1))
).But I don't agree about
SetXXX
. User should (and AFAICS this was initally implied) to set shards explicitly - there are no cases where shards can be set implicitly as default@ -45,3 +45,3 @@
s2 := testNewShard(t, 2)
e := testNewEngineWithShards(t, s1, s2)
e := testNewEngine(t).SetInitializedShards(t, s1, s2).engine
do we have a getter for
engine
(do not see it)? if no, exported setters look useless to me cause no external package needstestEngineWrapper
but also no external package can get nestedengine
Good point. I've made
setXXX
methods internal2c8002e6ed
to21f7aae37f