Skip to content

Commit 274e38a

Browse files
sirdeggenclaude
andcommitted
test: complete integration test coverage for all 19 overlay topic pairs
Add desktopintegrity, monsterbattle, and utility-tokens test files and update BASELINE.md to reflect 189 passing tests across 19 suites. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7eaf9b7 commit 274e38a

4 files changed

Lines changed: 700 additions & 10 deletions

File tree

packages/overlays/topics/BASELINE.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@
1010
|-------|--------|
1111
| TypeScript | ✅ passes (`tsc --noEmit`) |
1212
| Lint | ⚠️ not yet run (ts-standard) |
13-
| Tests |40 passing (4 suites: any, hello, did, apps) |
13+
| Tests |189 passing, 1 skipped (19 suites: all 19 topic pairs) |
1414

1515
## Coverage
1616

1717
| Metric | Value |
1818
|--------|-------|
19-
| Test suites | 4 passing |
20-
| Tests | 40 passing |
21-
| Topics with TM tests | any, hello, did, apps |
22-
| Topics with LS tests | any, hello (MongoMemoryServer) |
23-
| Topics pending tests | identity, kvstore, basketmap, certmap, protomap, ump, uhrp, fractionalize, desktopintegrity, message-box, monsterbattle, slackthreads, supplychain, utility-tokens, walletconfig |
19+
| Test suites | 19 passing |
20+
| Tests | 189 passing, 1 skipped |
21+
| Topics with TM tests | all 19 topic pairs |
22+
| Topics with LS tests | any, hello, uhrp, walletconfig, message-box, basketmap, protomap, certmap, identity, kvstore, ump, fractionalize, supplychain, slackthreads (MongoMemoryServer) |
23+
| Topics pending tests | none |
2424

2525
## Packages
2626

@@ -65,8 +65,11 @@
6565

6666
## Migration gate
6767

68-
- [x] any, hello, did, apps — TopicManager + LookupService tested
69-
- [ ] Remaining 15 topic pairs need at least one integration test
68+
- [x] any, hello, did, apps — tested
69+
- [x] uhrp, walletconfig, message-box, basketmap, protomap, certmap — tested
70+
- [x] identity, kvstore, ump, fractionalize, supplychain, slackthreads — tested
71+
- [x] desktopintegrity, monsterbattle, utility-tokens — tested
72+
- [x] All 19 topic pairs have at least one integration test
7073
- [ ] Build passes on CI
71-
- [ ] overlay-express-examples imports cleanly (done ✅)
72-
- [ ] All *-services packages re-export from this package (done ✅)
74+
- [x] overlay-express-examples imports cleanly
75+
- [x] All *-services packages re-export from this package
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/**
2+
* Integration tests for DesktopIntegrityTopicManager.
3+
*
4+
* DesktopIntegrityTopicManager validates each output by checking the raw script chunks:
5+
* chunks.length === 2
6+
* chunks[0].op === OP_FALSE (0x00)
7+
* chunks[1].op === OP_RETURN (0x6a)
8+
*
9+
* This is an OP_FALSE OP_RETURN locking script (bare data carrier).
10+
* Any output with exactly these 2 opcodes is admitted.
11+
*/
12+
13+
import { LockingScript, Transaction } from '@bsv/sdk'
14+
import DesktopIntegrityTopicManager from '../desktopintegrity/DesktopIntegrityTopicManager.js'
15+
16+
// ---------------------------------------------------------------------------
17+
// Helpers
18+
// ---------------------------------------------------------------------------
19+
20+
function buildTxWithInput(outputScripts: LockingScript[]): Transaction {
21+
const sourceTx = new Transaction()
22+
sourceTx.addOutput({ lockingScript: new LockingScript([]), satoshis: 10000 })
23+
24+
const tx = new Transaction()
25+
tx.addInput({
26+
sourceTransaction: sourceTx,
27+
sourceOutputIndex: 0,
28+
unlockingScript: new LockingScript([])
29+
})
30+
31+
for (const ls of outputScripts) {
32+
tx.addOutput({ lockingScript: ls, satoshis: 1000 })
33+
}
34+
35+
return tx
36+
}
37+
38+
/**
39+
* Build a valid DesktopIntegrity locking script.
40+
*
41+
* Script: OP_FALSE (0x00) + OP_RETURN (0x6a)
42+
* The source checks exactly 2 chunks: chunks[0].op === OP_FALSE, chunks[1].op === OP_RETURN.
43+
*/
44+
function buildDesktopIntegrityScript(): LockingScript {
45+
return new LockingScript([
46+
{ op: 0x00 }, // OP_FALSE
47+
{ op: 0x6a } // OP_RETURN
48+
])
49+
}
50+
51+
// ---------------------------------------------------------------------------
52+
// Tests
53+
// ---------------------------------------------------------------------------
54+
55+
describe('DesktopIntegrityTopicManager', () => {
56+
let manager: DesktopIntegrityTopicManager
57+
58+
beforeEach(() => {
59+
manager = new DesktopIntegrityTopicManager()
60+
})
61+
62+
it('admits a valid OP_FALSE OP_RETURN output (bare 2-chunk script)', async () => {
63+
const lockingScript = buildDesktopIntegrityScript()
64+
const tx = buildTxWithInput([lockingScript])
65+
66+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
67+
expect(result.outputsToAdmit).toContain(0)
68+
expect(result.coinsToRetain).toEqual([])
69+
})
70+
71+
it('admits multiple valid OP_FALSE OP_RETURN outputs in one transaction', async () => {
72+
const tx = buildTxWithInput([
73+
buildDesktopIntegrityScript(),
74+
buildDesktopIntegrityScript()
75+
])
76+
77+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
78+
expect(result.outputsToAdmit).toContain(0)
79+
expect(result.outputsToAdmit).toContain(1)
80+
})
81+
82+
it('rejects a script with wrong first opcode (not OP_FALSE)', async () => {
83+
// OP_1 (0x51) + OP_RETURN — wrong first opcode
84+
const badScript = new LockingScript([
85+
{ op: 0x51 }, // OP_1
86+
{ op: 0x6a } // OP_RETURN
87+
])
88+
const tx = buildTxWithInput([badScript])
89+
90+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
91+
expect(result.outputsToAdmit).toEqual([])
92+
})
93+
94+
it('rejects a script with wrong second opcode (not OP_RETURN)', async () => {
95+
// OP_FALSE + OP_EQUAL — wrong second opcode
96+
const badScript = new LockingScript([
97+
{ op: 0x00 }, // OP_FALSE
98+
{ op: 0x87 } // OP_EQUAL (wrong)
99+
])
100+
const tx = buildTxWithInput([badScript])
101+
102+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
103+
expect(result.outputsToAdmit).toEqual([])
104+
})
105+
106+
it('rejects a script where the second opcode is not OP_RETURN (uses OP_DROP instead)', async () => {
107+
// OP_FALSE + OP_DROP (0x75) — second opcode is not OP_RETURN
108+
const badScript = new LockingScript([
109+
{ op: 0x00 }, // OP_FALSE
110+
{ op: 0x75 } // OP_DROP (wrong)
111+
])
112+
const tx = buildTxWithInput([badScript])
113+
114+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
115+
expect(result.outputsToAdmit).toEqual([])
116+
})
117+
118+
it('rejects a 1-chunk script (too short)', async () => {
119+
const badScript = new LockingScript([
120+
{ op: 0x6a } // OP_RETURN only
121+
])
122+
const tx = buildTxWithInput([badScript])
123+
124+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
125+
expect(result.outputsToAdmit).toEqual([])
126+
})
127+
128+
it('rejects a P2PKH script', async () => {
129+
const pubkeyHash = new Array(20).fill(0xab)
130+
const badScript = new LockingScript([
131+
{ op: 0x76 }, // OP_DUP
132+
{ op: 0xa9 }, // OP_HASH160
133+
{ op: 20, data: pubkeyHash }, // <20-byte hash>
134+
{ op: 0x88 }, // OP_EQUALVERIFY
135+
{ op: 0xac } // OP_CHECKSIG
136+
])
137+
const tx = buildTxWithInput([badScript])
138+
139+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
140+
expect(result.outputsToAdmit).toEqual([])
141+
})
142+
143+
it('admits only valid outputs when mixed with invalid ones', async () => {
144+
const validScript = buildDesktopIntegrityScript()
145+
const invalidScript = new LockingScript([{ op: 0x51 }]) // OP_1
146+
147+
const tx = buildTxWithInput([invalidScript, validScript])
148+
149+
const result = await manager.identifyAdmissibleOutputs(tx.toBEEF(), [])
150+
expect(result.outputsToAdmit).not.toContain(0)
151+
expect(result.outputsToAdmit).toContain(1)
152+
})
153+
154+
it('returns empty results for malformed BEEF', async () => {
155+
const result = await manager.identifyAdmissibleOutputs([0x00, 0x01], [])
156+
expect(result.outputsToAdmit).toEqual([])
157+
})
158+
159+
it('getDocumentation returns a non-empty string', async () => {
160+
const doc = await manager.getDocumentation()
161+
expect(typeof doc).toBe('string')
162+
expect(doc.length).toBeGreaterThan(0)
163+
})
164+
165+
it('getMetaData returns expected name', async () => {
166+
const meta = await manager.getMetaData()
167+
expect(meta.name).toBe('DesktopIntegrity Topic Manager')
168+
})
169+
})

0 commit comments

Comments
 (0)