@harperfast/integration-testing 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,6 +50,34 @@ npx harper-integration-test-setup-loopback
50
50
 
51
51
  This script requires `sudo` and respects the `HARPER_INTEGRATION_TEST_LOOPBACK_POOL_COUNT` environment variable (defaults to 32).
52
52
 
53
+ On macOS the aliases are configured with a host (`/32`) netmask. This matters: with the default class-A (`/8`) netmask every `127.0.0.x` alias claims the whole `127.0.0.0/8` network, and at large pool counts the resulting set of overlapping-subnet interface addresses drives `mDNSResponder`'s address-conflict defense into a CPU-pinning storm of mDNS announcements on port 5353. If you previously ran an older version of this script, re-run it to convert the existing aliases to `/32`.
54
+
55
+ ### Persisting across reboots (macOS)
56
+
57
+ `ifconfig` aliases live only in the running kernel — macOS does not persist manually added `lo0` aliases, so they vanish on every reboot and the pool has to be reconfigured. For a dev machine that reboots regularly, install a `launchd` daemon that runs the setup script at boot. `scripts/io.harperdb.loopback-setup.plist` is provided for this; the script is root-aware, so it needs no `sudo` when launchd runs it as root.
58
+
59
+ ```sh
60
+ # 1. Copy the setup script to a stable, root-owned path (the plist points here)
61
+ sudo mkdir -p /usr/local/sbin
62
+ sudo install -m 755 -o root -g wheel \
63
+ "$(npm root)/@harperfast/integration-testing/scripts/setup-loopback.sh" \
64
+ /usr/local/sbin/harper-loopback-setup.sh
65
+
66
+ # 2. Install the daemon (must be root:wheel and mode 644 or launchd rejects it)
67
+ sudo install -m 644 -o root -g wheel \
68
+ "$(npm root)/@harperfast/integration-testing/scripts/io.harperdb.loopback-setup.plist" \
69
+ /Library/LaunchDaemons/io.harperdb.loopback-setup.plist
70
+
71
+ # 3. Load and run it now (also runs at every boot via RunAtLoad)
72
+ sudo launchctl bootstrap system /Library/LaunchDaemons/io.harperdb.loopback-setup.plist
73
+
74
+ # 4. Verify
75
+ cat /var/log/harper-loopback-setup.log # ✓ Configured ... line
76
+ ifconfig lo0 | grep '127.0.0' | tail -3 # aliases present
77
+ ```
78
+
79
+ Edit the `HARPER_INTEGRATION_TEST_LOOPBACK_POOL_COUNT` value in the installed plist to change the pool size (it defaults to 32, matching the script). To remove the daemon: `sudo launchctl bootout system/io.harperdb.loopback-setup` and delete the plist. If you edit the installed plist, `bootout` then `bootstrap` again to reload it.
80
+
53
81
  ## API
54
82
 
55
83
  The lifecycle and utility APIs below are framework-agnostic. They manage Harper child processes and a cross-process loopback address pool. Use them in the setup/teardown hooks of whichever test framework you prefer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harperfast/integration-testing",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "type": "module",
5
5
  "description": "Integration testing utilities for Harper-based projects. Provides Harper instance lifecycle management, loopback address pooling, and a test runner script.",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,30 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>io.harperdb.loopback-setup</string>
7
+
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>/bin/bash</string>
11
+ <string>/usr/local/sbin/harper-loopback-setup.sh</string>
12
+ </array>
13
+
14
+ <!-- One-shot at boot. Not a long-running service, so no KeepAlive. -->
15
+ <key>RunAtLoad</key>
16
+ <true/>
17
+
18
+ <!-- Pool size. Omit to use the script default (32); raise to 254 for the full pool. -->
19
+ <key>EnvironmentVariables</key>
20
+ <dict>
21
+ <key>HARPER_INTEGRATION_TEST_LOOPBACK_POOL_COUNT</key>
22
+ <string>32</string>
23
+ </dict>
24
+
25
+ <key>StandardOutPath</key>
26
+ <string>/var/log/harper-loopback-setup.log</string>
27
+ <key>StandardErrorPath</key>
28
+ <string>/var/log/harper-loopback-setup.log</string>
29
+ </dict>
30
+ </plist>
@@ -1,7 +1,14 @@
1
1
  #!/bin/bash
2
2
 
3
- # Prompt for password upfront
4
- sudo -v
3
+ # Run ifconfig via sudo when invoked interactively, or directly when already root
4
+ # (e.g. from the launchd daemon at boot, where there is no tty for `sudo -v`).
5
+ if [ "$(id -u)" -eq 0 ]; then
6
+ SUDO=""
7
+ else
8
+ SUDO="sudo"
9
+ # Prompt for password upfront
10
+ sudo -v
11
+ fi
5
12
 
6
13
  # The pool starts at 127.0.0.2 by default (127.0.0.1 is left for other services on localhost).
7
14
  # Override via the HARPER_INTEGRATION_TEST_LOOPBACK_POOL_START environment variable.
@@ -35,7 +42,20 @@ fi
35
42
 
36
43
  END=$((START + COUNT - 1))
37
44
  for i in $(seq $START $END); do
38
- sudo ifconfig lo0 alias 127.0.0.$i up
45
+ # Use a host (/32) netmask, not the implicit class-A /8. Without an explicit netmask,
46
+ # macOS gives each 127.0.0.x alias a 255.0.0.0 mask, so every alias claims to own the
47
+ # entire 127.0.0.0/8 network. With a large COUNT that means dozens/hundreds of interface
48
+ # addresses all asserting the same subnet, which drives mDNSResponder's address-conflict
49
+ # defense (PacketRRConflict) into an O(n^2) storm — pinning a CPU core and flooding
50
+ # 5353 with loopback announcements. A /32 host route removes the subnet overlap: each
51
+ # alias is an isolated host, so there is no conflict cascade even at the full 254-address
52
+ # pool. (Measured: 254 aliases /8 => ~65% CPU; 254 aliases /32 => ~0% CPU.)
53
+ #
54
+ # Remove any pre-existing alias first so re-running this converts a machine previously
55
+ # configured with the old /8 aliases; ifconfig alias on an existing address does not
56
+ # reliably reset its netmask. The `-alias` is a harmless no-op if the address is absent.
57
+ $SUDO ifconfig lo0 -alias 127.0.0.$i 2>/dev/null
58
+ $SUDO ifconfig lo0 alias 127.0.0.$i netmask 255.255.255.255 up
39
59
  done
40
60
 
41
61
  echo "✓ Configured $COUNT loopback addresses (127.0.0.$START-127.0.0.$END)"