[#116] node: Improve shard/engine construction in tests #190

Merged
fyrchik merged 1 commits from aarifullin/frostfs-node:feature/116-engine_constructor into master 2023-04-05 14:36:41 +00:00
Collaborator
  • Introduce testEngineWrapper that can be constructed with different options

Signed-off-by: Airat Arifullin a.arifullin@yadro.com

* Introduce testEngineWrapper that can be constructed with different options Signed-off-by: Airat Arifullin a.arifullin@yadro.com
aarifullin added the
frostfs-node
label 2023-03-30 12:55:47 +00:00
aarifullin reviewed 2023-03-30 13:01:10 +00:00
@ -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{
Poster
Collaborator

I would be glad to take any suggestion about testShards initialization. I tried to use intoduced WithShardsNumFromOpts but after rebase I was obliged to apply this hack with testShards.
It's still possible to invoke enginge.AddShard out of testNewEngine

I would be glad to take any suggestion about `testShards` initialization. I tried to use intoduced `WithShardsNumFromOpts` but after rebase I was obliged to apply this hack with `testShards`. It's still possible to invoke `enginge.AddShard` out of `testNewEngine`
aarifullin marked this conversation as resolved
aarifullin requested review from storage-core-committers 2023-03-30 13:02:01 +00:00
aarifullin requested review from storage-core-developers 2023-03-30 13:02:02 +00:00
fyrchik reviewed 2023-03-30 15:04:57 +00:00
@ -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)?

Maybe just `WithShardsAdditionalOpts(func(int) []shard.Option)`?
fyrchik marked this conversation as resolved
@ -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?

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?
Poster
Collaborator

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

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
fyrchik marked this conversation as resolved
@ -79,0 +80,4 @@
engine *StorageEngine
dir string
shardIDs []*shard.ID
objects []*objectSDK.Object

Feels unnecessary here, what value does it provide?

Feels unnecessary here, what value does it provide?
Poster
Collaborator

Removed it

Removed it
fyrchik marked this conversation as resolved
@ -79,0 +84,4 @@
isRunning bool
}
func (te *testEngineWrapper) Engine() *StorageEngine {

Not worth a method IMO, .engine is just as fine and Engine() makes me wondering how is it different from the RunEngine()

Not worth a method IMO, `.engine` is just as fine and `Engine()` makes me wondering how is it different from the `RunEngine()`
fyrchik marked this conversation as resolved
@ -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 prefer to have a separate method for this, not using this as an option. It affects control flow and is different from creating something.
Poster
Collaborator

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

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
fyrchik marked this conversation as resolved
@ -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.

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.
Poster
Collaborator

Removed

Removed
fyrchik marked this conversation as resolved
@ -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?

Can we prevent this by construction? `num must be greater than 0`?
Poster
Collaborator

It is no longer actual

It is no longer actual
fyrchik marked this conversation as resolved
@ -74,3 +52,1 @@
smallFileStorage: smallFileStorage,
largeFileStorage: largeFileStorage,
}
te := testNewEngine(t).

Can testNewEngine just accept engine opts as a varargs?

Can `testNewEngine` just accept `engine` opts as a varargs?
fyrchik marked this conversation as resolved
aarifullin force-pushed feature/116-engine_constructor from 0c38468fbb to 1b874919e5 2023-03-30 15:49:18 +00:00 Compare
aarifullin force-pushed feature/116-engine_constructor from 1b874919e5 to 2d2ecf52fe 2023-03-30 16:01:03 +00:00 Compare
dstepanov-yadro approved these changes 2023-03-31 07:11:46 +00:00
fyrchik reviewed 2023-03-31 07:35:24 +00:00
@ -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?

Why move these lines?
Poster
Collaborator

My fault. Removed them because of RunEngine(t), then removed this method and got these requires back

My fault. Removed them because of `RunEngine(t)`, then removed this method and got these requires back
fyrchik marked this conversation as resolved
@ -7,7 +7,6 @@ import (
"os"
"path/filepath"
"strconv"
"sync/atomic"

Please, rebase on master.

Please, rebase on master.
fyrchik marked this conversation as resolved
@ -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.

If we want our function to override defaults, `defaultOpts` should come first.
fyrchik marked this conversation as resolved

Just a question, why have you decided to go with (e *engine) WithX(t) *engine instead of (e *engine) setX(t)?

Just a question, why have you decided to go with `(e *engine) WithX(t) *engine` instead of `(e *engine) setX(t)`?
Poster
Collaborator

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 it

> 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 it
aarifullin force-pushed feature/116-engine_constructor from 2d2ecf52fe to 2c8002e6ed 2023-03-31 09:33:40 +00:00 Compare
aarifullin requested review from dstepanov-yadro 2023-03-31 09:35:16 +00:00

Just my opinion. If something is required, it is better to create a New method, which explicitly pass the required dependencies. All WithXXX & SetXXX methods should be used only for parameters that have default values.

Just my opinion. If something is required, it is better to create a `New` method, which explicitly pass the required dependencies. All `WithXXX` & `SetXXX` methods should be used only for parameters that have default values.
dstepanov-yadro approved these changes 2023-03-31 11:33:49 +00:00
Poster
Collaborator

All WithXXX & 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

> All `WithXXX` & `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
acid-ant approved these changes 2023-04-03 16:03:06 +00:00
fyrchik requested review from storage-core-committers 2023-04-03 16:24:34 +00:00
fyrchik requested review from carpawell 2023-04-03 16:24:39 +00:00
carpawell reviewed 2023-04-05 13:07:10 +00:00
@ -45,3 +45,3 @@
s2 := testNewShard(t, 2)
e := testNewEngineWithShards(t, s1, s2)
e := testNewEngine(t).SetInitializedShards(t, s1, s2).engine
Collaborator

do we have a getter for engine (do not see it)? if no, exported setters look useless to me cause no external package needs testEngineWrapper but also no external package can get nested engine

do we have a getter for `engine` (do not see it)? if no, exported setters look useless to me cause no external package needs `testEngineWrapper` but also no external package can get nested `engine`
Poster
Collaborator

Good point. I've made setXXX methods internal

Good point. I've made `setXXX` methods internal
carpawell marked this conversation as resolved
aarifullin force-pushed feature/116-engine_constructor from 2c8002e6ed to 21f7aae37f 2023-04-05 13:32:44 +00:00 Compare
aarifullin requested review from acid-ant 2023-04-05 13:33:46 +00:00
carpawell approved these changes 2023-04-05 14:07:17 +00:00
aarifullin requested review from dstepanov-yadro 2023-04-05 14:07:50 +00:00
dstepanov-yadro approved these changes 2023-04-05 14:22:16 +00:00
fyrchik merged commit 6f7b6a8813 into master 2023-04-05 14:36:41 +00:00
Sign in to join this conversation.
No Milestone
No Assignees
5 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: TrueCloudLab/frostfs-node#190
There is no content yet.