Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup consensus engine tests #2953

Merged
merged 7 commits into from
Apr 23, 2024
Merged

Conversation

StephenButtolph
Copy link
Contributor

@StephenButtolph StephenButtolph commented Apr 19, 2024

Why this should be merged

The consensus engine tests are in a really bad spot. This PR cleans them up a bit. By defining the genesis globally and adding a helper function to generate a chain in a helper function.

These tests are realistically going to be completely re-written... But I want to update these tests incrementally so we can understand what's changing.

How this works

How this was tested

  • CI

@StephenButtolph StephenButtolph added consensus This involves consensus testing This primarily focuses on testing labels Apr 19, 2024
@StephenButtolph StephenButtolph added this to the v1.11.5 milestone Apr 19, 2024
@StephenButtolph StephenButtolph self-assigned this Apr 19, 2024
Comment on lines -554 to -592
func TestEngineAbandonResponse(t *testing.T) {
require := require.New(t)

vdr, _, sender, vm, te, gBlk := setupDefaultConfig(t)

sender.Default(false)

blk := &snowman.TestBlock{
TestDecidable: choices.TestDecidable{
IDV: ids.GenerateTestID(),
StatusV: choices.Unknown,
},
ParentV: gBlk.ID(),
HeightV: 1,
BytesV: []byte{1},
}

vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) {
switch {
case blkID == gBlk.ID():
return gBlk, nil
case blkID == blk.ID():
return nil, errUnknownBlock
}
require.FailNow(errUnknownBlock.Error())
return nil, errUnknownBlock
}

require.NoError(te.issue(
context.Background(),
te.Ctx.NodeID,
blk,
false,
te.metrics.issued.WithLabelValues(unknownSource),
))
require.NoError(te.QueryFailed(context.Background(), vdr, 1))

require.Empty(te.blocked)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test made 100% no sense. te.blocked is always empty during this test... So really it's just testing that issue works... Which we already test in other tests.

@StephenButtolph StephenButtolph marked this pull request as ready for review April 19, 2024 05:22
Copy link
Contributor

@abi87 abi87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a nit and a couple of questions.
Definitely complex tests, doing a second pass

require.True(vmShutdownCalled)
}

func TestEngineAdd(t *testing.T) {
func TestEngineDropsAttemptToIssueBlockAfterFailedRequest(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change part of this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just changed the name of the test, I felt it was more useful of a name then TestEngineAdd

IDV: Genesis,
StatusV: choices.Accepted,
}}

vm.LastAcceptedF = func(context.Context) (ids.ID, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(No action required) Given that this is a test VM, why isn't this kind of initialization an internal detail or performed in a constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this should be improved. I mainly wanted to unblock the new test in #2956 for this PR, so not trying to do a total re-write here.

snow/engine/snowman/transitive_test.go Outdated Show resolved Hide resolved
require.Equal(vdr, inVdr)
require.Equal(blk.Parent(), blkID)
var request *common.Request
sender.SendGetF = func(_ context.Context, nodeID ids.NodeID, requestID uint32, blkID ids.ID) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(No action required) Would it be possible for the code under test to be refactored to enable verification of the desired behavior without having to resort to the current testvm/mock-like-thing approach?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some things that can definitely be factored out... See some of the changes in #2952.

// Handling a pull query for [parent] should result in immediately
// responding with chits for [Genesis] along with a request for [parent].
require.NoError(engine.PullQuery(context.Background(), peerID, 15, parent.ID(), 1))
require.True(sendChitsCalled)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(No action required) Is it possible to verify the desired behavior without resorting to checking for specific calls? i.e. specify inputs that can only result in the desired outputs if the expected call path were taken

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably re-write the tests to simulate multiple participants. But it feels like that would be better suited to an E2E test

@StephenButtolph StephenButtolph added this pull request to the merge queue Apr 23, 2024
Merged via the queue into master with commit 2535387 Apr 23, 2024
19 checks passed
@StephenButtolph StephenButtolph deleted the cleanup-consensus-tests branch April 23, 2024 21:09
Comment on lines +35 to +36
GenesisID = ids.GenerateTestID()
GenesisBytes = utils.RandomBytes(32)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even need these two vars since they can be accessed from just calling Genesis.BytesV/IDV?

)

func setup(t *testing.T, engCfg Config) (ids.NodeID, validators.Manager, *common.SenderTest, *block.TestVM, *Transitive, snowman.Block) {
func BuildChain(root *snowman.TestBlock, length int) []*snowman.TestBlock {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer us just generating the entire chain here instead of the caller defining a genesis block and calling BuildChain to get more blocks, but I could also buy the argument that maybe this is cleaner for tests that only have one block...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
consensus This involves consensus testing This primarily focuses on testing
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

6 participants