|
@@ -52,7 +52,6 @@ func TestCreateAndGet(t *testing.T) {
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
t.Fatal("Cannot create /fooDir/bar = bar")
|
|
t.Fatal("Cannot create /fooDir/bar = bar")
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func TestUpdateFile(t *testing.T) {
|
|
func TestUpdateFile(t *testing.T) {
|
|
@@ -81,7 +80,6 @@ func TestUpdateFile(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// create a directory, update its ttl, to see if it will be deleted
|
|
// create a directory, update its ttl, to see if it will be deleted
|
|
|
-
|
|
|
|
|
_, err = s.Create("/foo/foo", "", Permanent, 3, 1)
|
|
_, err = s.Create("/foo/foo", "", Permanent, 3, 1)
|
|
|
|
|
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -237,7 +235,6 @@ func TestRemove(t *testing.T) {
|
|
|
if err == nil || err.Error() != "Key Not Found" {
|
|
if err == nil || err.Error() != "Key Not Found" {
|
|
|
t.Fatalf("can get the node after deletion ")
|
|
t.Fatalf("can get the node after deletion ")
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func TestExpire(t *testing.T) {
|
|
func TestExpire(t *testing.T) {
|
|
@@ -280,7 +277,6 @@ func TestExpire(t *testing.T) {
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
t.Fatalf("cannot delete the node before expiration", err.Error())
|
|
t.Fatalf("cannot delete the node before expiration", err.Error())
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func TestTestAndSet(t *testing.T) { // TODO prevValue == nil ?
|
|
func TestTestAndSet(t *testing.T) { // TODO prevValue == nil ?
|
|
@@ -314,70 +310,95 @@ func TestTestAndSet(t *testing.T) { // TODO prevValue == nil ?
|
|
|
if e.PrevValue != "car" || e.Value != "bar" {
|
|
if e.PrevValue != "car" || e.Value != "bar" {
|
|
|
t.Fatalf("[%v/%v] [%v/%v]", e.PrevValue, "car", e.Value, "bar")
|
|
t.Fatalf("[%v/%v] [%v/%v]", e.PrevValue, "car", e.Value, "bar")
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func TestWatch(t *testing.T) {
|
|
func TestWatch(t *testing.T) {
|
|
|
s := New()
|
|
s := New()
|
|
|
// watch at a deeper path
|
|
// watch at a deeper path
|
|
|
- c, _ := s.WatcherHub.watch("/foo/foo/foo", false, 0)
|
|
|
|
|
|
|
+ c, _ := s.Watch("/foo/foo/foo", false, 0, 0, 1)
|
|
|
s.Create("/foo/foo/foo", "bar", Permanent, 1, 1)
|
|
s.Create("/foo/foo/foo", "bar", Permanent, 1, 1)
|
|
|
|
|
|
|
|
e := nonblockingRetrive(c)
|
|
e := nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo/foo/foo" {
|
|
|
|
|
- t.Fatal("watch for Create node fails")
|
|
|
|
|
|
|
+ if e.Key != "/foo/foo/foo" || e.Action != Create {
|
|
|
|
|
+ t.Fatal("watch for Create node fails ", e)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- c, _ = s.WatcherHub.watch("/foo/foo/foo", false, 0)
|
|
|
|
|
|
|
+ c, _ = s.Watch("/foo/foo/foo", false, 0, 1, 1)
|
|
|
s.Update("/foo/foo/foo", "car", Permanent, 2, 1)
|
|
s.Update("/foo/foo/foo", "car", Permanent, 2, 1)
|
|
|
e = nonblockingRetrive(c)
|
|
e = nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo/foo/foo" {
|
|
|
|
|
- t.Fatal("watch for Update node fails")
|
|
|
|
|
|
|
+ if e.Key != "/foo/foo/foo" || e.Action != Update {
|
|
|
|
|
+ t.Fatal("watch for Update node fails ", e)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- c, _ = s.WatcherHub.watch("/foo/foo/foo", false, 0)
|
|
|
|
|
|
|
+ c, _ = s.Watch("/foo/foo/foo", false, 0, 2, 1)
|
|
|
s.TestAndSet("/foo/foo/foo", "car", 0, "bar", Permanent, 3, 1)
|
|
s.TestAndSet("/foo/foo/foo", "car", 0, "bar", Permanent, 3, 1)
|
|
|
e = nonblockingRetrive(c)
|
|
e = nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo/foo/foo" {
|
|
|
|
|
|
|
+ if e.Key != "/foo/foo/foo" || e.Action != TestAndSet {
|
|
|
t.Fatal("watch for TestAndSet node fails")
|
|
t.Fatal("watch for TestAndSet node fails")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- c, _ = s.WatcherHub.watch("/foo/foo/foo", false, 0)
|
|
|
|
|
|
|
+ c, _ = s.Watch("/foo/foo/foo", false, 0, 3, 1)
|
|
|
s.Delete("/foo", true, 4, 1) //recursively delete
|
|
s.Delete("/foo", true, 4, 1) //recursively delete
|
|
|
e = nonblockingRetrive(c)
|
|
e = nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo" {
|
|
|
|
|
- t.Fatal("watch for Delete node fails")
|
|
|
|
|
|
|
+ if e.Key != "/foo" || e.Action != Delete {
|
|
|
|
|
+ t.Fatal("watch for Delete node fails ", e)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// watch at a prefix
|
|
// watch at a prefix
|
|
|
- c, _ = s.WatcherHub.watch("/foo", true, 0)
|
|
|
|
|
|
|
+ c, _ = s.Watch("/foo", true, 0, 4, 1)
|
|
|
s.Create("/foo/foo/boo", "bar", Permanent, 5, 1)
|
|
s.Create("/foo/foo/boo", "bar", Permanent, 5, 1)
|
|
|
e = nonblockingRetrive(c)
|
|
e = nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo/foo/boo" {
|
|
|
|
|
|
|
+ if e.Key != "/foo/foo/boo" || e.Action != Create {
|
|
|
t.Fatal("watch for Create subdirectory fails")
|
|
t.Fatal("watch for Create subdirectory fails")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- c, _ = s.WatcherHub.watch("/foo", true, 0)
|
|
|
|
|
|
|
+ c, _ = s.Watch("/foo", true, 0, 5, 1)
|
|
|
s.Update("/foo/foo/boo", "foo", Permanent, 6, 1)
|
|
s.Update("/foo/foo/boo", "foo", Permanent, 6, 1)
|
|
|
e = nonblockingRetrive(c)
|
|
e = nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo/foo/boo" {
|
|
|
|
|
|
|
+ if e.Key != "/foo/foo/boo" || e.Action != Update {
|
|
|
t.Fatal("watch for Update subdirectory fails")
|
|
t.Fatal("watch for Update subdirectory fails")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- c, _ = s.WatcherHub.watch("/foo", true, 0)
|
|
|
|
|
|
|
+ c, _ = s.Watch("/foo", true, 0, 6, 1)
|
|
|
s.TestAndSet("/foo/foo/boo", "foo", 0, "bar", Permanent, 7, 1)
|
|
s.TestAndSet("/foo/foo/boo", "foo", 0, "bar", Permanent, 7, 1)
|
|
|
e = nonblockingRetrive(c)
|
|
e = nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo/foo/boo" {
|
|
|
|
|
|
|
+ if e.Key != "/foo/foo/boo" || e.Action != TestAndSet {
|
|
|
t.Fatal("watch for TestAndSet subdirectory fails")
|
|
t.Fatal("watch for TestAndSet subdirectory fails")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- c, _ = s.WatcherHub.watch("/foo", true, 0)
|
|
|
|
|
|
|
+ c, _ = s.Watch("/foo", true, 0, 7, 1)
|
|
|
s.Delete("/foo/foo/boo", false, 8, 1)
|
|
s.Delete("/foo/foo/boo", false, 8, 1)
|
|
|
e = nonblockingRetrive(c)
|
|
e = nonblockingRetrive(c)
|
|
|
- if e.Key != "/foo/foo/boo" {
|
|
|
|
|
|
|
+ if e.Key != "/foo/foo/boo" || e.Action != Delete {
|
|
|
t.Fatal("watch for Delete subdirectory fails")
|
|
t.Fatal("watch for Delete subdirectory fails")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // watch expire
|
|
|
|
|
+ s.Create("/foo/foo/boo", "foo", time.Now().Add(time.Second*1), 9, 1)
|
|
|
|
|
+ c, _ = s.Watch("/foo", true, 0, 9, 1)
|
|
|
|
|
+ time.Sleep(time.Second * 2)
|
|
|
|
|
+ e = nonblockingRetrive(c)
|
|
|
|
|
+ if e.Key != "/foo/foo/boo" || e.Action != Expire || e.Index != 9 {
|
|
|
|
|
+ t.Fatal("watch for Expiration of Create() subdirectory fails ", e)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ s.Create("/foo/foo/boo", "foo", Permanent, 10, 1)
|
|
|
|
|
+ s.Update("/foo/foo/boo", "bar", time.Now().Add(time.Second*1), 11, 1)
|
|
|
|
|
+ c, _ = s.Watch("/foo", true, 0, 11, 1)
|
|
|
|
|
+ time.Sleep(time.Second * 2)
|
|
|
|
|
+ e = nonblockingRetrive(c)
|
|
|
|
|
+ if e.Key != "/foo/foo/boo" || e.Action != Expire || e.Index != 11 {
|
|
|
|
|
+ t.Fatal("watch for Expiration of Update() subdirectory fails ", e)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ s.Create("/foo/foo/boo", "foo", Permanent, 12, 1)
|
|
|
|
|
+ s.TestAndSet("/foo/foo/boo", "foo", 0, "bar", time.Now().Add(time.Second*1), 13, 1)
|
|
|
|
|
+ c, _ = s.Watch("/foo", true, 0, 13, 1)
|
|
|
|
|
+ time.Sleep(time.Second * 2)
|
|
|
|
|
+ e = nonblockingRetrive(c)
|
|
|
|
|
+ if e.Key != "/foo/foo/boo" || e.Action != Expire || e.Index != 13 {
|
|
|
|
|
+ t.Fatal("watch for Expiration of TestAndSet() subdirectory fails ", e)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func TestSort(t *testing.T) {
|
|
func TestSort(t *testing.T) {
|
|
@@ -442,7 +463,7 @@ func TestSaveAndRecover(t *testing.T) {
|
|
|
b, err := s.Save()
|
|
b, err := s.Save()
|
|
|
|
|
|
|
|
cloneFs := New()
|
|
cloneFs := New()
|
|
|
- time.Sleep(time.Second)
|
|
|
|
|
|
|
+ time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
cloneFs.Recovery(b)
|
|
cloneFs.Recovery(b)
|
|
|
|
|
|
|
@@ -453,11 +474,15 @@ func TestSaveAndRecover(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // lock to avoid racing with Expire()
|
|
|
|
|
+ s.worldLock.RLock()
|
|
|
|
|
+ defer s.worldLock.RUnlock()
|
|
|
|
|
+
|
|
|
if s.WatcherHub.EventHistory.StartIndex != cloneFs.WatcherHub.EventHistory.StartIndex {
|
|
if s.WatcherHub.EventHistory.StartIndex != cloneFs.WatcherHub.EventHistory.StartIndex {
|
|
|
t.Fatal("Error recovered event history start index")
|
|
t.Fatal("Error recovered event history start index")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- for i = 0; int(i) < s.WatcherHub.EventHistory.Queue.Size; i++ {
|
|
|
|
|
|
|
+ for i = 0; int(i) < cloneFs.WatcherHub.EventHistory.Queue.Size; i++ {
|
|
|
if s.WatcherHub.EventHistory.Queue.Events[i].Key !=
|
|
if s.WatcherHub.EventHistory.Queue.Events[i].Key !=
|
|
|
cloneFs.WatcherHub.EventHistory.Queue.Events[i].Key {
|
|
cloneFs.WatcherHub.EventHistory.Queue.Events[i].Key {
|
|
|
t.Fatal("Error recovered event history")
|
|
t.Fatal("Error recovered event history")
|
|
@@ -469,7 +494,6 @@ func TestSaveAndRecover(t *testing.T) {
|
|
|
if err == nil || err.Error() != "Key Not Found" {
|
|
if err == nil || err.Error() != "Key Not Found" {
|
|
|
t.Fatalf("can get the node after deletion ")
|
|
t.Fatalf("can get the node after deletion ")
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// GenKeys randomly generate num of keys with max depth
|
|
// GenKeys randomly generate num of keys with max depth
|
|
@@ -485,6 +509,7 @@ func GenKeys(num int, depth int) []string {
|
|
|
keys[i] += "/" + strconv.Itoa(rand.Int())
|
|
keys[i] += "/" + strconv.Itoa(rand.Int())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
return keys
|
|
return keys
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -504,11 +529,9 @@ func createAndGet(s *Store, path string, t *testing.T) {
|
|
|
if e.Value != "bar" {
|
|
if e.Value != "bar" {
|
|
|
t.Fatalf("expect value of %s is bar [%s]", path, e.Value)
|
|
t.Fatalf("expect value of %s is bar [%s]", path, e.Value)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func recursiveTestSort(k KeyValuePair, t *testing.T) {
|
|
func recursiveTestSort(k KeyValuePair, t *testing.T) {
|
|
|
-
|
|
|
|
|
for i, v := range k.KVPairs[:len(k.KVPairs)-1] {
|
|
for i, v := range k.KVPairs[:len(k.KVPairs)-1] {
|
|
|
if v.Key >= k.KVPairs[i+1].Key {
|
|
if v.Key >= k.KVPairs[i+1].Key {
|
|
|
t.Fatalf("sort failed, [%s] should be placed after [%s]", v.Key, k.KVPairs[i+1].Key)
|
|
t.Fatalf("sort failed, [%s] should be placed after [%s]", v.Key, k.KVPairs[i+1].Key)
|
|
@@ -517,7 +540,6 @@ func recursiveTestSort(k KeyValuePair, t *testing.T) {
|
|
|
if v.Dir {
|
|
if v.Dir {
|
|
|
recursiveTestSort(v, t)
|
|
recursiveTestSort(v, t)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if v := k.KVPairs[len(k.KVPairs)-1]; v.Dir {
|
|
if v := k.KVPairs[len(k.KVPairs)-1]; v.Dir {
|