Skip to content
Snippets Groups Projects
Commit 3ed599aa authored by Hans Moog's avatar Hans Moog
Browse files

Feat: started adding a stringify package for debugging purposes

To make debugging of the heartbeats a bit easier, this commit adds a stringify package which can show even very complex objects in a nice readable format like:

Heartbeat {
    nodeId: "c0a2918db00514d655f2b82199c6aedda234f807"
    mainStatement: OpinionStatement {
        previousStatementHash: <nil>
        nodeId: "c0a2918db00514d655f2b82199c6aedda234f807"
        time: 1567213114
        toggledTransactions: [
            ToggledTransaction {
                transactionId: 0x29f54622b0df47c864ceca1a5bb4ed84fb7dbbc1b4a6d9a029f79572b86f4d3c68bcca30b08953ac9d217a667facac7d4aa0
                initialStatement: true
                finalStatement: false
            },
            ToggledTransaction {
                transactionId: 0x774f74040c249b73ec4c390352e3191438899c166863b86765e1ef8546ea735bd0ff28dea6e35c9b7d66b35a5703b0c7fe63
                initialStatement: true
                finalStatement: false
            },
        ]
        signature: 0x57fa4ba799a2312b4e8561b144d9386703fce7f128c30c9ec2eeec73693878704d0a176cd4563f5afa8f5ceabdd2552f42bd17cd82363fc0bd1c1386edf914d401
    }
    neighborStatements: map{}
    signature: <nil>
}
parent 1eae8dbc
No related branches found
No related tags found
No related merge requests found
Showing
with 266 additions and 11 deletions
...@@ -12,12 +12,14 @@ require ( ...@@ -12,12 +12,14 @@ require (
github.com/gorilla/websocket v1.4.0 github.com/gorilla/websocket v1.4.0
github.com/iotaledger/iota.go v1.0.0-beta.7 github.com/iotaledger/iota.go v1.0.0-beta.7
github.com/kr/pretty v0.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect
github.com/kr/text v0.1.0
github.com/labstack/echo v3.3.10+incompatible github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.2.9 // indirect github.com/labstack/gommon v0.2.9 // indirect
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.8.1
github.com/rivo/tview v0.0.0-20190721135419-23dc8a0944e4 github.com/rivo/tview v0.0.0-20190721135419-23dc8a0944e4
github.com/rivo/uniseg v0.1.0 // indirect github.com/rivo/uniseg v0.1.0 // indirect
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
github.com/tonnerre/golang-text v0.0.0-20130925195846-048ed3d792f7 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 golang.org/x/net v0.0.0-20190724013045-ca1201d0de80
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e // indirect golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e // indirect
......
...@@ -100,6 +100,8 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH ...@@ -100,6 +100,8 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tonnerre/golang-text v0.0.0-20130925195846-048ed3d792f7 h1:E4pdTAo1tqctAfTr2tkxcX+JkDeJP84bQfjC3ONwoXQ=
github.com/tonnerre/golang-text v0.0.0-20130925195846-048ed3d792f7/go.mod h1:J5H/d3ZVtRUjmP4Zf87sPSIUSCGFXorzn3hQtdODORQ=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
......
...@@ -3,6 +3,8 @@ package heartbeat ...@@ -3,6 +3,8 @@ package heartbeat
import ( import (
"sync" "sync"
"github.com/iotaledger/goshimmer/packages/stringify"
"github.com/iotaledger/goshimmer/packages/errors" "github.com/iotaledger/goshimmer/packages/errors"
"github.com/iotaledger/goshimmer/packages/marshaling" "github.com/iotaledger/goshimmer/packages/marshaling"
...@@ -28,7 +30,7 @@ func NewHeartbeat() *Heartbeat { ...@@ -28,7 +30,7 @@ func NewHeartbeat() *Heartbeat {
func (heartbeat *Heartbeat) GetNodeId() string { func (heartbeat *Heartbeat) GetNodeId() string {
heartbeat.nodeIdMutex.RLock() heartbeat.nodeIdMutex.RLock()
defer heartbeat.nodeIdMutex.RLock() defer heartbeat.nodeIdMutex.RUnlock()
return heartbeat.nodeId return heartbeat.nodeId
} }
...@@ -126,3 +128,12 @@ func (heartbeat *Heartbeat) MarshalBinary() ([]byte, errors.IdentifiableError) { ...@@ -126,3 +128,12 @@ func (heartbeat *Heartbeat) MarshalBinary() ([]byte, errors.IdentifiableError) {
func (heartbeat *Heartbeat) UnmarshalBinary(data []byte) (err errors.IdentifiableError) { func (heartbeat *Heartbeat) UnmarshalBinary(data []byte) (err errors.IdentifiableError) {
return marshaling.Unmarshal(heartbeat, data, &heartbeatProto.HeartBeat{}) return marshaling.Unmarshal(heartbeat, data, &heartbeatProto.HeartBeat{})
} }
func (heartbeat *Heartbeat) String() string {
return stringify.Struct("Heartbeat",
stringify.StructField("nodeId", heartbeat.nodeId),
stringify.StructField("mainStatement", heartbeat.mainStatement),
stringify.StructField("neighborStatements", heartbeat.neighborStatements),
stringify.StructField("signature", heartbeat.signature),
)
}
package heartbeat package heartbeat
import ( import (
"encoding/hex"
"strconv"
"sync" "sync"
"github.com/iotaledger/goshimmer/packages/stringify"
"github.com/iotaledger/goshimmer/packages/errors" "github.com/iotaledger/goshimmer/packages/errors"
"github.com/iotaledger/goshimmer/packages/marshaling" "github.com/iotaledger/goshimmer/packages/marshaling"
...@@ -157,11 +157,11 @@ func (opinionStatement *OpinionStatement) UnmarshalBinary(data []byte) (err erro ...@@ -157,11 +157,11 @@ func (opinionStatement *OpinionStatement) UnmarshalBinary(data []byte) (err erro
} }
func (opinionStatement *OpinionStatement) String() string { func (opinionStatement *OpinionStatement) String() string {
return "OpinionStatement {\n" + return stringify.Struct("OpinionStatement",
" previousStatementHash: 0x" + hex.EncodeToString(opinionStatement.previousStatementHash) + "\n" + stringify.StructField("previousStatementHash", opinionStatement.previousStatementHash),
" nodeId: " + opinionStatement.nodeId + "\n" + stringify.StructField("nodeId", opinionStatement.nodeId),
" time: " + strconv.Itoa(int(opinionStatement.time)) + "\n" + stringify.StructField("time", opinionStatement.time),
" toggledTransactions: [" + "" + "]\n" + stringify.StructField("toggledTransactions", opinionStatement.toggledTransactions),
" signature: 0x" + hex.EncodeToString(opinionStatement.signature) + "\n" + stringify.StructField("signature", opinionStatement.signature),
"}" )
} }
...@@ -3,6 +3,8 @@ package heartbeat ...@@ -3,6 +3,8 @@ package heartbeat
import ( import (
"sync" "sync"
"github.com/iotaledger/goshimmer/packages/stringify"
"github.com/iotaledger/goshimmer/packages/errors" "github.com/iotaledger/goshimmer/packages/errors"
"github.com/iotaledger/goshimmer/packages/marshaling" "github.com/iotaledger/goshimmer/packages/marshaling"
...@@ -89,3 +91,11 @@ func (toggledTransaction *ToggledTransaction) MarshalBinary() ([]byte, errors.Id ...@@ -89,3 +91,11 @@ func (toggledTransaction *ToggledTransaction) MarshalBinary() ([]byte, errors.Id
func (toggledTransaction *ToggledTransaction) UnmarshalBinary(data []byte) (err errors.IdentifiableError) { func (toggledTransaction *ToggledTransaction) UnmarshalBinary(data []byte) (err errors.IdentifiableError) {
return marshaling.Unmarshal(toggledTransaction, data, &heartbeatProto.ToggledTransaction{}) return marshaling.Unmarshal(toggledTransaction, data, &heartbeatProto.ToggledTransaction{})
} }
func (toggledTransaction *ToggledTransaction) String() string {
return stringify.Struct("ToggledTransaction",
stringify.StructField("transactionId", toggledTransaction.transactionId),
stringify.StructField("initialStatement", toggledTransaction.initialStatement),
stringify.StructField("finalStatement", toggledTransaction.finalStatement),
)
}
...@@ -12,8 +12,12 @@ func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) { ...@@ -12,8 +12,12 @@ func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) {
transactionId1 := make([]byte, 50) transactionId1 := make([]byte, 50)
rand.Read(transactionId1) rand.Read(transactionId1)
transactionId2 := make([]byte, 50)
rand.Read(transactionId2)
heartbeatManager := NewHeartbeatManager(identity.GenerateRandomIdentity()) heartbeatManager := NewHeartbeatManager(identity.GenerateRandomIdentity())
heartbeatManager.SetInitialOpinion(transactionId1) heartbeatManager.SetInitialOpinion(transactionId1)
heartbeatManager.SetInitialOpinion(transactionId2)
result, err := heartbeatManager.GenerateHeartbeat() result, err := heartbeatManager.GenerateHeartbeat()
if err != nil { if err != nil {
...@@ -22,5 +26,5 @@ func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) { ...@@ -22,5 +26,5 @@ func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) {
return return
} }
fmt.Println(result.GetMainStatement()) fmt.Println(result)
} }
package stringify
func Bool(value bool) string {
if value {
return "true"
} else {
return "false"
}
}
package stringify
const (
INDENTATION_SIZE = 4
)
package stringify
import (
"strconv"
)
func Int(value int) string {
return strconv.Itoa(value)
}
package stringify
import (
"fmt"
"reflect"
"strconv"
)
func Interface(value interface{}) string {
switch value.(type) {
case bool:
return Bool(value.(bool))
case string:
return String(value.(string))
case []byte:
return SliceOfBytes(value.([]byte))
case int:
return Int(value.(int))
case uint64:
return strconv.FormatUint(value.(uint64), 10)
case reflect.Value:
typeCastedValue := value.(reflect.Value)
switch typeCastedValue.Kind() {
case reflect.Slice:
return sliceReflect(typeCastedValue)
case reflect.String:
return String(typeCastedValue.String())
case reflect.Int:
return Int(int(typeCastedValue.Int()))
case reflect.Uint8:
return Int(int(typeCastedValue.Uint()))
case reflect.Ptr:
return Interface(typeCastedValue.Interface())
default:
panic("undefined reflect type: " + typeCastedValue.Kind().String())
}
case fmt.Stringer:
return value.(fmt.Stringer).String()
default:
value := reflect.ValueOf(value)
switch value.Kind() {
case reflect.Slice:
return sliceReflect(value)
case reflect.Map:
return mapReflect(value)
default:
panic("undefined type: " + value.Kind().String())
}
}
}
package stringify
import (
"reflect"
"strings"
"github.com/kr/text"
)
func Map(value interface{}) string {
return mapReflect(reflect.ValueOf(value))
}
func mapReflect(value reflect.Value) (result string) {
result = "map{"
mapKeys := value.MapKeys()
if len(mapKeys) >= 1 {
result += "\n"
}
for _, mapKey := range mapKeys {
item := value.MapIndex(mapKey)
result += text.Indent("["+Interface(mapKey)+"]: "+Interface(item)+",\n", strings.Repeat(" ", INDENTATION_SIZE))
}
result += "}"
return
}
package stringify
import (
"fmt"
"testing"
)
func TestMap(t *testing.T) {
testMap := make(map[string][]byte)
testMap["huhu"] = []byte{1, 2}
testMap["haha"] = []byte{1, 2, 3, 4}
fmt.Println(Map(testMap))
}
package stringify
import (
"reflect"
"strings"
"github.com/kr/text"
)
func Slice(value []interface{}) string {
return sliceReflect(reflect.ValueOf(value))
}
func sliceReflect(value reflect.Value) (result string) {
result += "["
newLineVersion := false
for i := 0; i < value.Len(); i++ {
item := value.Index(i)
valueString := Interface(item)
if strings.Contains(valueString, "\n") {
if !newLineVersion {
result += "\n"
newLineVersion = true
}
result += text.Indent(Interface(item)+",\n", strings.Repeat(" ", INDENTATION_SIZE))
} else {
result += Interface(item) + ", "
}
}
if !newLineVersion {
result = result[:len(result)-2]
}
result += "]"
return
}
package stringify
import "encoding/hex"
func SliceOfBytes(value []byte) string {
if value == nil {
return "<nil>"
} else if len(value) == 0 {
return "<empty>"
} else {
return "0x" + hex.EncodeToString(value) + ""
}
}
package stringify
func String(value string) string {
return "\"" + value + "\""
}
package stringify
import (
"strings"
"github.com/kr/text"
)
func Struct(name string, fields ...*structField) string {
return structBuilder{
name: name,
fields: fields,
}.String()
}
type structBuilder struct {
name string
fields []*structField
}
func (stringifyStruct structBuilder) String() (result string) {
result = stringifyStruct.name + " {\n"
for _, field := range stringifyStruct.fields {
result += text.Indent(field.String()+"\n", strings.Repeat(" ", INDENTATION_SIZE))
}
result += "}"
return result
}
package stringify
type structField struct {
name string
value interface{}
}
func StructField(name string, value interface{}) *structField {
return &structField{
name: name,
value: value,
}
}
func (structField *structField) String() (result string) {
return structField.name + ": " + Interface(structField.value)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment