[BCI-3989][common] - CR methods err when service unstarted#705
[BCI-3989][common] - CR methods err when service unstarted#705
Conversation
This reverts commit 5006bec.
| func (it *fakeChainReaderInterfaceTester) Start(t *testing.T) { | ||
| fake, ok := it.impl.(*fakeChainReader) | ||
| assert.True(t, ok) | ||
| require.NoError(t, fake.Start(context.Background())) | ||
| } | ||
|
|
||
| func (it *fakeChainReaderInterfaceTester) Close(t *testing.T) { | ||
| fake, ok := it.impl.(*fakeChainReader) | ||
| assert.True(t, ok) | ||
| require.NoError(t, fake.Close()) | ||
| } |
There was a problem hiding this comment.
Why do we need these, why not directly call Start and Close on the ChainReader returned from GetChainReader
There was a problem hiding this comment.
It fails when we run the LOOPs tests. It tries to execute this Start() func which is a no-op. Exposing these 2 funcs in the InterfaceTester was a workaround on this issue.
Let me know your thoughts if there's other way of achieving this without exposing these methods. I'm not very familiar with LOOPs yet and might be missing some context
There was a problem hiding this comment.
Casting the interface to a specific struct type does not affect which method is called by name via Start/Close. Please see my other comment: #705 (comment)
| func (it *fakeContractReaderInterfaceTester) StartContractReader(t *testing.T) { | ||
| fake, ok := it.impl.(*fakeContractReader) | ||
| assert.True(t, ok) | ||
| require.NoError(t, fake.Start(context.Background())) | ||
| } | ||
|
|
||
| func (it *fakeContractReaderInterfaceTester) CloseContractReader(t *testing.T) { | ||
| fake, ok := it.impl.(*fakeContractReader) | ||
| assert.True(t, ok) | ||
| require.NoError(t, fake.Close()) | ||
| } |
There was a problem hiding this comment.
I'm having trouble seeing why we need these helper methods. impl is already a ContractReader, so we don't need to cast it to a specific fake type:
| func (it *fakeContractReaderInterfaceTester) StartContractReader(t *testing.T) { | |
| fake, ok := it.impl.(*fakeContractReader) | |
| assert.True(t, ok) | |
| require.NoError(t, fake.Start(context.Background())) | |
| } | |
| func (it *fakeContractReaderInterfaceTester) CloseContractReader(t *testing.T) { | |
| fake, ok := it.impl.(*fakeContractReader) | |
| assert.True(t, ok) | |
| require.NoError(t, fake.Close()) | |
| } | |
| func (it *fakeContractReaderInterfaceTester) StartContractReader(t *testing.T) { | |
| require.NoError(t, it.impl.Start(context.Background())) | |
| } | |
| func (it *fakeContractReaderInterfaceTester) CloseContractReader(t *testing.T) { | |
| require.NoError(t, it.impl.Close()) | |
| } |
Additionally, there is already a GetContractReader method, so callers that are doing this:
tester.StartContractReader(t)
defer tester.CloseContractReader(t)Could instead do this:
tester.GetContractReader(t).Start(ctx)
defer tester.GetContractReader(t).Close()Or better yet:
servicetest.Run(t, tester.GetContractReader(t))There was a problem hiding this comment.
@jmank88 @silaslenihan I couldn't do it this way. Tests fail for the loop relay client.
Pushed some changes with a new idea:
- Modify
testCasesandSetupto receive astartCRflag and control whether we should start CR or not - With this,
StartandClosewill be handled bySetupwithCleanup
All tests are passing, including new ones where we test that the service does not start. Let me know your thoughts
There was a problem hiding this comment.
Could you please update the description? I'm having trouble understanding the fundamental problem we are trying to solve.
There was a problem hiding this comment.
Since the BasicTester interface is used more generally than for just contract reader, I don't think it makes sense to add a contract-reader-only argument to BasicTester.Setup.
There was a problem hiding this comment.
Fundamental problem we are trying to solve: We only want GetLatestValue, BatchGetLatestValue and QueryKey to be called when the service CR is in Started state. If CR has not yet been started, we should return an error.
To test this new behavior, we need a way to get the CR in both states (started and not started).
We can't just call Start and Close directly on the return of GetContractReader to achieve this. This is because we also run relay client loop tests here. We are calling Start and Close on the client and not on the server as would be required.
The two solutions I proposed were aimed at solving this problem, the one with the helper methods and now the one with the flag. I feel like the one with the flag is cleaner. We are providing in the testCase the startCR flag to determine if the underlying Setup function should return the service in started or unstarted state
What do you think about defining a new interface similar to BasicTester but use it specifically on contract-reader?
There was a problem hiding this comment.
We can't just call Start and Close directly on the return of GetContractReader to achieve this. This is because we also run relay client loop tests here. We are calling Start and Close on the client and not on the server as would be required.
The two solutions I proposed were aimed at solving this problem, the one with the helper methods and now the one with the flag.
Something isn't adding up here. The modification that I proposed to your helper methods was intended to execute exactly equivalently. It was not proposing a change in behavior - definitely not one that switched from client to server or vice versa. If the helper method solution was valid, then we should revisit it, but in the most simplified form.
There was a problem hiding this comment.
Pushed a new solution with interfaces refactor and comments on changes. If do you think it's okay we can go with it. Else, I'll revisit the one with the helper methods in the most simplified form
jmank88
left a comment
There was a problem hiding this comment.
It looks like there are still some simplifications available
| require.NoError(t, it.impl.Start(context.Background())) | ||
| t.Cleanup(func() { require.NoError(t, it.impl.Close()) }) |
There was a problem hiding this comment.
Please use servicetest.Run. Notice it uses assert during cleanup.
…arted" This reverts commit e728084.
| ) | ||
|
|
||
| type ChainComponentsInterfaceTester[T TestingT[T]] interface { | ||
| type ChainComponentsTester[T any] interface { |
There was a problem hiding this comment.
- defined
ChainComponentsTesterso we use theSetup(t T, startCR bool)only forchainComponentstests - defined
chainComponentsTestcaseso we use thestartCRtestcase flag only forchainComponentstestcases - defined
runChainComponentsTeststo executechainComponentsspecific tests using theChainComponentsTesterinterface withSetup(t T, startCR bool)
| TestOn string | ||
| } | ||
|
|
||
| type codecTestcase[T any] struct { |
There was a problem hiding this comment.
- defined CodecTester so we use the
Setup(t T)without thestartCRflag for thecodec - defined
codecTestcaseso we don't use thestartCRtestcase flag forcodectestcases - defined
runCodecTeststo executecodecspecific tests using theCodecTesterinterface withSetup(t T)
| fake.stored = []TestStruct{} | ||
|
|
||
| if startCR { | ||
| servicetest.Run(t, it.impl) |
There was a problem hiding this comment.
added servicetest.Run(t, it.impl)
ilija42
left a comment
There was a problem hiding this comment.
Wdyt about this solution
solana ref: BCI-3989-cr-methods-error-when-unstarted
core ref: BCI-3989-cr-methods-error-when-unstarted
Task Description:
We only want
GetLatestValue,BatchGetLatestValueandQueryKeyto be called whenCRservice is inStartedstate. IfCRis not started yet, we should return an error.This PR:
Ticket:
Unblocks:
Merging flow: