-
Notifications
You must be signed in to change notification settings - Fork 19
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
reporter: fuzz tests for btccache #98
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I believe you get the fuzz tests right in the first place!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! I suggest testing a few more stuff:
testutil/datagen/reporter.go
Outdated
blocks, _, _ := GenRandomBlockchainWithBabylonTx(numBlocks, 0, 0) | ||
var ibs []*types.IndexedBlock | ||
|
||
blockHeight := int32(numBlocks - 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can have the starting height be a random int32
in the range of [0, max_int32-num_blocks]
. Currently the height of the earliest block is always 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup I agree, but blockHeight
is the height of last/best block here, so I think we can do
blockHeight := rand.Int31() + int32(numBlocks)
to randomize and then it would decrement subsequent block heights in loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep makes sense.
types/btccache_test.go
Outdated
rand.Seed(seed) | ||
|
||
// Create a new cache | ||
maxEntries := datagen.RandomInt(100) + 2 // ensure maxEntries > 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have 102
as the maximum size of the cache? We can test with more as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, changed to 1000 now.
types/btccache.go
Outdated
|
||
return b.reverse() | ||
} | ||
|
||
// thread-unsafe version of Reverse | ||
func (b *BTCCache) reverse() error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this return an error
if we always return nil
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe it was left over in a previous clean up, removing it now. We don't need to return errors in reverse
.
types/btccache_test.go
Outdated
|
||
// Get prev hash | ||
tip := cache.Tip() | ||
require.NotNil(t, tip) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we check that the tip is the last block of those that were inserted? Also, that the tip has the highest height than all other blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, that the tip has the highest height than all other blocks.
Do we require this? The helper function which generates blocks here already ensures the heights are sorted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, the block generation mechanism does that, but we should test that this invariant holds in the cache as well. Minor though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, fixed it now.
types/btccache_test.go
Outdated
block, _ := vdatagen.GenRandomBlock(1, &prevHash) | ||
newIb := types.NewIndexedBlockFromMsgBlock(rand.Int31(), block) | ||
cache.Add(newIb) | ||
require.Equal(t, numBlocks+1, cache.Size()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should check that cache.Tip()
is the new block that we added as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
err = cache.RemoveLast() | ||
require.NoError(t, err) | ||
} | ||
require.Equal(t, prevSize-deleteCount, cache.Size()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should check the tip of the cache and also that the blocks that are still there correspond to the slice of the ones that we added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see this being added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this comment was for newly added blocks so I added it here? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, finally added this check now on deleted blocks here, as per our call yesterday.
require.Equal(t, cacheBlocksBeforeDeletion[:len(cacheBlocksBeforeDeletion)-int(deleteCount)], cacheBlocksAfterDeletion)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates! Looks good overall, added some further comments
testutil/datagen/reporter.go
Outdated
blocks, _, _ := GenRandomBlockchainWithBabylonTx(numBlocks, 0, 0) | ||
var ibs []*types.IndexedBlock | ||
|
||
blockHeight := rand.Int31() + int32(numBlocks) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any overflow issues here? For example if rand.Int31
returns the largest positive integer for an int32, then we might have an overflow. That's why I suggested taking a random integer from [0, max_int32-numBlocks]
and then adding numBlocks
to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, once we identify the height, we could use the GetRandomIndexedBlocksFromHeight
function. Currently those functions have overlap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, you are right, there will be overflow issues. Sure I can use [0, max_int32-numBlocks]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently those functions have overlap.
Sure I have refactored GetRandomIndexedBlocks
, it can now call internally GetRandomIndexedBlocksFromHeight
types/btccache.go
Outdated
@@ -35,7 +35,8 @@ func (b *BTCCache) Init(ibs []*IndexedBlock) error { | |||
b.add(ib) | |||
} | |||
|
|||
return b.reverse() | |||
b.reverse() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is weird that we expect the input to the Init
function to be blocks in the reverse order. I think it would be better if this function received the blocks in the order that they should be added instead of having to do reversing stuff. The one that calls it should be responsible for providing the correct order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I like this suggestion. I have refactored Init
now, it expects blocks with sorted height, also we won't need the reverse
now
testutil/datagen/reporter.go
Outdated
blockHeight := rand.Int31() + int32(numBlocks) | ||
for _, block := range blocks { | ||
ibs = append(ibs, types.NewIndexedBlockFromMsgBlock(blockHeight, block)) | ||
blockHeight -= 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is weird that we need to construct a list in decreasing order in order to properly test Init()
. See my comment on the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I have refactored Init
, don't need to reverse it now.
@@ -139,7 +130,7 @@ func (b *BTCCache) GetAllBlocks() []*IndexedBlock { | |||
return b.blocks | |||
} | |||
|
|||
// FindBlock finds block at the given height in cache | |||
// FindBlock uses binary search to find the block with the given height in cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
types/btccache_test.go
Outdated
|
||
// Add all indexed blocks to the cache | ||
err = cache.Init(ibs) | ||
if numBlocks > maxEntries { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this might happen more often that we want it to (did not do the exact probability calculation), this means that many test cases are just going to test this and stop. I suppose we don't want to many test cases to fail on this, so maybe you can only test this case 1/10
times? You can use the datagen.OneInN(10)
method. We are already following this practice for some Babylon fuzz tests.
} | ||
require.Equal(t, prevCacheHeight+int32(addCount), cache.Tip().Height) | ||
require.Equal(t, newIbs[addCount-1], cache.Tip()) | ||
if addCount >= maxEntries { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my understanding addCount
is the of new blocks. But the cache already has numBlocks
inside of it. Then, in that case, we should check that in the case that addCount+numBlocks>=maxEntries
:
- The last
addCount
blocks in the cache are equal to all thenewIbs
blocks - The first
maxEntries-addCount
blocks in the cache are equal to the lastmaxEntries-addCount
blocks of the initial blocks that were added.
Otherwise, we should just check that the last addCount
blocks in the cache are equal to all the newIbs
blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, good point. I have added these cases and some comments in the code to clarify as discussed in our call yesterday.
err = cache.RemoveLast() | ||
require.NoError(t, err) | ||
} | ||
require.Equal(t, prevSize-deleteCount, cache.Size()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see this being added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, thanks for the updates! Very minor comments, LGTM!
btcclient/query.go
Outdated
@@ -71,5 +71,10 @@ func (c *Client) GetLastBlocks(stopHeight uint64) ([]*types.IndexedBlock, error) | |||
} | |||
} | |||
|
|||
// reverse the order of the blocks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a note in the docstring about the ordering of the result?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, added.
if sortedByHeight := sort.SliceIsSorted(ibs, func(i, j int) bool { | ||
return ibs[i].Height < ibs[j].Height | ||
}); !sortedByHeight { | ||
return ErrorUnsortedBlocks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great check!
|
||
cache, err := types.NewBTCCache(maxEntries) | ||
if err != nil { | ||
require.ErrorIs(t, err, types.ErrInvalidMaxEntries) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If datagen.OneInN(10)
returns false
and the types.NewBTCCache
returns an error, this check will pass, but it should not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure added this check
if !invalidMaxEntries {
t.Fatalf("NewBTCCache returned error %s", err)
}
// Add all indexed blocks to the cache | ||
err = cache.Init(ibs) | ||
if err != nil { | ||
require.ErrorIs(t, err, types.ErrTooManyEntries) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, fixed now added check same as above.
Co-authored-by: Vitalis Salis <[email protected]>
437a06c
to
dd9e756
Compare
Fixes
https://babylon-chain.atlassian.net/browse/BM-152
Description
Adds fuzz tests for btc cache