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

testing (dot) create dot unit tests #1980

Closed
wants to merge 53 commits into from

Conversation

edwardmack
Copy link
Contributor

@edwardmack edwardmack commented Nov 3, 2021

Changes

  • Create unit tests dot package: build_spec_test.go, config_test.go, import_test.go, node_test.go, service_test.go and utils_test.go

Tests

go test ./dot/ -v

Issues

Primary Reviewer

@qdm12
Copy link
Contributor

qdm12 commented Nov 4, 2021

I see a lot of integration tests deltas, is this expected? Did you maybe branch off your other integration tests PR?

TestBuildSpec_ToJSON and TestBuildSpec_ToJSONRaw do not have test for errors with json.Marshal, I don't know how to create condition that will simulate an error with this.

JSON Marshal will fail if you try to marshal e.g. a function/channel. Maybe add some dummy function field to your field struct to trigger an error?

TestWriteGenesisSpecFile doesn't test for errors from os.MkdirAll, I don't know how to create condition to simulate error.

Have a file at the same path 😉 Example

/tmp # touch test
/tmp # mkdir -p test
mkdir: can't create directory 'test': File exists

since these functions build the struct I don't how to compare pointer addresses

Why would we care about the pointer address?

Cleanup after errors

Shouldn't it cleanup even when there is no error? 🤔

Other general comments

  • For testing errors, I would suggest to use (since we already use testify around in the repo):

    if testCase.err != nil {
    	assert.EqualError(t, err, testCase.err.Error())
    } else {
    	assert.NoError(t, err)
    }
  • You can use assert.Equal(t, expected, actual) instead of reflect.DeepEqual + t.Errorf(...) since it does the same thing, it would accelerate test writing/shorten your test code 😉

@edwardmack
Copy link
Contributor Author

I see a lot of integration tests deltas, is this expected? Did you maybe branch off your other integration tests PR?

I did branch off my other integration tests PR, is this a bad idea? Whats the best way to work on stuff that depends on other stuff you've done. I've gotten into git branch trouble before, so I'm open to suggestions of best way to organize this.

JSON Marshal will fail if you try to marshal e.g. a function/channel. Maybe add some dummy function field to your field struct to trigger an error?

I'm no longer sure I need to test for this since the struct passed to this function insures it will not receive a function/channel.

TestWriteGenesisSpecFile doesn't test for errors from os.MkdirAll, I don't know how to create condition to simulate error.

Have a file at the same path wink Example

/tmp # touch test
/tmp # mkdir -p test
mkdir: can't create directory 'test': File exists

I wasn't able to create condition where os.MkdirAll failed.

since these functions build the struct I don't how to compare pointer addresses

Why would we care about the pointer address?

Good point, I've updated tests to compare returned values.

Cleanup after errors

Shouldn't it cleanup even when there is no error? thinking

Yes, good point, I've updated this.

Other general comments

  • For testing errors, I would suggest to use (since we already use testify around in the repo):
    if testCase.err != nil {
    	assert.EqualError(t, err, testCase.err.Error())
    } else {
    	assert.NoError(t, err)
    }
  • You can use assert.Equal(t, expected, actual) instead of reflect.DeepEqual + t.Errorf(...) since it does the same thing, it would accelerate test writing/shorten your test code wink

Updated.

@codecov
Copy link

codecov bot commented Nov 5, 2021

Codecov Report

Merging #1980 (f3936af) into development (1e74231) will increase coverage by 0.59%.
The diff coverage is 61.66%.

Impacted file tree graph

@@               Coverage Diff               @@
##           development    #1980      +/-   ##
===============================================
+ Coverage        61.34%   61.93%   +0.59%     
===============================================
  Files              203      203              
  Lines            27348    27400      +52     
===============================================
+ Hits             16776    16970     +194     
+ Misses            8699     8558     -141     
+ Partials          1873     1872       -1     
Flag Coverage Δ
unit-tests 61.93% <61.66%> (+0.59%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
lib/blocktree/blocktree.go 53.81% <0.00%> (-1.10%) ⬇️
dot/core/service.go 54.84% <57.14%> (-0.60%) ⬇️
lib/babe/verify.go 60.05% <57.14%> (+0.23%) ⬆️
dot/node.go 50.99% <60.43%> (-5.16%) ⬇️
dot/services.go 72.29% <100.00%> (+4.14%) ⬆️
lib/blocktree/node.go 63.50% <0.00%> (-7.30%) ⬇️
dot/network/connmgr.go 89.04% <0.00%> (-1.37%) ⬇️
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1e74231...f3936af. Read the comment docs.

@qdm12
Copy link
Contributor

qdm12 commented Nov 6, 2021

I did branch off my other integration tests PR, is this a bad idea? Whats the best way to work on stuff that depends on other stuff you've done. I've gotten into git branch trouble before, so I'm open to suggestions of best way to organize this.

I'd suggest you point this PR to that other branch you branched out from, merge the second one (this one) first and then the other branch (the first one) in development.

And yes don't worry too much about impossible to reproduce errors 😄 I'll mess around with os.MkdirAll though I'm curious now!

@timwu20
Copy link
Contributor

timwu20 commented Nov 8, 2021

Can you change the base branch of this PR to the other branch you moved the integration tests too? It'll make the diff easier to read.

}{
{
name: "normal conditions",
fields: fields{genesis: &genesis.Genesis{Name: "test"}},
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add more tests to test the other attributes of genesis.Genesis

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added.

@timwu20
Copy link
Contributor

timwu20 commented Nov 8, 2021

I wouldn't worry about trying to test coverage up to 100%. It's not really necessary to test json.Marshal and file read errors if you're already above 70% coverage.

dot/node.go Outdated
@@ -180,7 +180,7 @@ func NodeInitialized(basepath string) bool {
}

// LoadGlobalNodeName returns the stored global node name from database
func LoadGlobalNodeName(basepath string) (nodename string, err error) {
func LoadGlobalNodeName(basepath string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please let's use named returned values, it's really useful for readers/documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated.

if !reflect.DeepEqual(got, tt.want) {
t.Errorf("createCoreService() got = %v, want %v", got, tt.want)
if tt.want != nil {
assert.NotNil(t, got)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe assert it's nil if we expect it to be nil as well 🤔 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, added.

}
})
}
}

func Test_createDigestHandler(t *testing.T) {
cfg := NewTestConfig(t)
require.NotNil(t, cfg)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit I don't think this NotNil is really required since (afaik) we are asserting something from the test (NewTestConfig). Same for below checks as well. Although if these helper functions do use some production code, maybe do the assertion inside them since you are already passing t to them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, removed.

st: stateSrvc,
code: []byte(`fake code`),
},
err: errors.New("failed to create runtime executor: Failed to instantiate the module:\n compile error: Validation error \"Bad magic number\""),
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it us or the runtime returning an error with \n?

Comment on lines 63 to 72
switch blockState.(type) {
case *state.BlockState:
if blockState == (*state.BlockState)(nil) {
return nil, errNilBlockState
}
default:
if reflect.ValueOf(blockState).IsNil() {
return nil, errNilBlockState
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

supernit to reduce code duplication if we add more cases 😉

Suggested change
switch blockState.(type) {
case *state.BlockState:
if blockState == (*state.BlockState)(nil) {
return nil, errNilBlockState
}
default:
if reflect.ValueOf(blockState).IsNil() {
return nil, errNilBlockState
}
}
var isNil bool
switch blockState.(type) {
case *state.BlockState:
isNil = blockState == (*state.BlockState)(nil)
default:
isNil = reflect.ValueOf(blockState).IsNil()
}
if isNil {
return nil, errNilBlockState
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated.

dependabot bot and others added 5 commits December 6, 2021 12:03
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.4.1 to 2.5.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v2.4.1...v2.5.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@edwardmack edwardmack marked this pull request as ready for review December 7, 2021 22:56
Comment on lines +115 to +123
//<<<<<<< HEAD
//=======
//
// bs.genesis.ChainType = expectedChainType
// bs.genesis.Properties = expectedProperties
//
// require.NoError(t, err)
//
// // confirm human-readable fields
Copy link
Contributor

Choose a reason for hiding this comment

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

remove commented out block

// gen := new(genesis.Genesis)
// err = json.Unmarshal(genesisBytes, gen)
// require.NoError(t, err)
//>>>>>>> development
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

return node, nil
}

//InitKeystore to initialize node keystore
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
//InitKeystore to initialize node keystore
// InitKeystore initialised the node's keystore

@@ -41,9 +48,87 @@ type Node struct {
started chan struct{}
}

//go:generate mockgen -source=node.go -destination=mock_node_test.go -package=$GOPACKAGE

type newNodeIface interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

nice! I like this interface a lot, maybe name it nodeBuilder or nodeCreator or something like that?

Comment on lines +52 to +70
var isNilBlock bool
switch blockState.(type) {
case *state.BlockState:
isNilBlock = blockState == (*state.BlockState)(nil)
default:
isNilBlock = reflect.ValueOf(blockState).IsNil()
}
if isNilBlock {
return nil, errNilBlockState
}

if epochState == nil {
var isNilEpoch bool
switch epochState.(type) {
case *state.EpochState:
isNilEpoch = epochState == (*state.EpochState)(nil)
default:
isNilEpoch = reflect.ValueOf(epochState).IsNil()
}
if isNilEpoch {
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 ned this isNilBlock = blockState == (*state.BlockState)(nil) or does reflect.ValueOf(blockState).IsNil() evaluate to the same thing? I'd rather not have the (*state.BlockState) type assertion if possible

@@ -403,7 +403,7 @@ func (bt *BlockTree) StoreRuntime(hash common.Hash, in runtime.Instance) {
// GetBlockRuntime returns block runtime for corresponding block hash.
func (bt *BlockTree) GetBlockRuntime(hash common.Hash) (runtime.Instance, error) {
ins, ok := bt.runtime.Load(hash)
if !ok {
if !ok || ins == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

is ins == nil a case that happens? that seems concerning to me lol

Copy link
Contributor

@noot noot left a comment

Choose a reason for hiding this comment

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

very nice work! just a few comments, but the tests look good to me :D

@edwardmack edwardmack closed this Jan 11, 2022
@edwardmack
Copy link
Contributor Author

closed, replaced by PR #2112

@edwardmack edwardmack deleted the ed/create_dot_unit_tests branch June 21, 2022 14:50
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.

Create dot unit tests
6 participants