OverviewFilesCommitsIssuesDocsReleasesPeers

godot-keet commits / cd84d7f

Update admin channel tests for MetadataBase Autobase sync
Remove admin channel tests (T1, T3, T4, T9) — admin channel sync replaced by Protomux writer exchange in MetadataBase. Add meta.key deterministic bootstrap key test. Renumber remaining tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cd84d7fd98d3503ca1b8c1694b693c17c508d575
by plankatron <fleeky@gmail.com> · 2026-02-22T17:28:35.000Z

Changed files (1) +53 -134

tests/test-admin-channel.mjs +53 -134
……@@ -1,19 +1,16 @@
11/**
2 * test-admin-channel.mjs — Admin channel replication + protection tests
2 * test-admin-channel.mjs — MetadataBase Autobase sync tests
33 *
44 * Tests:
5 * 1. meta.set replicates to admin channel (_hs:room-meta posted)
6 * 2. meta.get reads from local cache after set
7 * 3. admin channel room exists and is writable
8 * 4. send route blocks direct writes to admin channel
9 * 5. room.create with roomType creates correct type
10 * 6. room.create without roomType creates Default room
11 * 7. meta.set with null field removes it (not replicated as null)
12 * 8. rapid meta.set calls don't corrupt cache (last-write-wins)
13 * 9. sync reads admin channel messages into cache
14 * 10. admin channel messages with non-meta _hs types are ignored
15 * 11. meta.set for multiple rooms posts separate messages
16 * 12. meta.get for unknown roomId returns empty object
5 * 1. meta.key returns deterministic bootstrap key info
6 * 2. meta.get reads from Autobase after set
7 * 3. room.create with roomType creates correct type
8 * 4. room.create without roomType creates Default room
9 * 5. meta.set with null field removes it
10 * 6. rapid meta.set calls don't corrupt (last-write-wins)
11 * 7. meta.set for multiple rooms stores separately
12 * 8. meta.get for unknown roomId returns empty object
13 * 9. meta.get is consistent after multiple operations
1714 *
1815 * Requires: keet-daemon running on /tmp/keet-daemon.sock
1916 * Usage: bare tests/test-admin-channel.mjs
……@@ -24,7 +21,6 @@ import FramedStream from 'framed-stream'
2421import b4a from 'b4a'
2522
2623const SOCKET = '/tmp/keet-daemon.sock'
27const ADMIN_CHANNEL = '98q5xy39rsibzjaxt6bjau5y9qfcjzk6phird399tpbq377uzkio'
2824let rpcId = 0
2925let passed = 0
3026let failed = 0
……@@ -73,7 +69,7 @@ function assert (condition, label) {
7369}
7470
7571async function run () {
76 console.log('=== Admin Channel Regression Tests ===\n')
72 console.log('=== MetadataBase Autobase Sync Tests ===\n')
7773 const client = connect()
7874
7975 // Find or create dedicated test room (never pollute real rooms)
……@@ -91,54 +87,38 @@ async function run () {
9187 Bare.exit(1)
9288 }
9389 const roomId = testRoom.roomId || testRoom.id
94 // Second test room: pick any other non-admin room
90 // Second test room: pick any other room
9591 const chatRooms = rooms.filter(r => {
9692 const id = r.roomId || r.id
97 return id !== roomId && id !== ADMIN_CHANNEL && id !== 'nbpfz7aw1k8uko7usjjzatfjbao8mudyd45kyj4a6aknwb45341o'
93 return id !== roomId
9894 })
9995 const secondRoom = chatRooms.length > 0 ? chatRooms[0] : null
100 console.log(`Test room: "${testRoom.title}" (${roomId.slice(0, 12)}...)`)
101 console.log(`Admin channel: ${ADMIN_CHANNEL.slice(0, 12)}...\n`)
96 console.log(`Test room: "${testRoom.title}" (${roomId.slice(0, 12)}...)\n`)
10297
10398 const marker = 'regression-' + Date.now()
10499
105 // === T1: meta.set replicates to admin channel ===
106 console.log('--- T1: meta.set replicates to admin channel ---')
100 // === T1: meta.key returns deterministic bootstrap key ===
101 console.log('--- T1: meta.key returns deterministic bootstrap key ---')
107102 try {
108 await client.call('meta.set', {
109 roomId,
110 metadata: { topics: [marker], discoverable: true, category: 'test' }
111 })
112 passed++
113 console.log(' OK: meta.set returned')
114
115 await new Promise(r => setTimeout(r, 2000))
116
117 const msgs = await client.call('read', { roomId: ADMIN_CHANNEL, limit: 20, reverse: true })
118 const messages = Array.isArray(msgs) ? msgs : (msgs?.messages || msgs?.data || [])
119 let found = false
120 for (const m of messages) {
121 const text = m.chat?.text || m.text || m.message?.text || ''
122 if (!text.startsWith('{"_hs":')) continue
123 try {
124 const parsed = JSON.parse(text)
125 if (parsed._hs === 'room-meta' && parsed.roomId === roomId && parsed.topics?.includes(marker)) {
126 found = true
127 break
128 }
129 } catch {}
130 }
131 assert(found, 'admin channel contains _hs:room-meta with marker')
103 const keyResult = await client.call('meta.key')
104 assert(keyResult.key !== null, 'meta.key returns bootstrap key')
105 assert(keyResult.writable === true, 'local peer is writable')
106 assert(keyResult.localKey !== null, 'has local writer key')
107 assert(typeof keyResult.key === 'string' && keyResult.key.length === 64, 'key is 64-char hex')
132108 } catch (err) {
133109 console.log(` FAIL: ${err.message}`)
134110 failed++
135111 }
136112
137 // === T2: meta.get reads local cache ===
138 console.log('\n--- T2: meta.get reads local cache ---')
113 // === T2: meta.get reads Autobase after set ===
114 console.log('\n--- T2: meta.get reads Autobase after set ---')
139115 try {
116 await client.call('meta.set', {
117 roomId,
118 metadata: { topics: [marker], discoverable: true, category: 'test' }
119 })
140120 const meta = await client.call('meta.get', { roomId })
141 assert(meta.topics?.includes(marker), 'local cache has marker topic')
121 assert(meta.topics?.includes(marker), 'Autobase has marker topic')
142122 assert(meta.discoverable === true, 'discoverable preserved')
143123 assert(meta.category === 'test', 'category preserved')
144124 } catch (err) {
……@@ -146,36 +126,8 @@ async function run () {
146126 failed++
147127 }
148128
149 // === T3: admin channel room info ===
150 console.log('\n--- T3: admin channel room exists ---')
151 try {
152 const info = await client.call('room', { roomId: ADMIN_CHANNEL })
153 assert(info !== null, 'admin channel room exists')
154 assert(info.status?.isWritable === true, 'admin channel is writable')
155 // keet-core internal: digest.settings.roomType 1 = Default, 2 = Broadcast, 3 = DM
156 // (config.roomType uses compat format: '0' = Default, '1' = Broadcast, '2' = DM)
157 const roomType = info.digest?.settings?.roomType
158 assert(roomType === 1, `admin channel is Default type (digest.roomType=${roomType})`)
159 } catch (err) {
160 console.log(` FAIL: ${err.message}`)
161 failed++
162 }
163
164 // === T4: send route blocks admin channel ===
165 console.log('\n--- T4: send blocks direct writes to admin channel ---')
166 try {
167 await client.call('send', { roomId: ADMIN_CHANNEL, text: 'should be blocked' })
168 console.log(' FAIL: should have thrown')
169 failed++
170 } catch (err) {
171 assert(
172 err.message.includes('read-only') || err.message.includes('meta.set'),
173 `correctly rejects: ${err.message}`
174 )
175 }
176
177 // === T5: room.create with roomType ===
178 console.log('\n--- T5: room.create with roomType=1 (Broadcast) ---')
129 // === T3: room.create with roomType ===
130 console.log('\n--- T3: room.create with roomType=1 (Broadcast) ---')
179131 let broadcastId = null
180132 try {
181133 const result = await client.call('room.create', { title: '_test-broadcast-' + Date.now(), roomType: '1' })
……@@ -191,8 +143,8 @@ async function run () {
191143 failed++
192144 }
193145
194 // === T6: room.create without roomType ===
195 console.log('\n--- T6: room.create without roomType (Default) ---')
146 // === T4: room.create without roomType ===
147 console.log('\n--- T4: room.create without roomType (Default) ---')
196148 let defaultId = null
197149 try {
198150 const result = await client.call('room.create', { title: '_test-default-' + Date.now() })
……@@ -208,20 +160,20 @@ async function run () {
208160 failed++
209161 }
210162
211 // === T7: meta.set null removes field ===
212 console.log('\n--- T7: meta.set null removes field ---')
163 // === T5: meta.set null removes field ===
164 console.log('\n--- T5: meta.set null removes field ---')
213165 try {
214166 await client.call('meta.set', { roomId, metadata: { category: null } })
215167 const meta = await client.call('meta.get', { roomId })
216 assert(meta.category === undefined, 'null field removed from cache')
168 assert(meta.category === undefined, 'null field removed')
217169 assert(meta.topics?.includes(marker), 'other fields preserved')
218170 } catch (err) {
219171 console.log(` FAIL: ${err.message}`)
220172 failed++
221173 }
222174
223 // === T8: rapid meta.set (last-write-wins) ===
224 console.log('\n--- T8: rapid meta.set last-write-wins ---')
175 // === T6: rapid meta.set (last-write-wins) ===
176 console.log('\n--- T6: rapid meta.set last-write-wins ---')
225177 try {
226178 // Fire 3 rapid sets
227179 await client.call('meta.set', { roomId, metadata: { topics: ['first'] } })
……@@ -229,65 +181,21 @@ async function run () {
229181 await client.call('meta.set', { roomId, metadata: { topics: ['third'] } })
230182
231183 const meta = await client.call('meta.get', { roomId })
232 assert(meta.topics?.includes('third'), 'last write wins in cache')
184 assert(meta.topics?.includes('third'), 'last write wins')
233185 assert(!meta.topics?.includes('first'), 'earlier writes overwritten')
234186 } catch (err) {
235187 console.log(` FAIL: ${err.message}`)
236188 failed++
237189 }
238190
239 // === T9: sync reads from admin channel ===
240 console.log('\n--- T9: admin channel has multiple room-meta messages ---')
241 try {
242 await new Promise(r => setTimeout(r, 1000))
243 const msgs = await client.call('read', { roomId: ADMIN_CHANNEL, limit: 50, reverse: false })
244 const messages = Array.isArray(msgs) ? msgs : (msgs?.messages || msgs?.data || [])
245 let metaCount = 0
246 const seenRooms = new Set()
247 for (const m of messages) {
248 const text = m.chat?.text || m.text || m.message?.text || ''
249 if (!text.startsWith('{"_hs":')) continue
250 try {
251 const parsed = JSON.parse(text)
252 if (parsed._hs === 'room-meta' && parsed.roomId) {
253 metaCount++
254 seenRooms.add(parsed.roomId)
255 }
256 } catch {}
257 }
258 assert(metaCount > 0, `found ${metaCount} _hs:room-meta messages in channel`)
259 assert(seenRooms.has(roomId), 'our test room is in channel')
260 } catch (err) {
261 console.log(` FAIL: ${err.message}`)
262 failed++
263 }
264
265 // === T10: non-meta _hs messages in channel are ignored by sync ===
266 console.log('\n--- T10: non-meta messages don\'t affect cache ---')
267 try {
268 // Read current meta for our room
269 const before = await client.call('meta.get', { roomId })
270 const topicsBefore = JSON.stringify(before.topics)
271
272 // The sync should only process _hs:room-meta, not other types
273 // We can't easily inject a non-meta message (send is blocked),
274 // but we verify the cache is consistent after sync
275 assert(before.topics !== undefined, 'cache has topics after sync')
276 assert(typeof before === 'object', 'cache returns object not array')
277 } catch (err) {
278 console.log(` FAIL: ${err.message}`)
279 failed++
280 }
281
282 // === T11: meta.set for multiple rooms ===
283 console.log('\n--- T11: multiple rooms get separate messages ---')
191 // === T7: meta.set for multiple rooms ===
192 console.log('\n--- T7: multiple rooms store separately ---')
284193 if (secondRoom) {
285194 const secondId = secondRoom.roomId || secondRoom.id
286195 try {
287196 const marker2 = 'multi-' + Date.now()
288197 await client.call('meta.set', { roomId, metadata: { topics: [marker2] } })
289198 await client.call('meta.set', { roomId: secondId, metadata: { topics: [marker2 + '-b'] } })
290 await new Promise(r => setTimeout(r, 2000))
291199
292200 const meta1 = await client.call('meta.get', { roomId })
293201 const meta2 = await client.call('meta.get', { roomId: secondId })
……@@ -302,8 +210,8 @@ async function run () {
302210 console.log(' SKIP: only 1 chat room available')
303211 }
304212
305 // === T12: meta.get for unknown roomId ===
306 console.log('\n--- T12: meta.get unknown roomId returns {} ---')
213 // === T8: meta.get for unknown roomId ===
214 console.log('\n--- T8: meta.get unknown roomId returns {} ---')
307215 try {
308216 const meta = await client.call('meta.get', { roomId: 'nonexistent-room-id-12345' })
309217 assert(typeof meta === 'object', 'returns object')
……@@ -313,6 +221,17 @@ async function run () {
313221 failed++
314222 }
315223
224 // === T9: meta.get consistency ===
225 console.log('\n--- T9: meta.get consistent after operations ---')
226 try {
227 const meta = await client.call('meta.get', { roomId })
228 assert(meta.topics !== undefined, 'has topics after all operations')
229 assert(typeof meta === 'object', 'returns object not array')
230 } catch (err) {
231 console.log(` FAIL: ${err.message}`)
232 failed++
233 }
234
316235 // === Cleanup ===
317236 console.log('\n--- Cleanup ---')
318237 try {