func (s *S) TestRetryChangeSetting(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "old", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) err = zk.RetryChange("/test", gozk.EPHEMERAL, []gozk.ACL{}, func(data string, stat gozk.Stat) (string, error) { c.Assert(data, Equals, "old") c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) return "brand new", nil }) c.Assert(err, IsNil) data, stat, err := zk.Get("/test") c.Assert(err, IsNil) c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(1)) c.Assert(data, Equals, "brand new") // ACL was unchanged by RetryChange(). acl, _, err := zk.ACL("/test") c.Assert(err, IsNil) c.Assert(acl, Equals, gozk.WorldACL(gozk.PERM_ALL)) }
func (s *S) TestRetryChangeConflictOnCreate(c *C) { zk, _ := s.init(c) changeFunc := func(data string, stat gozk.Stat) (string, error) { switch data { case "": c.Assert(stat, IsNil) _, err := zk.Create("/test", "conflict", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) return "<none> => conflict", nil case "conflict": c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) return "conflict => new", nil default: c.Fatal("Unexpected node data: " + data) } return "can't happen", nil } err := zk.RetryChange("/test", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL), changeFunc) c.Assert(err, IsNil) data, stat, err := zk.Get("/test") c.Assert(err, IsNil) c.Assert(data, Equals, "conflict => new") c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(1)) }
func (s *S) TestChildrenAndWatch(c *C) { c.Check(gozk.CountPendingWatches(), Equals, 0) zk, _ := s.init(c) c.Check(gozk.CountPendingWatches(), Equals, 1) children, stat, watch, err := zk.ChildrenW("/") c.Assert(err, IsNil) c.Assert(children, Equals, []string{"zookeeper"}) c.Assert(stat.NumChildren(), Equals, int32(1)) select { case <-watch: c.Fatal("Watch fired") default: } c.Check(gozk.CountPendingWatches(), Equals, 2) _, err = zk.Create("/test1", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) event := <-watch c.Assert(event.Type, Equals, gozk.EVENT_CHILD) c.Assert(event.Path, Equals, "/") c.Check(gozk.CountPendingWatches(), Equals, 1) children, stat, watch, err = zk.ChildrenW("/") c.Assert(err, IsNil) c.Assert(stat.NumChildren(), Equals, int32(2)) // The ordering is most likely unstable, so this test must be fixed. c.Assert(children, Equals, []string{"test1", "zookeeper"}) select { case <-watch: c.Fatal("Watch fired") default: } c.Check(gozk.CountPendingWatches(), Equals, 2) _, err = zk.Create("/test2", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) event = <-watch c.Assert(event.Type, Equals, gozk.EVENT_CHILD) c.Check(gozk.CountPendingWatches(), Equals, 1) }
func (s *S) TestCreateAndGet(c *C) { zk, _ := s.init(c) path, err := zk.Create("/test-", "bababum", gozk.SEQUENCE|gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) c.Assert(path, Matches, "/test-[0-9]+") // Check the error condition from Create(). _, err = zk.Create(path, "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, Matches, "node exists") data, _, err := zk.Get(path) c.Assert(err, IsNil) c.Assert(data, Equals, "bababum") }
func (s *S) TestExistsAndWatch(c *C) { c.Check(gozk.CountPendingWatches(), Equals, 0) zk, _ := s.init(c) c.Check(gozk.CountPendingWatches(), Equals, 1) stat, watch, err := zk.ExistsW("/test") c.Assert(err, IsNil) c.Assert(stat, IsNil) c.Check(gozk.CountPendingWatches(), Equals, 2) select { case <-watch: c.Fatal("Watch fired") default: } _, err = zk.Create("/test", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) event := <-watch c.Assert(event.Type, Equals, gozk.EVENT_CREATED) c.Assert(event.Path, Equals, "/test") c.Check(gozk.CountPendingWatches(), Equals, 1) stat, watch, err = zk.ExistsW("/test") c.Assert(err, IsNil) c.Assert(stat, NotNil) c.Assert(stat.NumChildren(), Equals, int32(0)) c.Check(gozk.CountPendingWatches(), Equals, 2) }
func (s *S) TestSetACL(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) err = zk.SetACL("/test", gozk.WorldACL(gozk.PERM_ALL), 5) c.Assert(err, NotNil) c.Assert(err.Code(), Equals, gozk.ZBADVERSION) err = zk.SetACL("/test", gozk.WorldACL(gozk.PERM_READ), -1) c.Assert(err, IsNil) acl, _, err := zk.ACL("/test") c.Assert(err, IsNil) c.Assert(acl, Equals, gozk.WorldACL(gozk.PERM_READ)) }
func (s *S) TestACL(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) acl, stat, err := zk.ACL("/test") c.Assert(err, IsNil) c.Assert(acl, Equals, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) acl, stat, err = zk.ACL("/non-existent") c.Assert(err, NotNil) c.Assert(err.Code(), Equals, gozk.ZNONODE) c.Assert(acl, IsNil) c.Assert(stat, IsNil) }
func (s *S) TestRetryChangeCreating(c *C) { zk, _ := s.init(c) err := zk.RetryChange("/test", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL), func(data string, stat gozk.Stat) (string, error) { c.Assert(data, Equals, "") c.Assert(stat, IsNil) return "new", nil }) c.Assert(err, IsNil) data, stat, err := zk.Get("/test") c.Assert(err, IsNil) c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) c.Assert(data, Equals, "new") acl, _, err := zk.ACL("/test") c.Assert(err, IsNil) c.Assert(acl, Equals, gozk.WorldACL(gozk.PERM_ALL)) }
func (s *S) TestWatchOnReconnection(c *C) { c.Check(gozk.CountPendingWatches(), Equals, 0) zk, session := s.init(c) event := <-session c.Assert(event.Type, Equals, gozk.EVENT_SESSION) c.Assert(event.State, Equals, gozk.STATE_CONNECTED) c.Check(gozk.CountPendingWatches(), Equals, 1) stat, watch, err := zk.ExistsW("/test") c.Assert(err, IsNil) c.Assert(stat, IsNil) c.Check(gozk.CountPendingWatches(), Equals, 2) s.StopZK() time.Sleep(2e9) s.StartZK() // The session channel should receive the reconnection notification, select { case event := <-session: c.Assert(event.State, Equals, gozk.STATE_CONNECTING) case <-time.After(3e9): c.Fatal("Session watch didn't fire") } select { case event := <-session: c.Assert(event.State, Equals, gozk.STATE_CONNECTED) case <-time.After(3e9): c.Fatal("Session watch didn't fire") } // The watch channel should not, since it's not affected. select { case event := <-watch: c.Fatalf("Exists watch fired: %s", event) default: } // And it should still work. _, err = zk.Create("/test", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) event = <-watch c.Assert(event.Type, Equals, gozk.EVENT_CREATED) c.Assert(event.Path, Equals, "/test") c.Check(gozk.CountPendingWatches(), Equals, 1) }
func (s *S) TestRetryChangeConflictOnSetDueToDelete(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "old", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) changeFunc := func(data string, stat gozk.Stat) (string, error) { switch data { case "old": c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) err := zk.Delete("/test", 0) c.Assert(err, IsNil) return "old => <deleted>", nil case "": c.Assert(stat, IsNil) return "<deleted> => new", nil default: c.Fatal("Unexpected node data: " + data) } return "can't happen", nil } err = zk.RetryChange("/test", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_READ), changeFunc) c.Assert(err, IsNil) data, stat, err := zk.Get("/test") c.Assert(err, IsNil) c.Assert(data, Equals, "<deleted> => new") c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) // Should be the new ACL. acl, _, err := zk.ACL("/test") c.Assert(err, IsNil) c.Assert(acl, Equals, gozk.WorldACL(gozk.PERM_READ)) }
func (s *S) TestGetAndWatch(c *C) { c.Check(gozk.CountPendingWatches(), Equals, 0) zk, _ := s.init(c) c.Check(gozk.CountPendingWatches(), Equals, 1) _, err := zk.Create("/test", "one", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) data, stat, watch, err := zk.GetW("/test") c.Assert(err, IsNil) c.Assert(data, Equals, "one") c.Assert(stat.Version(), Equals, int32(0)) select { case <-watch: c.Fatal("Watch fired") default: } c.Check(gozk.CountPendingWatches(), Equals, 2) _, err = zk.Set("/test", "two", -1) c.Assert(err, IsNil) event := <-watch c.Assert(event.Type, Equals, gozk.EVENT_CHANGED) c.Check(gozk.CountPendingWatches(), Equals, 1) data, _, watch, err = zk.GetW("/test") c.Assert(err, IsNil) c.Assert(data, Equals, "two") select { case <-watch: c.Fatal("Watch fired") default: } c.Check(gozk.CountPendingWatches(), Equals, 2) _, err = zk.Set("/test", "three", -1) c.Assert(err, IsNil) event = <-watch c.Assert(event.Type, Equals, gozk.EVENT_CHANGED) c.Check(gozk.CountPendingWatches(), Equals, 1) }
func (s *S) TestRetryChangeFailsCreating(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "old", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_READ)) // Read only! c.Assert(err, IsNil) var called bool err = zk.RetryChange("/test/sub", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL), func(data string, stat gozk.Stat) (string, error) { called = true return "", nil }) c.Assert(err, NotNil) c.Assert(err.Code(), Equals, gozk.ZNOAUTH) stat, err := zk.Exists("/test/sub") c.Assert(err, IsNil) c.Assert(stat, IsNil) c.Assert(called, Equals, true) }
func (s *S) TestRetryChangeFailsReading(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "old", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_WRITE)) // Write only! c.Assert(err, IsNil) var called bool err = zk.RetryChange("/test", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL), func(data string, stat gozk.Stat) (string, error) { called = true return "", nil }) c.Assert(err, NotNil) c.Assert(err.Code(), Equals, gozk.ZNOAUTH) stat, err := zk.Exists("/test") c.Assert(err, IsNil) c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) c.Assert(called, Equals, false) }
func (s *S) TestCreateSetAndGet(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) stat, err := zk.Set("/test", "bababum", -1) // Any version. c.Assert(err, IsNil) c.Assert(stat.Version(), Equals, int32(1)) data, _, err := zk.Get("/test") c.Assert(err, IsNil) c.Assert(data, Equals, "bababum") }
func (s *S) TestRetryChangeErrorInCallback(c *C) { zk, _ := s.init(c) err := zk.RetryChange("/test", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL), func(data string, stat gozk.Stat) (string, error) { return "don't use this", errors.New("BOOM!") }) c.Assert(err, NotNil) c.Assert(err.Code(), Equals, gozk.ZSYSTEMERROR) c.Assert(err.Error(), Equals, "BOOM!") stat, err := zk.Exists("/test") c.Assert(err, IsNil) c.Assert(stat, IsNil) }
// Surprisingly for some (including myself, initially), the watch // returned by the exists method actually fires on data changes too. func (s *S) TestExistsWatchOnDataChange(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) _, watch, err := zk.ExistsW("/test") c.Assert(err, IsNil) _, err = zk.Set("/test", "new", -1) c.Assert(err, IsNil) event := <-watch c.Assert(event.Path, Equals, "/test") c.Assert(event.Type, Equals, gozk.EVENT_CHANGED) }
func (s *S) TestDelete(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) err = zk.Delete("/test", 5) c.Assert(err, NotNil) c.Assert(err.Code(), Equals, gozk.ZBADVERSION) err = zk.Delete("/test", -1) c.Assert(err, IsNil) err = zk.Delete("/test", -1) c.Assert(err, NotNil) c.Assert(err.Code(), Equals, gozk.ZNONODE) }
func (s *S) TestCloseReleasesWatches(c *C) { c.Check(gozk.CountPendingWatches(), Equals, 0) zk, _ := s.init(c) c.Check(gozk.CountPendingWatches(), Equals, 1) _, err := zk.Create("/test", "one", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) _, _, _, err = zk.GetW("/test") c.Assert(err, IsNil) c.Assert(gozk.CountPendingWatches(), Equals, 2) zk.Close() c.Assert(gozk.CountPendingWatches(), Equals, 0) }
func (s *S) TestRetryChangeUnchangedValueDoesNothing(c *C) { zk, _ := s.init(c) _, err := zk.Create("/test", "old", gozk.EPHEMERAL, gozk.WorldACL(gozk.PERM_ALL)) c.Assert(err, IsNil) err = zk.RetryChange("/test", gozk.EPHEMERAL, []gozk.ACL{}, func(data string, stat gozk.Stat) (string, error) { c.Assert(data, Equals, "old") c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) return "old", nil }) c.Assert(err, IsNil) data, stat, err := zk.Get("/test") c.Assert(err, IsNil) c.Assert(stat, NotNil) c.Assert(stat.Version(), Equals, int32(0)) // Unchanged! c.Assert(data, Equals, "old") }