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

[Access] Make response for data providers consistent. #6846

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
275b16e
Changed response to consostent for block provider
AndriiDiachuk Dec 26, 2024
738ad8b
Merge branch 'AndriiDiachuk/6586-tx-statuses-data-providers-impl' of …
AndriiDiachuk Dec 27, 2024
9d2a761
Changed responses to be consistant for all block data providers
AndriiDiachuk Dec 27, 2024
aafcc4d
Refactored response type of account statuses data provider
AndriiDiachuk Dec 27, 2024
453f8d7
Refactored respone type of events daya provider
AndriiDiachuk Dec 27, 2024
92016be
Refactored transaction statuses data providers
AndriiDiachuk Dec 27, 2024
4c906b0
Merge branch 'master' of github.com:The-K-R-O-K/flow-go into AndriiDi…
AndriiDiachuk Jan 3, 2025
4c3e5ae
Renamed fields naming
AndriiDiachuk Jan 3, 2025
e1ad694
Merged and fixed tests
AndriiDiachuk Jan 7, 2025
5d8189c
Chanaged expected types in data provider tests to be consistent, adde…
AndriiDiachuk Jan 7, 2025
26485fa
Removed wrong Build function
AndriiDiachuk Jan 8, 2025
3b22d5d
Refactored data providers tests
AndriiDiachuk Jan 8, 2025
c868481
Refactored Build function BaseMessage for webSockets
AndriiDiachuk Jan 10, 2025
e549056
Merge branch 'master' of github.com:The-K-R-O-K/flow-go into AndriiDi…
AndriiDiachuk Jan 10, 2025
d4147c7
Merge branch 'master' into AndriiDiachuk/6819-make-response-for-data-…
peterargue Jan 13, 2025
58ba2f7
Merge branch 'master' of github.com:The-K-R-O-K/flow-go into AndriiDi…
AndriiDiachuk Jan 14, 2025
6c5aa7f
Merge branch 'AndriiDiachuk/6819-make-response-for-data-providers-con…
AndriiDiachuk Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,11 @@ func (p *AccountStatusesDataProvider) handleResponse() func(accountStatusesRespo
return status.Errorf(codes.Internal, "message index already incremented to %d", messageIndex.Value())
}

var response models.AccountStatusesResponse
response.Build(accountStatusesResponse, index)
var accountStatusesPayload models.AccountStatusesResponse
accountStatusesPayload.Build(accountStatusesResponse, index)

var response models.BaseDataProvidersResponse
response.Build(p.ID(), p.Topic(), &accountStatusesPayload)

p.send <- &response

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,49 @@ func (s *AccountStatusesProviderSuite) subscribeAccountStatusesDataProviderTestC

// requireAccountStatuses ensures that the received account statuses information matches the expected data.
func (s *AccountStatusesProviderSuite) requireAccountStatuses(actual interface{}, expected interface{}) {
expectedResponse, ok := expected.(*models.AccountStatusesResponse)
require.True(s.T(), ok, "Expected *models.AccountStatusesResponse, got %T", expected)
expectedResponse, ok := expected.(*models.BaseDataProvidersResponse)
require.True(s.T(), ok, "Expected *models.BaseDataProvidersResponse, got %T", expected)
Comment on lines +141 to +142
Copy link
Contributor

Choose a reason for hiding this comment

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

looks like you're doing this in a lot of places. maybe create a helper function? something like

func extractPayload[T any](t *testing.T, v interface{}) T {
	response, ok := v.(*BaseDataProvidersResponse)
	require.True(t, ok, "Expected *models.BaseDataProvidersResponse, got %T", v)

	payload, ok := response.Payload.(T)
	require.True(t, ok, "Unexpected response payload type: %T", response.Payload)

	return payload
}

then usage

expectedResponsePayload := extractPayload[*models.AccountStatusesResponse](t, expected)
actualResponsePayload := extractPayload[*models.AccountStatusesResponse](t, actual)


actualResponse, ok := actual.(*models.AccountStatusesResponse)
require.True(s.T(), ok, "Expected *models.AccountStatusesResponse, got %T", actual)
expectedResponsePayload, ok := expectedResponse.Payload.(*models.AccountStatusesResponse)
require.True(s.T(), ok, "Unexpected response payload type: %T", expectedResponse.Payload)

require.Equal(s.T(), expectedResponse.BlockID, actualResponse.BlockID)
require.Equal(s.T(), len(expectedResponse.AccountEvents), len(actualResponse.AccountEvents))
require.Equal(s.T(), expectedResponse.MessageIndex, actualResponse.MessageIndex)
require.Equal(s.T(), expectedResponse.Height, actualResponse.Height)
actualResponse, ok := actual.(*models.BaseDataProvidersResponse)
require.True(s.T(), ok, "Expected *models.BaseDataProvidersResponse, got %T", actual)

for key, expectedEvents := range expectedResponse.AccountEvents {
actualEvents, ok := actualResponse.AccountEvents[key]
actualResponsePayload, ok := actualResponse.Payload.(*models.AccountStatusesResponse)
require.True(s.T(), ok, "Unexpected response payload type: %T", actualResponse.Payload)

require.Equal(s.T(), expectedResponsePayload.BlockID, actualResponsePayload.BlockID)
require.Equal(s.T(), len(expectedResponsePayload.AccountEvents), len(actualResponsePayload.AccountEvents))
require.Equal(s.T(), expectedResponsePayload.MessageIndex, actualResponsePayload.MessageIndex)
require.Equal(s.T(), expectedResponsePayload.Height, actualResponsePayload.Height)
require.Equal(s.T(), expectedResponse.Topic, actualResponse.Topic)

for key, expectedEvents := range expectedResponsePayload.AccountEvents {
actualEvents, ok := actualResponsePayload.AccountEvents[key]
require.True(s.T(), ok, "Missing key in actual AccountEvents: %s", key)

s.Require().Equal(expectedEvents, actualEvents, "Mismatch for key: %s", key)
}
}

// expectedAccountStatusesResponses creates the expected responses for the provided events and backend responses.
func (s *AccountStatusesProviderSuite) expectedAccountStatusesResponses(backendResponses []*backend.AccountStatusesResponse) []interface{} {
expectedResponses := make([]interface{}, len(backendResponses))

for i, resp := range backendResponses {
var expectedResponsePayload models.AccountStatusesResponse
expectedResponsePayload.Build(resp, uint64(i))

expectedResponses[i] = &models.BaseDataProvidersResponse{
Topic: AccountStatusesTopic,
Payload: &expectedResponsePayload,
}
}

return expectedResponses
}

// TestAccountStatusesDataProvider_InvalidArguments tests the behavior of the account statuses data provider
// when invalid arguments are provided. It verifies that appropriate errors are returned
// for missing or conflicting arguments.
Expand Down Expand Up @@ -249,9 +273,13 @@ func (s *AccountStatusesProviderSuite) TestMessageIndexAccountStatusesProviderRe
var responses []*models.AccountStatusesResponse
for i := 0; i < accountStatusesCount; i++ {
res := <-send
accountStatusesRes, ok := res.(*models.AccountStatusesResponse)
accountStatusesRes, ok := res.(*models.BaseDataProvidersResponse)
s.Require().True(ok, "Expected *models.BaseDataProvidersResponse, got %T", res)

accountStatusesResData, ok := accountStatusesRes.Payload.(*models.AccountStatusesResponse)
s.Require().True(ok, "Expected *models.AccountStatusesResponse, got %T", res)
responses = append(responses, accountStatusesRes)

responses = append(responses, accountStatusesResData)
}

// Verifying that indices are starting from 0
Expand Down Expand Up @@ -281,17 +309,3 @@ func (s *AccountStatusesProviderSuite) backendAccountStatusesResponses(events []

return responses
}

// expectedAccountStatusesResponses creates the expected responses for the provided events and backend responses.
func (s *AccountStatusesProviderSuite) expectedAccountStatusesResponses(backendResponses []*backend.AccountStatusesResponse) []interface{} {
expectedResponses := make([]interface{}, len(backendResponses))

for i, resp := range backendResponses {
var expectedResponse models.AccountStatusesResponse
expectedResponse.Build(resp, uint64(i))

expectedResponses[i] = &expectedResponse
}

return expectedResponses
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,14 @@ func (p *BlockDigestsDataProvider) Run() error {
var block models.BlockDigest
block.Build(b)

return &models.BlockDigestMessageResponse{
Block: &block,
}, nil
var response models.BaseDataProvidersResponse
response.Build(
p.ID(),
p.Topic(),
&block,
)

return &response, nil
}),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,23 @@ func (s *BlockDigestsProviderSuite) SetupTest() {
s.BlocksProviderSuite.SetupTest()
}

// TestBlockDigestsDataProvider_InvalidArguments tests the behavior of the block digests data provider
// when invalid arguments are provided. It verifies that appropriate errors are returned
// for missing or conflicting arguments.
// This test covers the test cases:
// 1. Missing 'block_status' argument.
// 2. Invalid 'block_status' argument.
// 3. Providing both 'start_block_id' and 'start_block_height' simultaneously.
func (s *BlockDigestsProviderSuite) TestBlockDigestsDataProvider_InvalidArguments() {
ctx := context.Background()
send := make(chan interface{})

topic := BlockDigestsTopic

for _, test := range s.invalidArgumentsTestCases() {
s.Run(test.name, func() {
provider, err := NewBlockDigestsDataProvider(ctx, s.log, s.api, topic, test.arguments, send)
s.Require().Nil(provider)
s.Require().Error(err)
s.Require().Contains(err.Error(), test.expectedErrorMsg)
})
}
// TestBlockDigestsDataProvider_HappyPath tests the behavior of the block digests data provider
// when it is configured correctly and operating under normal conditions. It
// validates that block digests are correctly streamed to the channel and ensures
// no unexpected errors occur.
func (s *BlockDigestsProviderSuite) TestBlockDigestsDataProvider_HappyPath() {
testHappyPath(
s.T(),
BlockDigestsTopic,
s.factory,
s.validBlockDigestsArgumentsTestCases(),
func(dataChan chan interface{}) {
for _, block := range s.blocks {
dataChan <- flow.NewBlockDigest(block.Header.ID(), block.Header.Height, block.Header.Timestamp)
}
},
s.requireBlockDigest,
)
}

// validBlockDigestsArgumentsTestCases defines test happy cases for block digests data providers.
Expand All @@ -61,7 +57,10 @@ func (s *BlockDigestsProviderSuite) validBlockDigestsArgumentsTestCases() []test
var block models.BlockDigest
block.Build(blockDigest)

expectedResponses[i] = &models.BlockDigestMessageResponse{Block: &block}
expectedResponses[i] = &models.BaseDataProvidersResponse{
Topic: BlockDigestsTopic,
Payload: &block,
}
}

return []testType{
Expand Down Expand Up @@ -114,32 +113,43 @@ func (s *BlockDigestsProviderSuite) validBlockDigestsArgumentsTestCases() []test
}
}

// TestBlockDigestsDataProvider_HappyPath tests the behavior of the block digests data provider
// when it is configured correctly and operating under normal conditions. It
// validates that block digests are correctly streamed to the channel and ensures
// no unexpected errors occur.
func (s *BlockDigestsProviderSuite) TestBlockDigestsDataProvider_HappyPath() {
testHappyPath(
s.T(),
BlockDigestsTopic,
s.factory,
s.validBlockDigestsArgumentsTestCases(),
func(dataChan chan interface{}) {
for _, block := range s.blocks {
dataChan <- flow.NewBlockDigest(block.Header.ID(), block.Header.Height, block.Header.Timestamp)
}
},
s.requireBlockDigest,
)
// requireBlockDigest ensures that the received block header information matches the expected data.
func (s *BlocksProviderSuite) requireBlockDigest(actual interface{}, expected interface{}) {
expectedResponse, ok := expected.(*models.BaseDataProvidersResponse)
require.True(s.T(), ok, "Expected *models.BaseDataProvidersResponse, got %T", expected)

expectedResponsePayload, ok := expectedResponse.Payload.(*models.BlockDigest)
require.True(s.T(), ok, "Unexpected response payload type: %T", expectedResponse.Payload)

actualResponse, ok := actual.(*models.BaseDataProvidersResponse)
require.True(s.T(), ok, "Expected *models.BaseDataProvidersResponse, got %T", actual)

actualResponsePayload, ok := actualResponse.Payload.(*models.BlockDigest)
require.True(s.T(), ok, "Unexpected response payload type: %T", actualResponse.Payload)

s.Require().Equal(expectedResponse.Topic, actualResponse.Topic)
s.Require().Equal(expectedResponsePayload, actualResponsePayload)
}

// requireBlockHeaders ensures that the received block header information matches the expected data.
func (s *BlocksProviderSuite) requireBlockDigest(actual interface{}, expected interface{}) {
actualResponse, ok := actual.(*models.BlockDigestMessageResponse)
require.True(s.T(), ok, "unexpected response type: %T", actual)
// TestBlockDigestsDataProvider_InvalidArguments tests the behavior of the block digests data provider
// when invalid arguments are provided. It verifies that appropriate errors are returned
// for missing or conflicting arguments.
// This test covers the test cases:
// 1. Missing 'block_status' argument.
// 2. Invalid 'block_status' argument.
// 3. Providing both 'start_block_id' and 'start_block_height' simultaneously.
func (s *BlockDigestsProviderSuite) TestBlockDigestsDataProvider_InvalidArguments() {
ctx := context.Background()
send := make(chan interface{})

expectedResponse, ok := expected.(*models.BlockDigestMessageResponse)
require.True(s.T(), ok, "unexpected response type: %T", expected)
topic := BlockDigestsTopic

s.Require().Equal(expectedResponse.Block, actualResponse.Block)
for _, test := range s.invalidArgumentsTestCases() {
s.Run(test.name, func() {
provider, err := NewBlockDigestsDataProvider(ctx, s.log, s.api, topic, test.arguments, send)
s.Require().Nil(provider)
s.Require().Error(err)
s.Require().Contains(err.Error(), test.expectedErrorMsg)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,14 @@ func (p *BlockHeadersDataProvider) Run() error {
var header commonmodels.BlockHeader
header.Build(h)

return &models.BlockHeaderMessageResponse{
Header: &header,
}, nil
var response models.BaseDataProvidersResponse
response.Build(
p.ID(),
p.Topic(),
&header,
)

return &response, nil
}),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,23 @@ func (s *BlockHeadersProviderSuite) SetupTest() {
s.BlocksProviderSuite.SetupTest()
}

// TestBlockHeadersDataProvider_InvalidArguments tests the behavior of the block headers data provider
// when invalid arguments are provided. It verifies that appropriate errors are returned
// for missing or conflicting arguments.
// This test covers the test cases:
// 1. Missing 'block_status' argument.
// 2. Invalid 'block_status' argument.
// 3. Providing both 'start_block_id' and 'start_block_height' simultaneously.
func (s *BlockHeadersProviderSuite) TestBlockHeadersDataProvider_InvalidArguments() {
ctx := context.Background()
send := make(chan interface{})

topic := BlockHeadersTopic

for _, test := range s.invalidArgumentsTestCases() {
s.Run(test.name, func() {
provider, err := NewBlockHeadersDataProvider(ctx, s.log, s.api, topic, test.arguments, send)
s.Require().Nil(provider)
s.Require().Error(err)
s.Require().Contains(err.Error(), test.expectedErrorMsg)
})
}
// TestBlockHeadersDataProvider_HappyPath tests the behavior of the block headers data provider
// when it is configured correctly and operating under normal conditions. It
// validates that block headers are correctly streamed to the channel and ensures
// no unexpected errors occur.
func (s *BlockHeadersProviderSuite) TestBlockHeadersDataProvider_HappyPath() {
testHappyPath(
s.T(),
BlockHeadersTopic,
s.factory,
s.validBlockHeadersArgumentsTestCases(),
func(dataChan chan interface{}) {
for _, block := range s.blocks {
dataChan <- block.Header
}
},
s.requireBlockHeader,
)
}

// validBlockHeadersArgumentsTestCases defines test happy cases for block headers data providers.
Expand All @@ -60,7 +56,10 @@ func (s *BlockHeadersProviderSuite) validBlockHeadersArgumentsTestCases() []test
var header commonmodels.BlockHeader
header.Build(b.Header)

expectedResponses[i] = &models.BlockHeaderMessageResponse{Header: &header}
expectedResponses[i] = &models.BaseDataProvidersResponse{
Topic: BlockHeadersTopic,
Payload: &header,
}
}

return []testType{
Expand Down Expand Up @@ -113,32 +112,43 @@ func (s *BlockHeadersProviderSuite) validBlockHeadersArgumentsTestCases() []test
}
}

// TestBlockHeadersDataProvider_HappyPath tests the behavior of the block headers data provider
// when it is configured correctly and operating under normal conditions. It
// validates that block headers are correctly streamed to the channel and ensures
// no unexpected errors occur.
func (s *BlockHeadersProviderSuite) TestBlockHeadersDataProvider_HappyPath() {
testHappyPath(
s.T(),
BlockHeadersTopic,
s.factory,
s.validBlockHeadersArgumentsTestCases(),
func(dataChan chan interface{}) {
for _, block := range s.blocks {
dataChan <- block.Header
}
},
s.requireBlockHeader,
)
}

// requireBlockHeaders ensures that the received block header information matches the expected data.
func (s *BlockHeadersProviderSuite) requireBlockHeader(actual interface{}, expected interface{}) {
actualResponse, ok := actual.(*models.BlockHeaderMessageResponse)
require.True(s.T(), ok, "unexpected response type: %T", actual)
expectedResponse, ok := expected.(*models.BaseDataProvidersResponse)
require.True(s.T(), ok, "Expected *models.BaseDataProvidersResponse, got %T", expected)

expectedResponse, ok := expected.(*models.BlockHeaderMessageResponse)
require.True(s.T(), ok, "unexpected response type: %T", expected)
expectedResponsePayload, ok := expectedResponse.Payload.(*commonmodels.BlockHeader)
require.True(s.T(), ok, "Unexpected response payload type: %T", expectedResponse.Payload)

s.Require().Equal(expectedResponse.Header, actualResponse.Header)
actualResponse, ok := actual.(*models.BaseDataProvidersResponse)
require.True(s.T(), ok, "Expected *models.BaseDataProvidersResponse, got %T", actual)

actualResponsePayload, ok := actualResponse.Payload.(*commonmodels.BlockHeader)
require.True(s.T(), ok, "Unexpected response payload type: %T", actualResponse.Payload)

s.Require().Equal(expectedResponse.Topic, actualResponse.Topic)
s.Require().Equal(expectedResponsePayload, actualResponsePayload)
}

// TestBlockHeadersDataProvider_InvalidArguments tests the behavior of the block headers data provider
// when invalid arguments are provided. It verifies that appropriate errors are returned
// for missing or conflicting arguments.
// This test covers the test cases:
// 1. Missing 'block_status' argument.
// 2. Invalid 'block_status' argument.
// 3. Providing both 'start_block_id' and 'start_block_height' simultaneously.
func (s *BlockHeadersProviderSuite) TestBlockHeadersDataProvider_InvalidArguments() {
ctx := context.Background()
send := make(chan interface{})

topic := BlockHeadersTopic

for _, test := range s.invalidArgumentsTestCases() {
s.Run(test.name, func() {
provider, err := NewBlockHeadersDataProvider(ctx, s.log, s.api, topic, test.arguments, send)
s.Require().Nil(provider)
s.Require().Error(err)
s.Require().Contains(err.Error(), test.expectedErrorMsg)
})
}
}
Loading
Loading