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

test: implement index manager tests #982

Merged
merged 2 commits into from
Jun 16, 2022
Merged

test: implement index manager tests #982

merged 2 commits into from
Jun 16, 2022

Conversation

frrist
Copy link
Member

@frrist frrist commented Jun 9, 2022

  • also found and fixed deadlock on fatal errors

@frrist frrist self-assigned this Jun 9, 2022
@frrist frrist requested review from hsanjuan, kasteph and placer14 June 9, 2022 03:28
@frrist frrist force-pushed the frrist/manager-test branch from 96bddd2 to e1d6c42 Compare June 9, 2022 03:33
@codecov-commenter
Copy link

codecov-commenter commented Jun 9, 2022

Codecov Report

Merging #982 (e9515ea) into master (0464ef6) will increase coverage by 1.2%.
The diff coverage is 83.3%.

@@           Coverage Diff            @@
##           master    #982     +/-   ##
========================================
+ Coverage    34.0%   35.2%   +1.2%     
========================================
  Files          30      31      +1     
  Lines        2020    2087     +67     
========================================
+ Hits          687     736     +49     
- Misses       1256    1266     +10     
- Partials       77      85      +8     

return false, fatal
default:
success := atomic.NewBool(true)
grp, ctx := errgroup.WithContext(ctx)
Copy link
Member Author

Choose a reason for hiding this comment

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

introduction of errgroup fixes deadlock by allowing both channels to be read from simultaneously. Prior to this taskErrors was only read when a taskResults was received. If there wasn't a taskResult then the tipset indexer deadlocked writing to the taskErrors channel since nothing was reading from it.

@@ -331,11 +334,12 @@ func (t *TipSetIndexer) TipSet(ctx context.Context, ts *types.TipSet) (chan *Res

var (
outCh = make(chan *Result, len(stateResults))
errCh = make(chan error)
errCh = make(chan error, 1)
Copy link
Member Author

Choose a reason for hiding this comment

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

buffered channel to ensure writes never block

)
go func() {
defer func() {
close(outCh)
close(errCh)
Copy link
Member Author

Choose a reason for hiding this comment

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

close the channel signaling to consumers in the manager to exit.

Comment on lines -565 to +578
func (m *LilyNodeAPI) LogList(ctx context.Context) ([]string, error) {
func (m *LilyNodeAPI) LogList(_ context.Context) ([]string, error) {
return logging.GetSubsystems(), nil
}

func (m *LilyNodeAPI) LogSetLevel(ctx context.Context, subsystem, level string) error {
func (m *LilyNodeAPI) LogSetLevel(_ context.Context, subsystem, level string) error {
return logging.SetLogLevel(subsystem, level)
}

func (m *LilyNodeAPI) LogSetLevelRegex(ctx context.Context, regex, level string) error {
func (m *LilyNodeAPI) LogSetLevelRegex(_ context.Context, regex, level string) error {
return logging.SetLogLevelRegex(regex, level)
}

func (m *LilyNodeAPI) Shutdown(ctx context.Context) error {
func (m *LilyNodeAPI) Shutdown(_ context.Context) error {
Copy link
Member Author

Choose a reason for hiding this comment

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

linting

Comment on lines -631 to 633
func (l *LogQueryHook) AfterQuery(ctx context.Context, event *pg.QueryEvent) error {
func (l *LogQueryHook) AfterQuery(_ context.Context, _ *pg.QueryEvent) error {
return nil
Copy link
Member Author

Choose a reason for hiding this comment

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

more linting

@@ -0,0 +1,562 @@
package integrated
Copy link
Member Author

Choose a reason for hiding this comment

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

unit test the indexer manager with mocks

- fix deadlock on fatal errors
@frrist frrist force-pushed the frrist/manager-test branch from e1d6c42 to 72c7ff3 Compare June 9, 2022 03:39
Copy link
Contributor

@placer14 placer14 left a comment

Choose a reason for hiding this comment

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

Tests look wonderful! Thanks for comments, as well! 🍻

@@ -54,7 +60,7 @@ func NewManager(api tasks.DataSource, strg model.Storage, name string, opts ...M
opt(im)
}

im.indexBuilder = NewBuilder(api, name)
im.indexBuilder = idxBuilder

if im.exporter == nil {
im.exporter = indexer.NewModelExporter(name)
Copy link
Contributor

Choose a reason for hiding this comment

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

The stuttering on name in the function signature suggests you could collapse it into the builder. Making the builder responsible for the name gives you a cleaner signature.

func NewManager(strg model.Storage, idxBuilder tipset.IndexerBuilder, opts ...ManagerOpt) (*Manager, error)

Suggested change
im.exporter = indexer.NewModelExporter(name)
im.exporter = indexer.NewModelExporter(idxBuilder.Name())

Copy link
Member Author

Choose a reason for hiding this comment

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

ohh god idea!


// synchronously export extracted data and its report. If datas at this height are currently being persisted this method will block to avoid deadlocking the database.
if err := i.exporter.ExportResult(ctx, i.storage, int64(ts.Height()), modelResults); err != nil {
if len(modelResults) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

If you put this check inside ExportResult, then the dev doesn't need to worry about this case before consuming it. According to the godoc there, you could return a nil error and not break the semantics.

require.True(t, success)
}

func TestManagerStatusOKAndError(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to see this test name in the failure output and understand what is being protected. Something like:

Suggested change
func TestManagerStatusOKAndError(t *testing.T) {
func TestManagerResultsContainingErrorReturnsError(t *testing.T) {


}

func TestManagerStatusOKAndSkip(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func TestManagerStatusOKAndSkip(t *testing.T) {
func TestManagerResultsContainingSkipReturnsError(t *testing.T) {

success, err := manager.TipSet(ctx, ts1)
require.NoError(t, err)
require.False(t, success)
}
Copy link
Contributor

@placer14 placer14 Jun 14, 2022

Choose a reason for hiding this comment

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

success, err := manager.TipSet(ctx, ts1)
require.Error(t, err)
require.False(t, success)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

@frrist frrist Jun 15, 2022

Choose a reason for hiding this comment

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

Could you tell or show me what is being repeated? A lot of the setup is the same, but the tests validate different things.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I started to recontextualize what I was thinking here (I should've been more descriptive) and abandoned for other tasks. It's not a big deal if there's double coverage, if at all. It just seemed there was overlapping coverage in these examples. Nit only.

require.False(t, success)
}

func TestManagerFatalErrorAndOkReport(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func TestManagerFatalErrorAndOkReport(t *testing.T) {
func TestManagerFatalErrorDoesntBlockOkReport(t *testing.T) {

@frrist frrist force-pushed the frrist/manager-test branch from f63b805 to e9515ea Compare June 16, 2022 15:42
@frrist frrist merged commit 56fcf12 into master Jun 16, 2022
@frrist frrist deleted the frrist/manager-test branch June 16, 2022 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants