([^<]*)<\/dd>/);
+ return m ? m[1] : null;
+}
+
+function fieldTable(pkt, decoded) {
+ return loadPacketsSandbox()._packetsTestAPI.buildFieldTable(pkt, decoded || {}, [], []);
+}
+
+(async () => {
+ console.log('\n=== packet detail: Hash Size row ===');
+
+ await test('0-hop flood: Hash Size row shows the size the sender set', async () => {
+ assert.strictEqual(await detailHashSizeRow(PACKETS.floodHeardDirect2), '2 bytes');
+ });
+ await test('relayed flood: Hash Size row unchanged', async () => {
+ assert.strictEqual(await detailHashSizeRow(PACKETS.flood1Hop2), '2 bytes');
+ });
+ await test('direct zero-hop: no Hash Size row', async () => {
+ assert.strictEqual(await detailHashSizeRow(PACKETS.directZeroHop), null);
+ });
+ await test('direct with no hops but size bits set: no Hash Size row', async () => {
+ assert.strictEqual(await detailHashSizeRow(PACKETS.directNoHopsSizeBits), null);
+ });
+
+ console.log('\n=== packet detail: hex breakdown Path Length ===');
+
+ await test('0-hop flood: Path Length gives the size, not "direct advert"', () => {
+ const html = fieldTable(PACKETS.floodHeardDirect2);
+ assert.ok(html.includes('hash_size=2 bytes, hash_count=0'), 'got: ' + html);
+ assert.ok(!html.includes('direct advert'), 'a channel message is not an advert');
+ });
+ await test('direct zero-hop: Path Length says no size is encoded', () => {
+ const html = fieldTable(PACKETS.directZeroHop);
+ assert.ok(html.includes('hash_count=0 (no hash size encoded)'), 'got: ' + html);
+ assert.ok(!html.includes('hash_size='), 'no size to show');
+ });
+ await test('relayed flood: Path Length unchanged', () => {
+ assert.ok(fieldTable(PACKETS.flood1Hop2).includes('hash_size=2 bytes, hash_count=1'));
+ });
+
+ console.log('\n=== packet detail: Advertised Hash Size (ADVERT) ===');
+
+ const pubKey = 'C0DEDAD4'.padEnd(64, '0');
+ const advert = (pathByte, routeType) => ({
+ raw_hex: ((4 << 2) | routeType).toString(16).padStart(2, '0') + pathByte + pubKey + '00000000' + '0'.repeat(128),
+ route_type: routeType, payload_type: 4,
+ });
+ const advertSize = (html) => {
+ const m = html.match(/Advertised Hash Size<\/td>| ]*>([^<]*));
+ return m ? m[1] : null;
+ };
+
+ await test('0-hop flood advert: Advertised Hash Size shown', () => {
+ assert.strictEqual(advertSize(fieldTable(advert('80', 1), { type: 'ADVERT', pubKey })), '3 bytes');
+ });
+ await test('direct zero-hop advert: no Advertised Hash Size', () => {
+ assert.strictEqual(advertSize(fieldTable(advert('00', 2), { type: 'ADVERT', pubKey })), null);
+ });
+
+ console.log('');
+ if (failed > 0) {
+ console.error(`❌ ${failed} test(s) failed, ${passed} passed`);
+ process.exit(1);
+ }
+ console.log(`✅ All ${passed} tests passed`);
+})();
diff --git a/tests/unit/test-packets.js b/tests/unit/test-packets.js
index 39072f5cf..e8b5aa621 100644
--- a/tests/unit/test-packets.js
+++ b/tests/unit/test-packets.js
@@ -833,12 +833,12 @@ console.log('\n=== packets.js: buildFieldTable ===');
});
test('buildFieldTable hash_size calculation', () => {
- // Path byte 0xC0 → bits 7-6 = 3 → hash_size = 4, but hash_count = 0
- // Since #653: when hashCount == 0, shows "hash_count=0 (direct advert)" instead of hash_size
- const pkt = { raw_hex: '00C0', route_type: 1, payload_type: 0 };
+ // FLOOD (header 0x01), path byte 0xC0 → bits 7-6 = 3 → hash_size = 4,
+ // reserved (firmware rejects it), hash_count = 0: no size to show.
+ const pkt = { raw_hex: '01C0', route_type: 1, payload_type: 0 };
const decoded = {};
const result = api.buildFieldTable(pkt, decoded, [], []);
- assert(result.includes('hash_count=0 (direct advert)'));
+ assert(result.includes('hash_count=0 (no hash size encoded)'));
});
test('buildFieldTable hash_size shown when hash_count > 0', () => {
|