upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests/integration/test-price-discovery.mjs
blob: d7548d3e3790335eeca81f1bc527b0597e5500a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { execSync } from 'child_process';

const BOARD_A_IP = process.env.TOLLGATE_IP || '10.185.47.1';
const BOARD_B_IP = process.env.TOLLGATE_B_IP || process.env.TOLLGATE_IP_B || '10.192.45.1';
const API_A = `http://${BOARD_A_IP}:2121`;
const API_B = `http://${BOARD_B_IP}:2121`;

function run(cmd) {
  try { return execSync(cmd, { encoding: 'utf8', timeout: 15000 }); }
  catch (e) { return e.stdout || null; }
}

function runJson(cmd) {
  const out = run(cmd);
  try { return out ? JSON.parse(out) : null; }
  catch { return null; }
}

let passed = 0, failed = 0;
function assert(cond, msg) {
  if (cond) { console.log(`  PASS: ${msg}`); passed++; }
  else { console.log(`  FAIL: ${msg}`); failed++; }
}

function canReach(url) {
  const result = run(`curl -s --connect-timeout 3 --max-time 5 -o /dev/null -w "%{http_code}" ${url}`);
  return result && result.trim() !== '000' && result.trim() !== '';
}

console.log('=== test-price-discovery (two-board) ===\n');

const reachA = canReach(`${API_A}/market`);
const reachB = canReach(`${API_B}/market`);

console.log(`Reachability: Board A=${reachA ? 'YES' : 'NO'}, Board B=${reachB ? 'YES' : 'NO'}\n`);

if (!reachA && !reachB) {
  console.log('FATAL: Neither board reachable. Check TOLLGATE_IP and TOLLGATE_B_IP');
  process.exit(1);
}

console.log('--- Board A: market endpoint ---');
{
  if (reachA) {
    const data = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_A}/market`);
    assert(data !== null, 'Board A /market returns JSON');
    assert(typeof data?.count === 'number', `Board A count is ${data?.count}`);
    if (data && data.entries) {
      console.log(`  Board A sees ${data.count} nearby TollGate(s):`);
      for (const e of data.entries) {
        console.log(`    ${e.ssid} (BSSID: ${e.bssid}) — ${e.price_per_step} sats/step, RSSI: ${e.rssi}`);
      }
    }
  } else {
    console.log('  SKIP: Board A not reachable');
  }
}

console.log('\n--- Board B: market endpoint ---');
{
  if (reachB) {
    const data = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_B}/market`);
    assert(data !== null, 'Board B /market returns JSON');
    assert(typeof data?.count === 'number', `Board B count is ${data?.count}`);
    if (data && data.entries) {
      console.log(`  Board B sees ${data.count} nearby TollGate(s):`);
      for (const e of data.entries) {
        console.log(`    ${e.ssid} (BSSID: ${e.bssid}) — ${e.price_per_step} sats/step, RSSI: ${e.rssi}`);
      }
    }
  } else {
    console.log('  SKIP: Board B not reachable');
  }
}

console.log('\n--- Cross-discovery: Board A sees Board B ---');
{
  if (reachA) {
    const mktA = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_A}/market`);
    if (mktA && mktA.count > 0) {
      const foundB = mktA.entries.some(e =>
        (e.ssid.startsWith('TollGate-') || e.ssid === 'unknown') && e.bssid !== '' && e.price_per_step > 0
      );
      assert(foundB, `Board A discovered another TollGate (count=${mktA.count})`);
    } else {
      console.log('  INFO: Board A has 0 entries. Scan may need more time.');
    }
  } else {
    console.log('  SKIP: Board A not reachable');
  }
}

console.log('\n--- Cross-discovery: Board B sees Board A ---');
{
  if (reachB) {
    const mktB = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_B}/market`);
    if (mktB && mktB.count > 0) {
      const foundA = mktB.entries.some(e =>
        (e.ssid.startsWith('TollGate-') || e.ssid === 'unknown') && e.bssid !== '' && e.price_per_step > 0
      );
      assert(foundA, `Board B discovered another TollGate (count=${mktB.count})`);
    } else {
      console.log('  INFO: Board B has 0 entries. Scan may need more time.');
    }
  } else {
    console.log('  SKIP: Board B not reachable');
  }
}

console.log('\n--- Discovery data integrity ---');
{
  const boards = [];
  if (reachA) {
    const mktA = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_A}/market`);
    if (mktA?.entries) boards.push({ name: 'A', data: mktA });
  }
  if (reachB) {
    const mktB = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_B}/market`);
    if (mktB?.entries) boards.push({ name: 'B', data: mktB });
  }

  for (const { name, data } of boards) {
    for (const e of data.entries) {
      assert(typeof e.price_per_step === 'number' && e.price_per_step > 0,
        `Board ${name} entry has valid price (${e.price_per_step})`);
      assert(typeof e.step_size === 'number' && e.step_size > 0,
        `Board ${name} entry has valid step_size (${e.step_size})`);
      assert(typeof e.metric === 'string' && e.metric.length > 0,
        `Board ${name} entry has valid metric (${e.metric})`);
      assert(typeof e.rssi === 'number',
        `Board ${name} entry has valid RSSI (${e.rssi})`);
      break;
    }
  }
}

console.log(`\n=== Results: ${passed} passed, ${failed} failed ===`);
process.exit(failed > 0 ? 1 : 0);