Updates
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
require('bare-process/global')
|
||||
const test = require('brittle')
|
||||
const HyperP2PTemporalIndex = require('../index.js')
|
||||
const crypto = require('bare-crypto')
|
||||
const b4a = require('b4a')
|
||||
|
||||
test('hyper-p2p-temporal-index - basic lifecycle and insert', async (t) => {
|
||||
const index = new HyperP2PTemporalIndex({ localId: 'test-peer' })
|
||||
t.ok(index, 'index created')
|
||||
|
||||
const ev = await index.insertEvent({ value: 42, sensor: 'temp' }, { metadata: { source: 'iot' } })
|
||||
t.ok(ev.id, 'event has id')
|
||||
t.ok(ev.timestamp, 'has timestamp')
|
||||
t.ok(ev.signature, 'signed by default')
|
||||
t.is(ev.metadata.source, 'iot')
|
||||
|
||||
const metrics = index.getMetrics()
|
||||
t.is(metrics.inserts, 1)
|
||||
t.is(metrics.eventCount, 1)
|
||||
|
||||
await index.close()
|
||||
})
|
||||
|
||||
test('hyper-p2p-temporal-index - range query and hierarchical bucketing', async (t) => {
|
||||
const index = new HyperP2PTemporalIndex({ enableSigning: true })
|
||||
const now = Date.now()
|
||||
const past = now - 1000 * 60 * 60 // 1 hour ago
|
||||
|
||||
await index.insertEvent({ type: 'log', msg: 'old' }, { timestamp: past })
|
||||
await index.insertEvent({ type: 'log', msg: 'recent' }, { timestamp: now })
|
||||
|
||||
const results = await index.queryRange(past - 1000, now + 1000, { limit: 10, verify: true })
|
||||
t.ok(results.length >= 2, 'retrieved events in range')
|
||||
t.ok(results[0].timestamp <= results[1].timestamp, 'sorted by time')
|
||||
|
||||
await index.close()
|
||||
})
|
||||
|
||||
test('hyper-p2p-temporal-index - nearest query and expiry/prune', async (t) => {
|
||||
const index = new HyperP2PTemporalIndex({ defaultTtlMs: 100 }) // short TTL for test
|
||||
const now = Date.now()
|
||||
|
||||
const ev1 = await index.insertEvent({ v: 1 }, { timestamp: now - 200 })
|
||||
const ev2 = await index.insertEvent({ v: 2 }, { timestamp: now - 100 })
|
||||
|
||||
const nearest = await index.queryNearest(now - 50, { direction: 'before' })
|
||||
t.ok(nearest, 'found nearest before')
|
||||
t.is(nearest.data.v, 2)
|
||||
|
||||
// Force prune
|
||||
await new Promise(r => setTimeout(r, 150))
|
||||
const pruned = await index.pruneExpired(true)
|
||||
t.ok(pruned >= 1, 'pruned expired events')
|
||||
|
||||
const metrics = index.getMetrics()
|
||||
t.ok(metrics.prunes > 0)
|
||||
|
||||
await index.close()
|
||||
})
|
||||
|
||||
test('hyper-p2p-temporal-index - topic derivation and P2P integration', async (t) => {
|
||||
const index = new HyperP2PTemporalIndex()
|
||||
const topic = index.deriveTopic()
|
||||
t.ok(b4a.isBuffer(topic), 'topic is buffer')
|
||||
t.ok(topic.length > 10, 'topic has protocol prefix')
|
||||
|
||||
// Simulate vector clock integration
|
||||
const mockVC = {
|
||||
tick: (id) => ({ [id]: 1 }),
|
||||
compare: (a, b) => 0
|
||||
}
|
||||
index.setVectorClock(mockVC)
|
||||
|
||||
const ev = await index.insertEvent({ test: true })
|
||||
t.ok(ev.vectorClock, 'vector clock attached')
|
||||
|
||||
await index.close()
|
||||
})
|
||||
|
||||
test('hyper-p2p-temporal-index - error handling and graceful close', async (t) => {
|
||||
const index = new HyperP2PTemporalIndex()
|
||||
index.on('error', () => {})
|
||||
|
||||
try {
|
||||
await index.insertEvent(null) // should handle gracefully
|
||||
} catch (e) {
|
||||
t.fail('should not throw on bad data')
|
||||
}
|
||||
|
||||
await index.close()
|
||||
t.pass('closed without error')
|
||||
})
|
||||
|
||||
test('hyper-p2p-temporal-index - metrics and production patterns', async (t) => {
|
||||
const index = new HyperP2PTemporalIndex({ maxEvents: 5 })
|
||||
for (let i = 0; i < 7; i++) {
|
||||
await index.insertEvent({ i })
|
||||
}
|
||||
const m = index.getMetrics()
|
||||
t.ok(m.eventCount <= 5, 'auto-pruned over limit')
|
||||
t.is(m.inserts, 7)
|
||||
|
||||
await index.close()
|
||||
})
|
||||
test('hyper-p2p-temporal-index: close without leak', async (t) => {
|
||||
const m = new HyperP2PTemporalIndex()
|
||||
await m.close()
|
||||
t.pass()
|
||||
})
|
||||
test('hyper-p2p-temporal-index: validation rejects invalid input', async (t) => {
|
||||
const m = new HyperP2PTemporalIndex()
|
||||
try {
|
||||
if (typeof m.addNeighbor === 'function') m.addNeighbor(null)
|
||||
else if (typeof m.buildCircuit === 'function') m.buildCircuit([])
|
||||
else if (typeof m.grant === 'function') m.grant(null, -1)
|
||||
else if (typeof m.enqueue === 'function') m.enqueue('bad', null)
|
||||
else if (typeof m.reportSample === 'function') m.reportSample(null, -1, -1)
|
||||
else if (typeof m.fanout === 'function') m.fanout(null, 0)
|
||||
else if (typeof m.probe === 'function') m.probe(null)
|
||||
else if (typeof m.resolve === 'function') m.resolve(null)
|
||||
else if (typeof m.acquire === 'function') m.acquire(null)
|
||||
else throw new Error('no validation hook')
|
||||
t.fail('expected throw')
|
||||
} catch (err) {
|
||||
t.ok(err instanceof Error)
|
||||
}
|
||||
await m.close()
|
||||
})
|
||||
Reference in New Issue
Block a user