fix(launcher): check and install FUSE dependencies before LMS setup and launch
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
const { test } = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
const { readFileSync } = require('node:fs')
|
||||
const { join } = require('node:path')
|
||||
const ts = require('typescript')
|
||||
const source = readFileSync(join(__dirname, '../src/main/appImageFuse.ts'), 'utf8')
|
||||
const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText
|
||||
const api = {}
|
||||
new Function('exports', compiled)(api)
|
||||
const cache = 'libfuse.so.2 (libc6,x86-64) => /lib/x86_64-linux-gnu/libfuse.so.2'
|
||||
|
||||
function fixture(options = {}) {
|
||||
let installed = Boolean(options.installed)
|
||||
const calls = []
|
||||
const prepare = api.createFusePreparation({
|
||||
platform: options.platform ?? 'linux', arch: 'x64',
|
||||
readOsRelease: () => `ID=ubuntu\nVERSION_ID="${options.version ?? '24.04'}"\nPRETTY_NAME="Ubuntu"`,
|
||||
confirm: async () => { calls.push('confirm'); return options.accept !== false },
|
||||
run: async (command, args) => {
|
||||
calls.push([command, ...args])
|
||||
if (command === '/sbin/ldconfig') return { stdout: installed ? cache : '', stderr: '' }
|
||||
if (command === '/usr/bin/apt-cache') return { stdout: options.noCandidate ? 'Candidate: (none)' : 'Candidate: 2.9.9', stderr: '' }
|
||||
if (command === 'pkexec') {
|
||||
if (options.fail) throw new Error('authentication cancelled')
|
||||
installed = options.stillMissing !== true
|
||||
return { stdout: '', stderr: '' }
|
||||
}
|
||||
throw new Error(`Unexpected command ${command}`)
|
||||
},
|
||||
})
|
||||
return { prepare, calls }
|
||||
}
|
||||
|
||||
test('FUSE 3 and a foreign architecture do not satisfy FUSE 2', () => {
|
||||
assert.equal(api.hasFuseLibrary(cache, 'x64'), true)
|
||||
assert.equal(api.hasFuseLibrary(cache, 'arm64'), false)
|
||||
assert.equal(api.hasFuseLibrary('libfuse3.so.3 (libc6,x86-64)', 'x64'), false)
|
||||
})
|
||||
test('existing library and non-Linux skip installation', async () => {
|
||||
for (const options of [{ installed: true }, { platform: 'darwin' }]) {
|
||||
const f = fixture(options)
|
||||
await f.prepare()
|
||||
assert.equal(f.calls.includes('confirm'), false)
|
||||
}
|
||||
})
|
||||
test('Ubuntu versions choose the appropriate package and recheck installation', async () => {
|
||||
for (const [version, pkg] of [['22.04', 'libfuse2'], ['24.04', 'libfuse2t64'], ['26.04', 'libfuse2t64']]) {
|
||||
const f = fixture({ version })
|
||||
await f.prepare()
|
||||
assert.deepEqual(f.calls.find((call) => call[0] === 'pkexec'), ['pkexec', '/usr/bin/apt-get', 'install', '-y', '--no-remove', pkg])
|
||||
assert.equal(f.calls.filter((call) => call[0] === '/sbin/ldconfig').length, 2)
|
||||
}
|
||||
})
|
||||
test('cancel does not install and can be retried', async () => {
|
||||
const f = fixture({ accept: false })
|
||||
await assert.rejects(f.prepare(), /취소/)
|
||||
await assert.rejects(f.prepare(), /취소/)
|
||||
assert.equal(f.calls.some((call) => call[0] === 'pkexec'), false)
|
||||
})
|
||||
test('missing candidate, failed authentication and failed postcheck reject', async () => {
|
||||
for (const options of [{ noCandidate: true }, { fail: true }, { stillMissing: true }]) {
|
||||
await assert.rejects(fixture(options).prepare())
|
||||
}
|
||||
})
|
||||
test('concurrent preparations share one prompt and installation', async () => {
|
||||
const f = fixture()
|
||||
await Promise.all([f.prepare(), f.prepare()])
|
||||
assert.equal(f.calls.filter((call) => call === 'confirm').length, 1)
|
||||
assert.equal(f.calls.filter((call) => call[0] === 'pkexec').length, 1)
|
||||
})
|
||||
Reference in New Issue
Block a user