Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

swarm/network: Add tests for complex connectivity evaluations #1069

Closed
wants to merge 36 commits into from

Conversation

nolash
Copy link
Contributor

@nolash nolash commented Dec 18, 2018

This PR adds tests for all kademlia connectivity conditions relevant to the peer discovery mechanisms. This is a preparatory step to verify the correctness of the SuggestPeer component.

It also adds tests for less naïve health evaluations, to inform simulation implementations that would be interested in this information.

Added tests are:

  • Bins shallower than depth are connected to minimum of peers if we know any peers in them
  • Unit test for saturation calculation

Merge dependencies (in order of merge to master):

// evaluates healthiness by taking into account potential connections
// additional conditions for healthiness
// - IF we know of peers in bins shallower than depth, connected to at least HealthBinSize of them
func assertHealthPotential(t *testing.T, k *Kademlia, expectHealthyAndPotent bool) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

testing.T is not used in this function. If you just call t.Fatal instead of returning the error, this assert function will be more compact and easier to use in tests.

Register(k, "00000000")
log.Trace(k.String())
if err := assertHealthSimple(t, k, true); err != nil {
t.Fatal(err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you pass testing.T to the assert function, you can just call t.Fatal inside and refactor all test code, to have an assert on one line, and not three, when you no longer have to return the error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I prefer to know the line it failed :)

Copy link
Member

Choose a reason for hiding this comment

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

t.Helper() will take care of that

// in order deepest to shallowest compared to the kademlia base address
depth := depthForPot(k.conns, k.MinProxBinSize, k.base)
k.eachAddr(nil, depth, func(_ *BzzAddr, po int, _ bool) bool {
pk[uint8(po)]++
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably a good idea to extract Po as a type, because we use it as uint8 and int at different places. Or at the very least be consistent about its type.

Doesn't have to be addressed in this PR, but we shouldn't have to do conversions here.

@nolash
Copy link
Contributor Author

nolash commented Dec 19, 2018

@nonsense thanks for the comments, this is still WIP though...

Copy link
Contributor

@holisticode holisticode left a comment

Choose a reason for hiding this comment

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

Brilliant work!

Very nice tests, IMHO dramatically improves confidence in swarm's network reliance once we have this sorted out.

I bumped into some early questions which seem to have been cleared later on while going through the PR. I left them nevertheless, they might give suggestions for selectively improving the code comments at your discretion.

}

// NewKadParams returns a params struct with default values
func NewKadParams() *KadParams {
return &KadParams{
MaxProxDisplay: 16,
MinProxBinSize: 2,
HealthBinSize: 1,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is 1 really a good value here? Do we need a HealthBinSize at all if its default value is 1

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well it could be 2 in the future. And 1 is not 0.

type KadParams struct {
// adjustable parameters
MaxProxDisplay int // number of rows the table shows
MinProxBinSize int // nearest neighbour core minimum cardinality
HealthBinSize int // number of connections out of known peers in a bin to be considered healthy
Copy link
Contributor

@holisticode holisticode Jan 8, 2019

Choose a reason for hiding this comment

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

Why do we need a HealthBinSize if we have MinBinSize? What's the role of MinBinSize then? Can't we just use MinBinSize for HealthBinSize?

Copy link
Contributor Author

@nolash nolash Jan 11, 2019

Choose a reason for hiding this comment

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

MinBinSize is how many peers to we ideally want in a bin (shallower than depth), if they are available.

HealthBinSize is how many peers do we need in a bin to consider the domain shallower than depth healthy.

The former term is not intuitive, perhaps.

swarm/network/kademlia.go Show resolved Hide resolved
swarm/network/kademlia.go Show resolved Hide resolved
swarm/network/kademlia.go Show resolved Hide resolved
swarm/network/kademlia_test.go Show resolved Hide resolved

// know three peers, connected to the two deepest
// healthy but not potent
Register(k, "00000000")
Copy link
Contributor

Choose a reason for hiding this comment

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

So what is the semantics of impotent? Is it a fatal issue? Is it something which can be ignored, as the test says, its potentially unhealthy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The way I understand the current concept, we're not "healthy" if we are not "potent." We need to know and be connected to all neighbours and we need peers in every shallower bin, provided that they exist.

swarm/network/kademlia_test.go Outdated Show resolved Hide resolved
peer = newTestDiscoveryPeer(addr, k)
k.On(peer)
assertHealthSaturation(t, k, 0)
}
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 maybe need a test where saturation is depth at max?

Copy link
Contributor Author

@nolash nolash Jan 9, 2019

Choose a reason for hiding this comment

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

You mean that all bins are saturated and what happens then? I think yes, you're right.

log.Debug("kademlia", "connectNN", h.ConnectNN, "knowNN", h.KnowNN)
log.Debug("kademlia", "health", h.ConnectNN && h.KnowNN, "addr", hex.EncodeToString(k.BaseAddr()), "node", id)
log.Debug("kademlia", "ill condition", !h.ConnectNN, "addr", hex.EncodeToString(k.BaseAddr()), "node", id)
if !h.ConnectNN {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't we need to check all the Saturation and Potent etc. members here? .E.g
h.ConnectNN && h.KnowNN && h.CountKnowNN > 0

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it should probably have Potent. Actually, we should probably discuss with @janos exactly what and how we wait for.

Saturation has to do with discovery of peers, and does not affect "healthy" in the way we use the term.

@nolash
Copy link
Contributor Author

nolash commented Jan 14, 2019

Obsoleted by #1108

@nolash nolash closed this Jan 14, 2019
@frncmx frncmx deleted the you-fill-me-up branch January 22, 2019 09:33
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants