Skip to content

Commit

Permalink
Fix random CI failures on Mac
Browse files Browse the repository at this point in the history
Using `tempy` to generate random temporary directories results in
unix domain socket names that are too long (104 bytes is the max
on Mac) which manifests itself as EADDRINUSE errors. So replace
`tempy` with a simple alternative.

Also expands the CI test matrix, adding Node.js 18 and Windows and
Mac, to test platform differences in the handling of sockets.
  • Loading branch information
vweevers committed Jul 10, 2022
1 parent a4be8fc commit 7ccf7b2
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 26 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
node: [12, 14, 16]
name: Node ${{ matrix.node }}
os: [ubuntu-latest, macos-latest, windows-latest]
node: [12, 14, 16, 18]
name: Node ${{ matrix.node }} on ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion test/basic.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const test = require('tape')
const tempy = require('tempy')
const tempy = require('./util/tempy')
const path = require('path')
const events = require('events')
const { RaveLevel } = require('..')
Expand Down
2 changes: 1 addition & 1 deletion test/bytewise.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const test = require('tape')
const bytewise = require('bytewise')
const tempy = require('tempy')
const tempy = require('./util/tempy')
const { RaveLevel } = require('..')

test('bytewise key encoding', function (t) {
Expand Down
2 changes: 1 addition & 1 deletion test/election.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const test = require('tape')
const { once } = require('events')
const tempy = require('tempy')
const tempy = require('./util/tempy')
const { RaveLevel } = require('..')

test('basic failover', async function (t) {
Expand Down
39 changes: 21 additions & 18 deletions test/multi-process.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const test = require('tape')
const tempy = require('tempy')
const tempy = require('./util/tempy')
const { once } = require('events')
const { fork } = require('child_process')
const { RaveLevel } = require('..')
Expand All @@ -14,24 +14,27 @@ if (process.argv[2] === 'child') {
if (err) throw err
})
} else {
test('multiple processes', async function (t) {
const location = tempy.directory()
const entries = []
const promises = []
const exits = []
// Repeat because we have/had random issues here
for (let i = 0; i < 20; i++) {
test(`multiple processes (${i})`, async function (t) {
const location = tempy.directory()
const entries = []
const promises = []
const exits = []

for (let i = 0; i < 10; i++) {
const key = String(i).padStart(5, '0')
const value = String(Math.random())
const argv = ['child', location, key, value]
const child = fork(__filename, argv, { timeout: 30e3 })
for (let i = 0; i < 10; i++) {
const key = String(i).padStart(5, '0')
const value = String(Math.random())
const argv = ['child', location, key, value]
const child = fork(__filename, argv, { timeout: 30e3 })

entries.push([key, value])
promises.push(once(child, 'exit'))
exits.push([0, null])
}
entries.push([key, value])
promises.push(once(child, 'exit'))
exits.push([0, null])
}

t.same(await Promise.all(promises), exits)
t.same(await new RaveLevel(location).iterator().all(), entries)
})
t.same(await Promise.all(promises), exits)
t.same(await new RaveLevel(location).iterator().all(), entries)
})
}
}
2 changes: 1 addition & 1 deletion test/open-close.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const test = require('tape')
const { once } = require('events')
const tempy = require('tempy')
const tempy = require('./util/tempy')
const { RaveLevel } = require('..')

test('self-flush', async function (t) {
Expand Down
2 changes: 1 addition & 1 deletion test/sublevel.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const test = require('tape')
const tempy = require('tempy')
const tempy = require('./util/tempy')
const { RaveLevel } = require('..')

test('sublevel', function (t) {
Expand Down
22 changes: 22 additions & 0 deletions test/util/tempy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

const tempy = require('tempy')
const path = require('path')
const crypto = require('crypto')
const fs = require('fs')

exports.directory = function () {
if (process.platform === 'darwin') {
// With tempy we'd get a directory like:
// /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/2548920d4cad0629af0e283f78636f1f
//
// Add to that the 'rave-level.sock' filename and the total length is 105 bytes,
// while the maximum length of a unix domain socket on Mac is 104 bytes. Exceeding
// it can result in EADDRINUSE errors.
const dir = path.join('/tmp', crypto.randomBytes(10).toString('hex'))
fs.mkdirSync(dir)
return dir
} else {
return tempy.directory()
}
}

0 comments on commit 7ccf7b2

Please sign in to comment.