diff --git a/README.md b/README.md index 2f525a27a..22bde6678 100644 --- a/README.md +++ b/README.md @@ -94,21 +94,27 @@ curl -L http://127.0.0.1:4001/v2/keys/message -X PUT -d value="Hello world" } ``` -This response contains four fields. -We will introduce three more fields as we try more commands. +The response object contains several attributes: -1. The action of the request; we set the value via a `PUT` request, thus the action is `set`. +1. `action`: the action of the request that was just made. +The request attempted to modify `node.value` via a `PUT` HTTP request, thus the value of action is `set`. -2. The key of the request; we set `/message` to `Hello world`, so the key field is `/message`. -We use a file system like structure to represent the key-value pairs so each key starts with `/`. +2. `node.key`: the HTTP path the to which the request was made. +We set `/message` to `Hello world`, so the key field is `/message`. +Etcd uses a file-system-like structure to represent the key-value pairs, therefore all keys start with `/`. -3. The current value of the key; we set the value to`Hello world`. +3. `node.value`: the value of the key after resolving the request. +In this case, a successful request was made that attempted to change the node's value to `Hello world`. -4. Modified Index is a unique, monotonically incrementing index created for each change to etcd. -Requests that change the index include `set`, `delete`, `update`, `create` and `compareAndSwap`. -Since the `get` and `watch` commands do not change state in the store, they do not change the index. +4. `node.createdIndex`: an index is a unique, monotonically-incrementing integer created for each change to etcd. +This specific index reflects at which point in the etcd state machine a given key was created. You may notice that in this example the index is `2` even though it is the first request you sent to the server. -This is because there are internal commands that also change the state like adding and syncing servers. +This is because there are internal commands that also change the state behind the scenes like adding and syncing servers. + +5. `node.modifiedIndex`: like `node.createdIndex`, this attribute is also an etcd index. +Actions that cause the value to change include `set`, `delete`, `update`, `create` and `compareAndSwap`. +Since the `get` and `watch` commands do not change state in the store, they do not change the value of `node.modifiedIndex`. + ### Response Headers diff --git a/build.ps1 b/build.ps1 index fb8a386ce..5e022d25f 100644 --- a/build.ps1 +++ b/build.ps1 @@ -4,6 +4,7 @@ $env:GOPATH=$pwd.Path $SRC_DIR="$env:GOPATH/src" $ETCD_DIR="$SRC_DIR/$ETCD_PACKAGE" $env:ETCD_DIR="$SRC_DIR/$ETCD_PACKAGE" +$env:ETCD_TARGET=$pwd.Path $ETCD_BASE=(Split-Path $ETCD_DIR -Parent) if(-not(test-path $ETCD_DIR)){ @@ -11,7 +12,7 @@ if(-not(test-path $ETCD_DIR)){ } if(-not(test-path $ETCD_DIR )){ - cmd /c 'mklink /D "%ETCD_DIR%" ..\..\..\' + cmd /c 'mklink /J "%ETCD_DIR%" %ETCD_TARGET%' } foreach($i in (ls third_party/*)){ diff --git a/scripts/release-version.ps1 b/scripts/release-version.ps1 index 544028440..2f5c24dc4 100644 --- a/scripts/release-version.ps1 +++ b/scripts/release-version.ps1 @@ -2,6 +2,6 @@ $VER=(git describe --tags HEAD) @" -package main -const releaseVersion = "$VER" +package server +const ReleaseVersion = "$VER" "@ \ No newline at end of file diff --git a/server/config.go b/server/config.go index 75585e860..0f27b8674 100644 --- a/server/config.go +++ b/server/config.go @@ -277,7 +277,7 @@ func (c *Config) LoadFlags(arguments []string) error { // Print deprecation warnings on STDERR. f.Visit(func(f *flag.Flag) { if len(newFlagNameLookup[f.Name]) > 0 { - fmt.Fprintf(os.Stderr, "[deprecated] use -%s, not -%s", newFlagNameLookup[f.Name], f.Name) + fmt.Fprintf(os.Stderr, "[deprecated] use -%s, not -%s\n", newFlagNameLookup[f.Name], f.Name) } }) @@ -416,7 +416,7 @@ func (c *Config) Sanitize() error { c.NameFromHostname() } - if c.DataDir == "" && c.Name != "" { + if c.DataDir == "" && c.Name != "" && !c.ShowVersion && !c.ShowHelp { c.DataDirFromName() } diff --git a/server/config_test.go b/server/config_test.go index 002996983..2cab7d610 100644 --- a/server/config_test.go +++ b/server/config_test.go @@ -532,7 +532,7 @@ func TestConfigDeprecatedAddrFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Addr, "127.0.0.1:4002") }) - assert.Equal(t, stderr, "[deprecated] use -addr, not -c") + assert.Equal(t, stderr, "[deprecated] use -addr, not -c\n") } func TestConfigDeprecatedBindAddrFlag(t *testing.T) { @@ -542,7 +542,7 @@ func TestConfigDeprecatedBindAddrFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "") }) - assert.Equal(t, stderr, "[deprecated] use -bind-addr, not -cl", "") + assert.Equal(t, stderr, "[deprecated] use -bind-addr, not -cl\n", "") } func TestConfigDeprecatedCAFileFlag(t *testing.T) { @@ -552,7 +552,7 @@ func TestConfigDeprecatedCAFileFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.CAFile, "/tmp/file.ca", "") }) - assert.Equal(t, stderr, "[deprecated] use -ca-file, not -clientCAFile", "") + assert.Equal(t, stderr, "[deprecated] use -ca-file, not -clientCAFile\n", "") } func TestConfigDeprecatedCertFileFlag(t *testing.T) { @@ -562,7 +562,7 @@ func TestConfigDeprecatedCertFileFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.CertFile, "/tmp/file.cert", "") }) - assert.Equal(t, stderr, "[deprecated] use -cert-file, not -clientCert", "") + assert.Equal(t, stderr, "[deprecated] use -cert-file, not -clientCert\n", "") } func TestConfigDeprecatedKeyFileFlag(t *testing.T) { @@ -572,7 +572,7 @@ func TestConfigDeprecatedKeyFileFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.KeyFile, "/tmp/file.key", "") }) - assert.Equal(t, stderr, "[deprecated] use -key-file, not -clientKey", "") + assert.Equal(t, stderr, "[deprecated] use -key-file, not -clientKey\n", "") } func TestConfigDeprecatedPeersFlag(t *testing.T) { @@ -582,7 +582,7 @@ func TestConfigDeprecatedPeersFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "") }) - assert.Equal(t, stderr, "[deprecated] use -peers, not -C", "") + assert.Equal(t, stderr, "[deprecated] use -peers, not -C\n", "") } func TestConfigDeprecatedPeersFileFlag(t *testing.T) { @@ -592,7 +592,7 @@ func TestConfigDeprecatedPeersFileFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.PeersFile, "/tmp/machines", "") }) - assert.Equal(t, stderr, "[deprecated] use -peers-file, not -CF", "") + assert.Equal(t, stderr, "[deprecated] use -peers-file, not -CF\n", "") } func TestConfigDeprecatedMaxClusterSizeFlag(t *testing.T) { @@ -602,7 +602,7 @@ func TestConfigDeprecatedMaxClusterSizeFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.MaxClusterSize, 5, "") }) - assert.Equal(t, stderr, "[deprecated] use -max-cluster-size, not -maxsize", "") + assert.Equal(t, stderr, "[deprecated] use -max-cluster-size, not -maxsize\n", "") } func TestConfigDeprecatedMaxResultBufferFlag(t *testing.T) { @@ -612,7 +612,7 @@ func TestConfigDeprecatedMaxResultBufferFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.MaxResultBuffer, 512, "") }) - assert.Equal(t, stderr, "[deprecated] use -max-result-buffer, not -m", "") + assert.Equal(t, stderr, "[deprecated] use -max-result-buffer, not -m\n", "") } func TestConfigDeprecatedMaxRetryAttemptsFlag(t *testing.T) { @@ -622,7 +622,7 @@ func TestConfigDeprecatedMaxRetryAttemptsFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.MaxRetryAttempts, 10, "") }) - assert.Equal(t, stderr, "[deprecated] use -max-retry-attempts, not -r", "") + assert.Equal(t, stderr, "[deprecated] use -max-retry-attempts, not -r\n", "") } func TestConfigDeprecatedNameFlag(t *testing.T) { @@ -632,7 +632,7 @@ func TestConfigDeprecatedNameFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Name, "test-name", "") }) - assert.Equal(t, stderr, "[deprecated] use -name, not -n", "") + assert.Equal(t, stderr, "[deprecated] use -name, not -n\n", "") } func TestConfigDeprecatedPeerAddrFlag(t *testing.T) { @@ -642,7 +642,7 @@ func TestConfigDeprecatedPeerAddrFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Peer.Addr, "localhost:7002", "") }) - assert.Equal(t, stderr, "[deprecated] use -peer-addr, not -s", "") + assert.Equal(t, stderr, "[deprecated] use -peer-addr, not -s\n", "") } func TestConfigDeprecatedPeerBindAddrFlag(t *testing.T) { @@ -652,7 +652,7 @@ func TestConfigDeprecatedPeerBindAddrFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:4003", "") }) - assert.Equal(t, stderr, "[deprecated] use -peer-bind-addr, not -sl", "") + assert.Equal(t, stderr, "[deprecated] use -peer-bind-addr, not -sl\n", "") } func TestConfigDeprecatedPeerCAFileFlag(t *testing.T) { @@ -662,7 +662,7 @@ func TestConfigDeprecatedPeerCAFileFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "") }) - assert.Equal(t, stderr, "[deprecated] use -peer-ca-file, not -serverCAFile", "") + assert.Equal(t, stderr, "[deprecated] use -peer-ca-file, not -serverCAFile\n", "") } func TestConfigDeprecatedPeerCertFileFlag(t *testing.T) { @@ -672,7 +672,7 @@ func TestConfigDeprecatedPeerCertFileFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") }) - assert.Equal(t, stderr, "[deprecated] use -peer-cert-file, not -serverCert", "") + assert.Equal(t, stderr, "[deprecated] use -peer-cert-file, not -serverCert\n", "") } func TestConfigDeprecatedPeerKeyFileFlag(t *testing.T) { @@ -682,7 +682,7 @@ func TestConfigDeprecatedPeerKeyFileFlag(t *testing.T) { assert.NoError(t, err) assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "") }) - assert.Equal(t, stderr, "[deprecated] use -peer-key-file, not -serverKey", "") + assert.Equal(t, stderr, "[deprecated] use -peer-key-file, not -serverKey\n", "") } //-------------------------------------- diff --git a/server/util.go b/server/util.go index d124a1fc0..729b64f65 100644 --- a/server/util.go +++ b/server/util.go @@ -37,10 +37,9 @@ func redirect(hostname string, w http.ResponseWriter, req *http.Request) { // slice of the substrings between the separator with all leading and trailing // white space removed, as defined by Unicode. func trimsplit(s, sep string) []string { - raw := strings.Split(s, ",") - trimmed := make([]string, 0) - for _, r := range raw { - trimmed = append(trimmed, strings.TrimSpace(r)) + trimmed := strings.Split(s, sep) + for i := range trimmed { + trimmed[i] = strings.TrimSpace(trimmed[i]) } return trimmed } diff --git a/server/v2/tests/delete_handler_test.go b/server/v2/tests/delete_handler_test.go index d5e1c8206..a7dd6e687 100644 --- a/server/v2/tests/delete_handler_test.go +++ b/server/v2/tests/delete_handler_test.go @@ -26,7 +26,7 @@ func TestV2DeleteKey(t *testing.T) { assert.Equal(t, resp.StatusCode, http.StatusOK) body := tests.ReadBody(resp) assert.Nil(t, err, "") - assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo/bar","modifiedIndex":3,"createdIndex":2}}`, "") + assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo/bar","modifiedIndex":3,"createdIndex":2},"prevNode":{"key":"/foo/bar","value":"XXX","modifiedIndex":2,"createdIndex":2}}`, "") }) } @@ -48,7 +48,7 @@ func TestV2DeleteEmptyDirectory(t *testing.T) { assert.Equal(t, resp.StatusCode, http.StatusOK) body := tests.ReadBody(resp) assert.Nil(t, err, "") - assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2}}`, "") + assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2},"prevNode":{"key":"/foo","dir":true,"modifiedIndex":2,"createdIndex":2}}`, "") }) } @@ -70,7 +70,7 @@ func TestV2DeleteNonEmptyDirectory(t *testing.T) { assert.Equal(t, resp.StatusCode, http.StatusOK) body := tests.ReadBody(resp) assert.Nil(t, err, "") - assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2}}`, "") + assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2},"prevNode":{"key":"/foo","dir":true,"modifiedIndex":2,"createdIndex":2}}`, "") }) } @@ -87,7 +87,7 @@ func TestV2DeleteDirectoryRecursiveImpliesDir(t *testing.T) { assert.Equal(t, resp.StatusCode, http.StatusOK) body := tests.ReadBody(resp) assert.Nil(t, err, "") - assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2}}`, "") + assert.Equal(t, string(body), `{"action":"delete","node":{"key":"/foo","dir":true,"modifiedIndex":3,"createdIndex":2},"prevNode":{"key":"/foo","dir":true,"modifiedIndex":2,"createdIndex":2}}`, "") }) } diff --git a/store/event.go b/store/event.go index 00885af80..cd7e0815d 100644 --- a/store/event.go +++ b/store/event.go @@ -12,8 +12,9 @@ const ( ) type Event struct { - Action string `json:"action"` - Node *NodeExtern `json:"node,omitempty"` + Action string `json:"action"` + Node *NodeExtern `json:"node,omitempty"` + PrevNode *NodeExtern `json:"prevNode,omitempty"` } func newEvent(action string, key string, modifiedIndex, createdIndex uint64) *Event { @@ -34,7 +35,7 @@ func (e *Event) IsCreated() bool { return true } - if e.Action == Set && e.Node.PrevValue == "" { + if e.Action == Set && e.PrevNode == nil { return true } @@ -52,7 +53,7 @@ func (event *Event) Response(currentIndex uint64) interface{} { Action: event.Action, Key: event.Node.Key, Value: event.Node.Value, - PrevValue: event.Node.PrevValue, + PrevValue: event.PrevNode.Value, Index: event.Node.ModifiedIndex, TTL: event.Node.TTL, Expiration: event.Node.Expiration, diff --git a/store/node.go b/store/node.go index 71c0a64d7..e17fcf204 100644 --- a/store/node.go +++ b/store/node.go @@ -231,9 +231,9 @@ func (n *node) Remove(dir, recursive bool, callback func(path string)) *etcdErr. return nil } -func (n *node) Repr(recurisive, sorted bool) NodeExtern { +func (n *node) Repr(recurisive, sorted bool) *NodeExtern { if n.IsDir() { - node := NodeExtern{ + node := &NodeExtern{ Key: n.Path, Dir: true, ModifiedIndex: n.ModifiedIndex, @@ -272,7 +272,7 @@ func (n *node) Repr(recurisive, sorted bool) NodeExtern { return node } - node := NodeExtern{ + node := &NodeExtern{ Key: n.Path, Value: n.Value, ModifiedIndex: n.ModifiedIndex, diff --git a/store/node_extern.go b/store/node_extern.go index 514d5c8cf..1466ea16a 100644 --- a/store/node_extern.go +++ b/store/node_extern.go @@ -10,7 +10,6 @@ import ( // TTL is time to live in second type NodeExtern struct { Key string `json:"key, omitempty"` - PrevValue string `json:"-"` Value string `json:"value,omitempty"` Dir bool `json:"dir,omitempty"` Expiration *time.Time `json:"expiration,omitempty"` @@ -20,7 +19,7 @@ type NodeExtern struct { CreatedIndex uint64 `json:"createdIndex,omitempty"` } -type NodeExterns []NodeExtern +type NodeExterns []*NodeExtern // interfaces for sorting func (ns NodeExterns) Len() int { diff --git a/store/store.go b/store/store.go index 08d585056..0709551ce 100644 --- a/store/store.go +++ b/store/store.go @@ -225,10 +225,9 @@ func (s *store) CompareAndSwap(nodePath string, prevValue string, prevIndex uint s.CurrentIndex++ e := newEvent(CompareAndSwap, nodePath, s.CurrentIndex, n.CreatedIndex) + e.PrevNode = n.Repr(false, false) eNode := e.Node - eNode.PrevValue = n.Value - // if test succeed, write the value n.Write(value, s.CurrentIndex) n.UpdateTTL(expireTime) @@ -267,12 +266,11 @@ func (s *store) Delete(nodePath string, dir, recursive bool) (*Event, error) { nextIndex := s.CurrentIndex + 1 e := newEvent(Delete, nodePath, nextIndex, n.CreatedIndex) + e.PrevNode = n.Repr(false, false) eNode := e.Node if n.IsDir() { eNode.Dir = true - } else { - eNode.PrevValue = n.Value } callback := func(path string) { // notify function @@ -326,6 +324,7 @@ func (s *store) CompareAndDelete(nodePath string, prevValue string, prevIndex ui s.CurrentIndex++ e := newEvent(CompareAndDelete, nodePath, s.CurrentIndex, n.CreatedIndex) + e.PrevNode = n.Repr(false, false) callback := func(path string) { // notify function // notify the watchers with deleted set true @@ -412,6 +411,7 @@ func (s *store) Update(nodePath string, newValue string, expireTime time.Time) ( } e := newEvent(Update, nodePath, nextIndex, n.CreatedIndex) + e.PrevNode = n.Repr(false, false) eNode := e.Node if n.IsDir() && len(newValue) != 0 { @@ -420,7 +420,6 @@ func (s *store) Update(nodePath string, newValue string, expireTime time.Time) ( return nil, etcdErr.NewError(etcdErr.EcodeNotFile, nodePath, currIndex) } - eNode.PrevValue = n.Value n.Write(newValue, nextIndex) eNode.Value = newValue @@ -482,7 +481,7 @@ func (s *store) internalCreate(nodePath string, dir bool, value string, unique, if n.IsDir() { return nil, etcdErr.NewError(etcdErr.EcodeNotFile, nodePath, currIndex) } - eNode.PrevValue, _ = n.Read() + e.PrevNode = n.Repr(false, false) n.Remove(false, false, nil) } else { @@ -557,6 +556,7 @@ func (s *store) DeleteExpiredKeys(cutoff time.Time) { s.CurrentIndex++ e := newEvent(Expire, node.Path, s.CurrentIndex, node.CreatedIndex) + e.PrevNode = node.Repr(false, false) callback := func(path string) { // notify function // notify the watchers with deleted set true diff --git a/store/store_test.go b/store/store_test.go index b29fea627..6a068018d 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -93,7 +93,6 @@ func TestSet(t *testing.T) { assert.Equal(t, e.Action, "set", "") assert.Equal(t, e.Node.Key, "/foo", "") assert.False(t, e.Node.Dir, "") - assert.Equal(t, e.Node.PrevValue, "", "") assert.Equal(t, e.Node.Value, "", "") assert.Nil(t, e.Node.Nodes, "") assert.Nil(t, e.Node.Expiration, "") @@ -106,12 +105,16 @@ func TestSet(t *testing.T) { assert.Equal(t, e.Action, "set", "") assert.Equal(t, e.Node.Key, "/foo", "") assert.False(t, e.Node.Dir, "") - assert.Equal(t, e.Node.PrevValue, "", "") assert.Equal(t, e.Node.Value, "bar", "") assert.Nil(t, e.Node.Nodes, "") assert.Nil(t, e.Node.Expiration, "") assert.Equal(t, e.Node.TTL, 0, "") assert.Equal(t, e.Node.ModifiedIndex, uint64(2), "") + // check prevNode + assert.NotNil(t, e.PrevNode, "") + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "", "") + assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "") // Set /dir as a directory e, err = s.Set("/dir", true, "", Permanent) @@ -119,7 +122,6 @@ func TestSet(t *testing.T) { assert.Equal(t, e.Action, "set", "") assert.Equal(t, e.Node.Key, "/dir", "") assert.True(t, e.Node.Dir, "") - assert.Equal(t, e.Node.PrevValue, "", "") assert.Equal(t, e.Node.Value, "", "") assert.Nil(t, e.Node.Nodes, "") assert.Nil(t, e.Node.Expiration, "") @@ -136,7 +138,6 @@ func TestStoreCreateValue(t *testing.T) { assert.Equal(t, e.Action, "create", "") assert.Equal(t, e.Node.Key, "/foo", "") assert.False(t, e.Node.Dir, "") - assert.Equal(t, e.Node.PrevValue, "", "") assert.Equal(t, e.Node.Value, "bar", "") assert.Nil(t, e.Node.Nodes, "") assert.Nil(t, e.Node.Expiration, "") @@ -149,7 +150,6 @@ func TestStoreCreateValue(t *testing.T) { assert.Equal(t, e.Action, "create", "") assert.Equal(t, e.Node.Key, "/empty", "") assert.False(t, e.Node.Dir, "") - assert.Equal(t, e.Node.PrevValue, "", "") assert.Equal(t, e.Node.Value, "", "") assert.Nil(t, e.Node.Nodes, "") assert.Nil(t, e.Node.Expiration, "") @@ -195,10 +195,15 @@ func TestStoreUpdateValue(t *testing.T) { assert.Equal(t, e.Action, "update", "") assert.Equal(t, e.Node.Key, "/foo", "") assert.False(t, e.Node.Dir, "") - assert.Equal(t, e.Node.PrevValue, "bar", "") assert.Equal(t, e.Node.Value, "baz", "") assert.Equal(t, e.Node.TTL, 0, "") assert.Equal(t, e.Node.ModifiedIndex, uint64(2), "") + // check prevNode + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "bar", "") + assert.Equal(t, e.PrevNode.TTL, 0, "") + assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "") + e, _ = s.Get("/foo", false, false) assert.Equal(t, e.Node.Value, "baz", "") @@ -208,10 +213,15 @@ func TestStoreUpdateValue(t *testing.T) { assert.Equal(t, e.Action, "update", "") assert.Equal(t, e.Node.Key, "/foo", "") assert.False(t, e.Node.Dir, "") - assert.Equal(t, e.Node.PrevValue, "baz", "") assert.Equal(t, e.Node.Value, "", "") assert.Equal(t, e.Node.TTL, 0, "") assert.Equal(t, e.Node.ModifiedIndex, uint64(3), "") + // check prevNode + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "baz", "") + assert.Equal(t, e.PrevNode.TTL, 0, "") + assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(2), "") + e, _ = s.Get("/foo", false, false) assert.Equal(t, e.Node.Value, "", "") } @@ -278,6 +288,10 @@ func TestStoreDeleteValue(t *testing.T) { e, err := s.Delete("/foo", false, false) assert.Nil(t, err, "") assert.Equal(t, e.Action, "delete", "") + // check pervNode + assert.NotNil(t, e.PrevNode, "") + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "bar", "") } // Ensure that the store can delete a directory if recursive is specified. @@ -290,6 +304,10 @@ func TestStoreDeleteDiretory(t *testing.T) { e, err := s.Delete("/foo", true, false) assert.Nil(t, err, "") assert.Equal(t, e.Action, "delete", "") + // check pervNode + assert.NotNil(t, e.PrevNode, "") + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Dir, true, "") // create directory /foo and directory /foo/bar s.Create("/foo/bar", true, "", false, Permanent) @@ -346,6 +364,13 @@ func TestStoreCompareAndDeletePrevValue(t *testing.T) { assert.Nil(t, err, "") assert.Equal(t, e.Action, "compareAndDelete", "") assert.Equal(t, e.Node.Key, "/foo", "") + + // check pervNode + assert.NotNil(t, e.PrevNode, "") + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "bar", "") + assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "") + assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "") } func TestStoreCompareAndDeletePrevValueFailsIfNotMatch(t *testing.T) { @@ -366,6 +391,12 @@ func TestStoreCompareAndDeletePrevIndex(t *testing.T) { e, err := s.CompareAndDelete("/foo", "", 1) assert.Nil(t, err, "") assert.Equal(t, e.Action, "compareAndDelete", "") + // check pervNode + assert.NotNil(t, e.PrevNode, "") + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "bar", "") + assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "") + assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "") } func TestStoreCompareAndDeletePrevIndexFailsIfNotMatch(t *testing.T) { @@ -398,8 +429,14 @@ func TestStoreCompareAndSwapPrevValue(t *testing.T) { e, err := s.CompareAndSwap("/foo", "bar", 0, "baz", Permanent) assert.Nil(t, err, "") assert.Equal(t, e.Action, "compareAndSwap", "") - assert.Equal(t, e.Node.PrevValue, "bar", "") assert.Equal(t, e.Node.Value, "baz", "") + // check pervNode + assert.NotNil(t, e.PrevNode, "") + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "bar", "") + assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "") + assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "") + e, _ = s.Get("/foo", false, false) assert.Equal(t, e.Node.Value, "baz", "") } @@ -424,8 +461,14 @@ func TestStoreCompareAndSwapPrevIndex(t *testing.T) { e, err := s.CompareAndSwap("/foo", "", 1, "baz", Permanent) assert.Nil(t, err, "") assert.Equal(t, e.Action, "compareAndSwap", "") - assert.Equal(t, e.Node.PrevValue, "bar", "") assert.Equal(t, e.Node.Value, "baz", "") + // check pervNode + assert.NotNil(t, e.PrevNode, "") + assert.Equal(t, e.PrevNode.Key, "/foo", "") + assert.Equal(t, e.PrevNode.Value, "bar", "") + assert.Equal(t, e.PrevNode.ModifiedIndex, uint64(1), "") + assert.Equal(t, e.PrevNode.CreatedIndex, uint64(1), "") + e, _ = s.Get("/foo", false, false) assert.Equal(t, e.Node.Value, "baz", "") }