@@ -64,3 +64,47 @@ async test "integration: etcd discovery register/resolve/deregister over a real
6464 let after = sock.range({ key: prefix_bytes, range_end, limit: 0 })
6565 assert_eq(after.kvs.length(), 0)
6666}
67+
68+ ///|
69+ async test " integration: etcd watch observes a live PUT over a real watch stream " {
70+ guard @env.get_env_var("MOON_ETCD_TEST ") is Some (_) else { return }
71+ @async.with_task_group(g => {
72+ let key = @utf8.encode("moonzero-ci/watch/probe")
73+ // Clean any leftover on a setup connection.
74+ let setup = EtcdSocket ::connect(etcd_test_host(), 2379)
75+ let _ = setup.delete_range({ key, range_end: b"", prev_kv: false })
76+ setup.close()
77+ // A concurrent publisher Puts the key once the watch has had time to establish.
78+ let putter = g.spawn(() => {
79+ @async.sleep(500)
80+ let pub_conn = EtcdSocket ::connect(etcd_test_host(), 2379)
81+ let _ = pub_conn.put({
82+ key,
83+ value: @utf8.encode("10.0.0.1:9090"),
84+ lease: 0L ,
85+ })
86+ pub_conn.close()
87+ })
88+ // Watch and read the created ack plus the PUT event the publisher triggers.
89+ let sock = EtcdSocket ::connect(etcd_test_host(), 2379)
90+ let responses = sock.watch({ key, range_end: b"", start_revision: 0L }, 2)
91+ sock.close()
92+ let _ = putter.wait()
93+ assert_eq(responses.length() >= 2, true )
94+ assert_eq(responses[0].created, true )
95+ let mut saw_put = false
96+ for r in responses {
97+ for e in r.events {
98+ if e.event_type == @moonzero.EtcdEventType ::Put &&
99+ e.kv.value == @utf8.encode("10.0.0.1:9090") {
100+ saw_put = true
101+ }
102+ }
103+ }
104+ assert_eq(saw_put, true )
105+ // Cleanup.
106+ let cleanup = EtcdSocket ::connect(etcd_test_host(), 2379)
107+ let _ = cleanup.delete_range({ key, range_end: b"", prev_kv: false })
108+ cleanup.close()
109+ })
110+ }
0 commit comments