Skip to content

Commit

Permalink
[FAB-14941] move util.Flatten to localconfig
Browse files Browse the repository at this point in the history
The orderer main uses the function to enumerate the current
configuration.

Change-Id: I8e4363dfd7ac53c356af271b7448915b5c77a230
Signed-off-by: Matthew Sykes <sykesmat@us.ibm.com>
  • Loading branch information
sykesm committed Apr 3, 2019
1 parent 4d26b1e commit ee40591
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 105 deletions.
57 changes: 0 additions & 57 deletions common/util/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"crypto/rand"
"fmt"
"io"
"reflect"
"time"

"github.com/golang/protobuf/ptypes/timestamp"
Expand Down Expand Up @@ -138,59 +137,3 @@ func ConcatenateBytes(data ...[]byte) []byte {
}
return result
}

// `flatten` recursively retrieves every leaf node in a struct in depth-first fashion
// and aggregate the results into given string slice with format: "path.to.leaf = value"
// in the order of definition. Root name is ignored in the path. This helper function is
// useful to pretty-print a struct, such as configs.
// for example, given data structure:
// A{
// B{
// C: "foo",
// D: 42,
// },
// E: nil,
// }
// it should yield a slice of string containing following items:
// [
// "B.C = \"foo\"",
// "B.D = 42",
// "E =",
// ]
func Flatten(i interface{}) []string {
var res []string
flatten("", &res, reflect.ValueOf(i))
return res
}

const DELIMITER = "."

func flatten(k string, m *[]string, v reflect.Value) {
delimiter := DELIMITER
if k == "" {
delimiter = ""
}

switch v.Kind() {
case reflect.Ptr:
if v.IsNil() {
*m = append(*m, fmt.Sprintf("%s =", k))
return
}
flatten(k, m, v.Elem())
case reflect.Struct:
if x, ok := v.Interface().(fmt.Stringer); ok {
*m = append(*m, fmt.Sprintf("%s = %v", k, x))
return
}

for i := 0; i < v.NumField(); i++ {
flatten(k+delimiter+v.Type().Field(i).Name, m, v.Field(i))
}
case reflect.String:
// It is useful to quote string values
*m = append(*m, fmt.Sprintf("%s = \"%s\"", k, v))
default:
*m = append(*m, fmt.Sprintf("%s = %v", k, v))
}
}
46 changes: 0 additions & 46 deletions common/util/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ package util

import (
"bytes"
"fmt"
"reflect"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestComputeSHA256(t *testing.T) {
Expand Down Expand Up @@ -111,45 +107,3 @@ func TestMetadataSignatureBytesNil(t *testing.T) {
t.Errorf("Did not concatenate bytes correctly, expected %s, got %s", expected, result)
}
}

type A struct {
s string
}

type B struct {
A A
i int
X string
}

type C struct{}

type D struct {
B B
c *C
}

func (a A) String() string {
return fmt.Sprintf("I'm '%s'", a.s)
}

func TestFlattenStruct(t *testing.T) {
d := &D{
B: B{
A: A{
s: "foo",
},
i: 42,
X: "bar ",
},
c: nil,
}

var x []string
flatten("", &x, reflect.ValueOf(d))
assert.Equal(t, 4, len(x), "expect 3 items")
assert.Equal(t, x[0], "B.A = I'm 'foo'")
assert.Equal(t, x[1], "B.i = 42")
assert.Equal(t, x[2], "B.X = \"bar \"")
assert.Equal(t, x[3], "c =")
}
68 changes: 68 additions & 0 deletions orderer/common/localconfig/flatten.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package localconfig

import (
"fmt"
"reflect"
)

// Flatten performs a depth-first serialization of a struct to a slice of
// strings. Each string will be formatted at 'path.to.leaf = value'.
func Flatten(i interface{}) []string {
var res []string
flatten("", &res, reflect.ValueOf(i))
return res
}

// flatten recursively retrieves every leaf node in a struct in depth-first fashion
// and aggregate the results into given string slice with format: "path.to.leaf = value"
// in the order of definition. Root name is ignored in the path. This helper function is
// useful to pretty-print a struct, such as configs.
// for example, given data structure:
// A{
// B{
// C: "foo",
// D: 42,
// },
// E: nil,
// }
// it should yield a slice of string containing following items:
// [
// "B.C = \"foo\"",
// "B.D = 42",
// "E =",
// ]
func flatten(k string, m *[]string, v reflect.Value) {
delimiter := "."
if k == "" {
delimiter = ""
}

switch v.Kind() {
case reflect.Ptr:
if v.IsNil() {
*m = append(*m, fmt.Sprintf("%s =", k))
return
}
flatten(k, m, v.Elem())
case reflect.Struct:
if x, ok := v.Interface().(fmt.Stringer); ok {
*m = append(*m, fmt.Sprintf("%s = %v", k, x))
return
}

for i := 0; i < v.NumField(); i++ {
flatten(k+delimiter+v.Type().Field(i).Name, m, v.Field(i))
}
case reflect.String:
// It is useful to quote string values
*m = append(*m, fmt.Sprintf("%s = \"%s\"", k, v))
default:
*m = append(*m, fmt.Sprintf("%s = %v", k, v))
}
}
57 changes: 57 additions & 0 deletions orderer/common/localconfig/flatten_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package localconfig

import (
"fmt"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
)

type A struct {
s string
}

type B struct {
A A
i int
X string
}

type C struct{}

type D struct {
B B
c *C
}

func (a A) String() string {
return fmt.Sprintf("I'm '%s'", a.s)
}

func TestFlattenStruct(t *testing.T) {
d := &D{
B: B{
A: A{
s: "foo",
},
i: 42,
X: "bar ",
},
c: nil,
}

var x []string
flatten("", &x, reflect.ValueOf(d))
assert.Equal(t, 4, len(x), "expect 3 items")
assert.Equal(t, x[0], "B.A = I'm 'foo'")
assert.Equal(t, x[1], "B.i = 42")
assert.Equal(t, x[2], "B.X = \"bar \"")
assert.Equal(t, x[3], "c =")
}
3 changes: 1 addition & 2 deletions orderer/common/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"github.com/hyperledger/fabric/common/metrics"
"github.com/hyperledger/fabric/common/metrics/disabled"
"github.com/hyperledger/fabric/common/tools/protolator"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/comm"
"github.com/hyperledger/fabric/core/operations"
"github.com/hyperledger/fabric/internal/configtxgen/encoder"
Expand Down Expand Up @@ -799,7 +798,7 @@ func (mgr *caManager) updateClusterDialer(
}

func prettyPrintStruct(i interface{}) {
params := util.Flatten(i)
params := localconfig.Flatten(i)
var buffer bytes.Buffer
for i := range params {
buffer.WriteString("\n\t")
Expand Down

0 comments on commit ee40591

Please sign in to comment.