mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 14:16:16 -08:00
* docs: design Linux frame-copy packaging * docs: plan Linux frame-copy packaging * feat(packaging): define Linux frame-copy profiles * fix(packaging): reject inherited profile names * feat(embedded-mpv): validate staged Linux runtime * fix(embedded-mpv): require Linux source packages * fix(embedded-mpv): harden Linux runtime staging * feat(embedded-mpv): build LGPL Linux runtime * fix(embedded-mpv): pin Linux runtime inputs * feat(embedded-mpv): build relocatable Linux helper * fix(embedded-mpv): require bundled Linux runtime * fix(embedded-mpv): make Linux runtime portable * feat(packaging): ship Linux frame-copy artifacts * fix(embedded-mpv): verify Linux helper linkage * fix(packaging): enforce Linux frame-copy isolation * fix(embedded-mpv): pin Linux display data * docs(embedded-mpv): document Linux frame-copy packaging * feat(embedded-mpv): probe Linux frame-copy runtime * test(embedded-mpv): smoke packaged Linux frame-copy * docs(embedded-mpv): clarify Linux system runtime baseline * fix(embedded-mpv): harden Linux runtime capability gate * ci: verify Linux frame-copy packages * test(embedded-mpv): harden packaged Linux smoke * test(embedded-mpv): preserve packaged GL mode * test(packaging): harden Linux package probes * fix(embedded-mpv): enable private Snap shared memory * fix(embedded-mpv): sanitize Linux helper environment * fix(packaging): enforce private Snap memory semantics * fix(packaging): reject ambiguous Snap memory metadata * fix(embedded-mpv): prioritize trusted Snap GL * fix(packaging): reject advanced Snap YAML semantics * fix(packaging): reject arbitrary Snap YAML aliases * feat(packaging): ship Linux runtime license notices * docs(embedded-mpv): document Linux runtime distribution * fix(packaging): parse Snap trailing comments safely * fix(release): gate Snap publish on public source release * fix(packaging): strip VCS metadata from source bundle * docs(packaging): clarify Linux source release gate * test(embedded-mpv): smoke missing bundled libmpv * style(embedded-mpv): format final validation inputs * fix(e2e): satisfy fixture index signature typing * fix(ci): declare fontconfig gperf generator * fix(embedded-mpv): hash runtime cache identities * fix(packaging): harden Linux frame-copy delivery * fix(packaging): tighten runtime delivery gates * fix(ci): decouple Linux runtime matrix * fix(packaging): harden Linux frame-copy delivery * fix(packaging): validate Linux frame-copy runtimes * fix(packaging): scope Snap Electron library checks * feat(packaging): ship Linux frame-copy runtimes * fix(packaging): improve Linux runtime smoke diagnostics * fix(packaging): expose bounded helper probe details * test(packaging): trace Snap EGL probe failures * fix(packaging): prefer core22 ABI in Snap helper * fix(packaging): bound helper probe capture * fix(packaging): harden Linux frame-copy releases * fix(packaging): canonicalize libplacebo submodule identity * fix(packaging): make source archive inspection portable * fix(packaging): harden Snap release verification
192 lines
6.6 KiB
TypeScript
192 lines
6.6 KiB
TypeScript
import assert = require('node:assert/strict');
|
|
import { readFileSync } from 'node:fs';
|
|
import { join, resolve } from 'node:path';
|
|
import { describe, it } from 'node:test';
|
|
import { isMeaningfulNativePlaybackSnapshot } from './embedded-mpv-frame-copy-packaged-fixtures';
|
|
import './embedded-mpv-frame-copy-packaged-filesystem.tests';
|
|
import { resolvePackagedElectronLaunchArgs } from './electron-test-fixtures';
|
|
import packagedPlaywrightConfig from '../playwright.packaged.config';
|
|
|
|
const projectRoot = resolve(__dirname, '..');
|
|
|
|
describe('packaged Electron launch arguments', () => {
|
|
it('keeps WebGL enabled for software rendering while disabling the sandbox only as root', () => {
|
|
assert.deepEqual(
|
|
resolvePackagedElectronLaunchArgs(() => 1000),
|
|
['--ignore-gpu-blocklist']
|
|
);
|
|
assert.deepEqual(resolvePackagedElectronLaunchArgs(undefined), [
|
|
'--ignore-gpu-blocklist',
|
|
]);
|
|
assert.deepEqual(
|
|
resolvePackagedElectronLaunchArgs(() => 0),
|
|
['--ignore-gpu-blocklist', '--no-sandbox']
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('native-view playback proof', () => {
|
|
it('requires the loaded URL, a playing or paused state, and positive duration', () => {
|
|
const expectedUrl = 'http://127.0.0.1:3210/fixture.y4m';
|
|
const baseSnapshot = {
|
|
durationSeconds: 2,
|
|
status: 'playing',
|
|
streamUrl: expectedUrl,
|
|
};
|
|
|
|
assert.equal(
|
|
isMeaningfulNativePlaybackSnapshot(baseSnapshot, expectedUrl),
|
|
true
|
|
);
|
|
assert.equal(
|
|
isMeaningfulNativePlaybackSnapshot(
|
|
{ ...baseSnapshot, status: 'paused' },
|
|
`${expectedUrl}#ignored`
|
|
),
|
|
true
|
|
);
|
|
assert.equal(
|
|
isMeaningfulNativePlaybackSnapshot(
|
|
{ ...baseSnapshot, durationSeconds: null },
|
|
expectedUrl
|
|
),
|
|
false
|
|
);
|
|
assert.equal(
|
|
isMeaningfulNativePlaybackSnapshot(
|
|
{ ...baseSnapshot, status: 'idle' },
|
|
expectedUrl
|
|
),
|
|
false
|
|
);
|
|
assert.equal(
|
|
isMeaningfulNativePlaybackSnapshot(
|
|
{ ...baseSnapshot, streamUrl: `${expectedUrl}?other=1` },
|
|
expectedUrl
|
|
),
|
|
false
|
|
);
|
|
});
|
|
|
|
it('loads the fixture and observes playback before disposing the native session', () => {
|
|
const source = readFileSync(
|
|
join(projectRoot, 'src', 'embedded-mpv-frame-copy-packaged.e2e.ts'),
|
|
'utf8'
|
|
);
|
|
const fallbackStart = source.indexOf('const launchedFallbackApp');
|
|
const captureIndex = source.indexOf(
|
|
'installEmbeddedMpvSessionCapture',
|
|
fallbackStart
|
|
);
|
|
const loadIndex = source.indexOf(
|
|
'loadEmbeddedMpvPlayback',
|
|
fallbackStart
|
|
);
|
|
const proofIndex = source.indexOf(
|
|
'isMeaningfulNativePlaybackSnapshot',
|
|
fallbackStart
|
|
);
|
|
const exitCodeIndex = source.indexOf(
|
|
'electronApp.process().exitCode',
|
|
fallbackStart
|
|
);
|
|
const disposeIndex = source.indexOf(
|
|
'disposeEmbeddedMpvSession',
|
|
fallbackStart
|
|
);
|
|
|
|
assert.ok(fallbackStart >= 0);
|
|
assert.ok(captureIndex > fallbackStart);
|
|
assert.ok(loadIndex > captureIndex);
|
|
assert.ok(proofIndex > loadIndex);
|
|
assert.ok(exitCodeIndex > proofIndex);
|
|
assert.ok(disposeIndex > exitCodeIndex);
|
|
});
|
|
|
|
it('removes the manifest-declared libmpv target and expects the stable missing-library reason', () => {
|
|
const source = readFileSync(
|
|
join(projectRoot, 'src', 'embedded-mpv-frame-copy-packaged.e2e.ts'),
|
|
'utf8'
|
|
);
|
|
const manifestIdentityIndex = source.indexOf(
|
|
'const runtimeIdentity = readPackagedRuntimeIdentity'
|
|
);
|
|
const guardIndex = source.indexOf(
|
|
'createPackagedEntryGuard(',
|
|
manifestIdentityIndex
|
|
);
|
|
const sonameIndex = source.indexOf(
|
|
'runtimeIdentity.libmpvSoname',
|
|
guardIndex
|
|
);
|
|
const hideIndex = source.indexOf('.hide()', sonameIndex);
|
|
const fallbackStart = source.indexOf(
|
|
'const launchedFallbackApp',
|
|
hideIndex
|
|
);
|
|
const missingReasonIndex = source.indexOf(
|
|
"frameCopyUnavailableReason: 'runtime-library-missing'",
|
|
fallbackStart
|
|
);
|
|
|
|
assert.ok(manifestIdentityIndex >= 0);
|
|
assert.ok(guardIndex > manifestIdentityIndex);
|
|
assert.ok(sonameIndex > guardIndex);
|
|
assert.ok(hideIndex > sonameIndex);
|
|
assert.ok(fallbackStart > hideIndex);
|
|
assert.ok(missingReasonIndex > fallbackStart);
|
|
assert.doesNotMatch(source, /createRuntimeManifestGuard/);
|
|
assert.doesNotMatch(source, /runtimeManifest\.hide/);
|
|
});
|
|
});
|
|
|
|
describe('dedicated packaged smoke target', () => {
|
|
it('inherits the GL mode from the workflow environment', () => {
|
|
const source = readFileSync(
|
|
join(projectRoot, 'src', 'embedded-mpv-frame-copy-packaged.e2e.ts'),
|
|
'utf8'
|
|
);
|
|
|
|
assert.doesNotMatch(source, /LIBGL_ALWAYS_SOFTWARE\s*:/);
|
|
});
|
|
|
|
it('does not build the backend or start portal mock servers', () => {
|
|
const project = JSON.parse(
|
|
readFileSync(join(projectRoot, 'project.json'), 'utf8')
|
|
) as {
|
|
targets?: Record<
|
|
string,
|
|
{
|
|
cache?: boolean;
|
|
dependsOn?: unknown;
|
|
options?: { command?: string };
|
|
}
|
|
>;
|
|
};
|
|
const target = project.targets?.['packaged-frame-copy-smoke'];
|
|
const packagedConfig = readFileSync(
|
|
join(projectRoot, 'playwright.packaged.config.ts'),
|
|
'utf8'
|
|
);
|
|
|
|
if (!target) {
|
|
throw new Error('The packaged frame-copy smoke target is missing.');
|
|
}
|
|
assert.equal(target.cache, false);
|
|
assert.deepEqual(target.dependsOn, [
|
|
'test-packaged-frame-copy-fixtures',
|
|
]);
|
|
assert.match(
|
|
target.options?.command ?? '',
|
|
/playwright\.packaged\.config\.ts/
|
|
);
|
|
assert.match(
|
|
target.options?.command ?? '',
|
|
/embedded-mpv-frame-copy-packaged\.e2e\.ts/
|
|
);
|
|
assert.match(packagedConfig, /timeout:\s*120000/);
|
|
assert.match(packagedConfig, /webServer:\s*\[\]/);
|
|
assert.deepEqual(packagedPlaywrightConfig.webServer, []);
|
|
});
|
|
});
|