Files
pipu-music/scripts/check-apk.test.mjs
T
mrleo1nid b0cbd0f149
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m17s
ci / ts / ts (packages + web) (push) Successful in 2m22s
release / android (APK в релиз) (push) Successful in 4m15s
release / release (версия и заметки) (push) Successful in 6s
fix: repair Android startup and improve mobile web layouts
2026-10-21 17:14:05 +03:00

83 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { deflateRawSync } from 'node:zlib';
import { checkApk, loadAlignment, REQUIRED } from './check-apk.mjs';
/** ELF64 с одним PT_LOAD и заданным выравниванием. */
function elf(align) {
const b = Buffer.alloc(64 + 56);
b.writeUInt32BE(0x7f454c46, 0);
b[4] = 2;
b.writeBigUInt64LE(64n, 0x20);
b.writeUInt16LE(56, 0x36);
b.writeUInt16LE(1, 0x38);
b.writeUInt32LE(1, 64);
b.writeBigUInt64LE(BigInt(align), 64 + 0x30);
return b;
}
/** ZIP из пар [имя, содержимое]. */
function zip(files, compress = true) {
const locals = [];
const central = [];
let offset = 0;
for (const [name, data] of files) {
const packed = compress ? deflateRawSync(data) : data;
const n = Buffer.from(name);
const lh = Buffer.alloc(30);
lh.writeUInt32LE(0x04034b50, 0);
lh.writeUInt16LE(compress ? 8 : 0, 8);
lh.writeUInt32LE(packed.length, 18);
lh.writeUInt32LE(data.length, 22);
lh.writeUInt16LE(n.length, 26);
locals.push(lh, n, packed);
const ch = Buffer.alloc(46);
ch.writeUInt32LE(0x02014b50, 0);
ch.writeUInt16LE(compress ? 8 : 0, 10);
ch.writeUInt32LE(packed.length, 20);
ch.writeUInt32LE(data.length, 24);
ch.writeUInt16LE(n.length, 28);
ch.writeUInt32LE(offset, 42);
central.push(ch, n);
offset += 30 + n.length + packed.length;
}
const cd = Buffer.concat(central);
const end = Buffer.alloc(22);
end.writeUInt32LE(0x06054b50, 0);
end.writeUInt16LE(files.length, 8);
end.writeUInt16LE(files.length, 10);
end.writeUInt32LE(cd.length, 12);
end.writeUInt32LE(offset, 16);
return Buffer.concat([...locals, cd, end]);
}
test('reads the smallest PT_LOAD alignment', () => {
assert.equal(loadAlignment(elf(16384)), 16384);
assert.equal(loadAlignment(elf(4096)), 4096);
});
test('accepts an arm64-only APK aligned to 16 KB', () => {
const apk = zip(REQUIRED.map((l) => [`lib/arm64-v8a/${l}`, elf(16384)]));
assert.deepEqual(checkApk(apk).problems, []);
});
test('rejects direct APK library loading that breaks ARM translation', () => {
const apk = zip(REQUIRED.map((l) => [`lib/arm64-v8a/${l}`, elf(16384)]), false);
const { problems } = checkApk(apk);
assert.equal(problems.length, REQUIRED.length);
assert.ok(problems.every((p) => p.includes('useLegacyPackaging')));
});
test('rejects other ABIs, missing libraries and 4 KB alignment', () => {
const libs = REQUIRED.filter((l) => l !== 'libexpo-modules-core.so').map((l) => [
`lib/arm64-v8a/${l}`,
elf(l === 'librnskia.so' ? 4096 : 16384),
]);
const { problems } = checkApk(zip([...libs, ['lib/x86_64/libjsi.so', elf(16384)]]));
assert.equal(problems.length, 3);
assert.match(problems.join('\n'), /lib\/x86_64/);
assert.match(problems.join('\n'), /libexpo-modules-core\.so/);
assert.match(problems.join('\n'), /librnskia\.so.*4096/);
});