blob: 09584e3443b48e7d7f9a124546044b2db1b4f175 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import assert from 'node:assert/strict';
import childProcess from 'node:child_process';
import { EventEmitter } from 'node:events';
import { syncBuiltinESMExports } from 'node:module';
import test from 'node:test';
import { fileURLToPath } from 'node:url';
import { runCli } from './run-cli.mjs';
const launcher = fileURLToPath(new URL('./run-cli.mjs', import.meta.url));
const root = fileURLToPath(new URL('../../', import.meta.url));
test('development builds select the native capability before forwarding CLI arguments', async (t) => {
let invocation;
t.mock.method(childProcess, 'spawn', (command, args, options) => {
invocation = { command, args, options };
const child = new EventEmitter();
queueMicrotask(() => child.emit('exit', 0, null));
return child;
});
syncBuiltinESMExports();
t.after(() => {
t.mock.restoreAll();
syncBuiltinESMExports();
});
const native = ['run', '--locked', '-p', 'maka-cli', '--', 'code', '--log', 'a b.sqlite'];
const bridge = [
'run',
'--locked',
'-p',
'maka-cli',
'--no-default-features',
'--',
'code',
'--log',
'a b.sqlite',
];
for (const [mode, platform, osRelease, expected] of [
[undefined, 'linux', '6.8.0-generic', native],
[undefined, 'linux', '6.6.87.2-microsoft-standard-WSL2', bridge],
['auto', 'linux', '4.4.0-Microsoft', bridge],
['auto', 'darwin', 'Microsoft', native],
['auto', 'win32', 'Microsoft', native],
['native', 'linux', '6.6.87.2-microsoft-standard-WSL2', native],
['bridge', 'linux', '6.8.0-generic', bridge],
]) {
const env = mode === undefined ? {} : { MAKA_CUA_BUILD_MODE: mode };
assert.deepEqual(
await runCli(['code', '--log', 'a b.sqlite'], {
env,
platform,
osRelease,
repositoryRoot: '/source checkout',
}),
{ code: 0, signal: null },
);
assert.deepEqual(invocation, {
command: 'cargo',
args: expected,
options: {
cwd: '/source checkout',
env,
stdio: 'inherit',
windowsHide: true,
},
});
}
});
// Run the public Node entrypoint while replacing only its external Cargo process.
function invokeLauncher(event, env = {}) {
const preload = `
import childProcess from 'node:child_process';
import { EventEmitter } from 'node:events';
import { syncBuiltinESMExports } from 'node:module';
childProcess.spawn = (command, args, options) => {
process.stdout.write(JSON.stringify({ command, args, cwd: options.cwd }) + '\\n');
const child = new EventEmitter();
queueMicrotask(() => ${event});
return child;
};
syncBuiltinESMExports();
`;
return childProcess.spawnSync(
process.execPath,
['--import', 'data:text/javascript,' + encodeURIComponent(preload), launcher, '--help'],
{
env: { ...process.env, MAKA_CUA_BUILD_MODE: 'bridge', ...env },
encoding: 'utf8',
timeout: 10_000,
windowsHide: true,
},
);
}
test('the launcher preserves Cargo failures and invokes Cargo from the repository', () => {
const result = invokeLauncher("child.emit('exit', 29, null)");
assert.equal(result.status, 29);
assert.equal(result.stderr, '');
assert.deepEqual(JSON.parse(result.stdout), {
command: 'cargo',
args: ['build', '--locked', '-p', 'maka-python-runtime', '--bin', 'maka-python-worker'],
cwd: root,
});
});
test('the launcher reports a Cargo spawn error', () => {
const result = invokeLauncher("child.emit('error', new Error('Cargo could not start'))");
assert.equal(result.status, 1);
assert.equal(result.stderr, 'Cargo could not start\n');
});
test('the launcher rejects unknown build modes before starting Cargo', () => {
const result = invokeLauncher("child.emit('exit', 0, null)", { MAKA_CUA_BUILD_MODE: 'typo' });
assert.equal(result.status, 1);
assert.equal(result.stdout, '');
assert.equal(result.stderr, 'MAKA_CUA_BUILD_MODE must be auto, native, or bridge\n');
});
test('the launcher preserves Cargo termination signals', {
skip: process.platform === 'win32',
}, () => {
const result = invokeLauncher("child.emit('exit', null, 'SIGTERM')");
assert.equal(result.status, null);
assert.equal(result.signal, 'SIGTERM');
});