store: copy Nodes correctly in NodeExtern.Clone

This commit is contained in:
Yicheng Qin 2014-10-29 16:19:18 -07:00
parent b59961228b
commit a910d8ba9f
2 changed files with 35 additions and 11 deletions

View File

@ -77,7 +77,7 @@ func (eNode *NodeExtern) Clone() *NodeExtern {
if eNode == nil { if eNode == nil {
return nil return nil
} }
en := &NodeExtern{ nn := &NodeExtern{
Key: eNode.Key, Key: eNode.Key,
Dir: eNode.Dir, Dir: eNode.Dir,
TTL: eNode.TTL, TTL: eNode.TTL,
@ -86,17 +86,19 @@ func (eNode *NodeExtern) Clone() *NodeExtern {
} }
if eNode.Value != nil { if eNode.Value != nil {
s := *eNode.Value s := *eNode.Value
en.Value = &s nn.Value = &s
} }
if eNode.Expiration != nil { if eNode.Expiration != nil {
t := *eNode.Expiration t := *eNode.Expiration
en.Expiration = &t nn.Expiration = &t
} }
eNode.Nodes = make(NodeExterns, len(en.Nodes)) if eNode.Nodes != nil {
for i, n := range en.Nodes { nn.Nodes = make(NodeExterns, len(eNode.Nodes))
eNode.Nodes[i] = n.Clone() for i, n := range eNode.Nodes {
nn.Nodes[i] = n.Clone()
}
} }
return en return nn
} }
type NodeExterns []*NodeExtern type NodeExterns []*NodeExtern

View File

@ -1,8 +1,10 @@
package store package store
import ( import (
"reflect"
"testing" "testing"
"time" "time"
"unsafe"
) )
import "github.com/coreos/etcd/Godeps/_workspace/src/github.com/stretchr/testify/assert" import "github.com/coreos/etcd/Godeps/_workspace/src/github.com/stretchr/testify/assert"
@ -19,10 +21,13 @@ func TestNodeExternClone(t *testing.T) {
mi uint64 = 321 mi uint64 = 321
) )
var ( var (
val = "some_data" val = "some_data"
valp = &val valp = &val
exp = time.Unix(12345, 67890) exp = time.Unix(12345, 67890)
expp = &exp expp = &exp
child = NodeExtern{}
childp = &child
childs = []*NodeExtern{childp}
) )
eNode = &NodeExtern{ eNode = &NodeExtern{
@ -32,6 +37,7 @@ func TestNodeExternClone(t *testing.T) {
ModifiedIndex: mi, ModifiedIndex: mi,
Value: valp, Value: valp,
Expiration: expp, Expiration: expp,
Nodes: childs,
} }
gNode := eNode.Clone() gNode := eNode.Clone()
@ -43,6 +49,8 @@ func TestNodeExternClone(t *testing.T) {
// values should be the same // values should be the same
assert.Equal(t, *gNode.Value, val) assert.Equal(t, *gNode.Value, val)
assert.Equal(t, *gNode.Expiration, exp) assert.Equal(t, *gNode.Expiration, exp)
assert.Equal(t, len(gNode.Nodes), len(childs))
assert.Equal(t, *gNode.Nodes[0], child)
// but pointers should differ // but pointers should differ
if gNode.Value == eNode.Value { if gNode.Value == eNode.Value {
t.Fatalf("expected value pointers to differ, but got same!") t.Fatalf("expected value pointers to differ, but got same!")
@ -50,6 +58,9 @@ func TestNodeExternClone(t *testing.T) {
if gNode.Expiration == eNode.Expiration { if gNode.Expiration == eNode.Expiration {
t.Fatalf("expected expiration pointers to differ, but got same!") t.Fatalf("expected expiration pointers to differ, but got same!")
} }
if sameSlice(gNode.Nodes, eNode.Nodes) {
t.Fatalf("expected nodes pointers to differ, but got same!")
}
// Original should be the same // Original should be the same
assert.Equal(t, eNode.Key, key) assert.Equal(t, eNode.Key, key)
assert.Equal(t, eNode.TTL, ttl) assert.Equal(t, eNode.TTL, ttl)
@ -57,15 +68,26 @@ func TestNodeExternClone(t *testing.T) {
assert.Equal(t, eNode.ModifiedIndex, mi) assert.Equal(t, eNode.ModifiedIndex, mi)
assert.Equal(t, eNode.Value, valp) assert.Equal(t, eNode.Value, valp)
assert.Equal(t, eNode.Expiration, expp) assert.Equal(t, eNode.Expiration, expp)
if !sameSlice(eNode.Nodes, childs) {
t.Fatalf("expected nodes pointer to same, but got different!")
}
// Change the clone and ensure the original is not affected // Change the clone and ensure the original is not affected
gNode.Key = "/baz" gNode.Key = "/baz"
gNode.TTL = 0 gNode.TTL = 0
gNode.Nodes[0].Key = "uno"
assert.Equal(t, eNode.Key, key) assert.Equal(t, eNode.Key, key)
assert.Equal(t, eNode.TTL, ttl) assert.Equal(t, eNode.TTL, ttl)
assert.Equal(t, eNode.CreatedIndex, ci) assert.Equal(t, eNode.CreatedIndex, ci)
assert.Equal(t, eNode.ModifiedIndex, mi) assert.Equal(t, eNode.ModifiedIndex, mi)
assert.Equal(t, *eNode.Nodes[0], child)
// Change the original and ensure the clone is not affected // Change the original and ensure the clone is not affected
eNode.Key = "/wuf" eNode.Key = "/wuf"
assert.Equal(t, eNode.Key, "/wuf") assert.Equal(t, eNode.Key, "/wuf")
assert.Equal(t, gNode.Key, "/baz") assert.Equal(t, gNode.Key, "/baz")
} }
func sameSlice(a, b []*NodeExtern) bool {
ah := (*reflect.SliceHeader)(unsafe.Pointer(&a))
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
return *ah == *bh
}