storj/pkg/kademlia/testrouting/viz.go
Jennifer Li Johnson b5447c6608
Routing table tests (#1270)
This PR includes a new package called testrouting, which implements a very algorithmically slow but hopefully easy-to-keep-operationally-correct in-memory routing table. The routing table also supports writing out its current structure as a DOT graph for visualization. testrouting is primarily meant to help in coming up with generic routing table integration tests.

This PR also includes a new routing table integration test suite that runs against all current routing table implementations. Our existing routing table passes a lot of the tests, but not all of them, still debugging why. I have confirmed the tests should pass with the visualization graphs though.
2019-02-22 13:39:29 -05:00

49 lines
1.2 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package testrouting
import (
"bytes"
"encoding/hex"
"fmt"
"io"
)
// Graph writes a DOT format visual graph description of the routing table to w
func (t *Table) Graph(w io.Writer) error {
t.mu.Lock()
defer t.mu.Unlock()
var buf bytes.Buffer
buf.Write([]byte("digraph{node [shape=box];"))
t.graph(&buf, t.makeTree())
buf.Write([]byte("}\n"))
_, err := buf.WriteTo(w)
return err
}
func (t *Table) graph(buf *bytes.Buffer, b *bucket) {
if t.splits[b.prefix] {
fmt.Fprintf(buf, "b%s [label=%q];", b.prefix, b.prefix)
if b.similar != nil {
t.graph(buf, b.similar)
t.graph(buf, b.dissimilar)
fmt.Fprintf(buf, "b%s -> {b%s, b%s};",
b.prefix, b.similar.prefix, b.dissimilar.prefix)
}
return
}
// b.prefix is only ever 0s or 1s, so we don't need escaping below.
fmt.Fprintf(buf, "b%s [label=\"%s\nrouting:\\l", b.prefix, b.prefix)
for _, node := range b.nodes {
fmt.Fprintf(buf, " %s\\l", hex.EncodeToString(node.node.Id[:]))
}
fmt.Fprintf(buf, "cache:\\l")
for _, node := range b.cache {
fmt.Fprintf(buf, " %s\\l", hex.EncodeToString(node.node.Id[:]))
}
fmt.Fprintf(buf, "\"];")
}