mirror of
https://github.com/openai/codex.git
synced 2026-09-11 20:36:49 +00:00
## Why The Rust GStreamer bindings link GLib's GIO library even when none of the selected plugins imports it. Following only plugin dependencies can omit a library the bindings need. ## What changed - Export `gio-2.0` pkg-config metadata in the voice SDK. - Require GIO as a runtime dependency root on Linux, macOS, and Windows, including its transitive dependencies under the existing import checks. - Reject runtime packages that omit the required GIO library. ## Testing Extend fixtures to cover GIO inclusion and missing-library rejection across platforms, loading GIO and its transitive dependency after moving a Linux runtime, and resolving `gio-2.0` through pkg-config after moving an SDK. GitOrigin-RevId: d12e45d387d56c54d94d788cf07d82bb22c2b4a3
155 lines
6.3 KiB
Python
155 lines
6.3 KiB
Python
"""Exercise exported bytes, development aliases and moved pkg-config inputs."""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from runtime import digest
|
|
from sdk import MODULES, export_sdk
|
|
|
|
|
|
class SdkTests(unittest.TestCase):
|
|
def setUp(self):
|
|
temporary = tempfile.TemporaryDirectory(prefix="voice SDK ")
|
|
self.addCleanup(temporary.cleanup)
|
|
self.root = Path(temporary.name)
|
|
self.prefix = self.root / "prefix"
|
|
self.receipts = self.root / "receipts"
|
|
self.output = self.root / "sdk"
|
|
self.target = "aarch64-apple-darwin"
|
|
for name in ("include/glib-2.0", "lib/glib-2.0/include", "lib/pkgconfig"):
|
|
(self.prefix / name).mkdir(parents=True)
|
|
(self.prefix / "include/glib-2.0/glib.h").write_text("/* SDK fixture */")
|
|
(self.prefix / "lib/glib-2.0/include/glibconfig.h").write_text("/* target */")
|
|
self.library = self.prefix / "lib/libfixture.0.dylib"
|
|
self.library.write_bytes(b"receipt-verified fixture bytes")
|
|
for module in (*MODULES, "zlib"):
|
|
(self.prefix / f"lib/pkgconfig/{module}.pc").write_text(
|
|
"prefix=${pcfiledir}/../..\n"
|
|
f"Name: {module}\nDescription: SDK fixture\nVersion: 1.0\n"
|
|
"Cflags: -I${prefix}/include\nLibs: -L${prefix}/lib -lfixture\n"
|
|
)
|
|
audio = self.prefix / "lib/pkgconfig/gstreamer-audio-1.0.pc"
|
|
audio.write_text(
|
|
audio.read_text() + "Requires.private: gstreamer-tag-1.0, zlib\n"
|
|
)
|
|
(self.receipts / "inspection").mkdir(parents=True)
|
|
self.ci = {
|
|
"target": self.target,
|
|
"build_complete": True,
|
|
"inspection_complete": True,
|
|
"manifest_sha256": digest(Path(__file__).with_name("sources.json")),
|
|
"commit": "a" * 40,
|
|
}
|
|
(self.receipts / "ci.json").write_text(json.dumps(self.ci))
|
|
(self.receipts / "inspection/binaries.json").write_text(
|
|
json.dumps(
|
|
[
|
|
{
|
|
"path": "lib/libfixture.0.dylib",
|
|
"target": self.target,
|
|
"sha256": digest(self.library),
|
|
}
|
|
]
|
|
)
|
|
)
|
|
|
|
def test_exported_bytes_and_receipt_survive_move_without_original(self):
|
|
export_sdk(self.prefix, self.receipts, self.target, self.output)
|
|
moved = self.root / "moved SDK"
|
|
self.output.rename(moved)
|
|
shutil.rmtree(self.prefix)
|
|
manifest = json.loads((moved / "sdk.json").read_text())
|
|
actual = {
|
|
path.relative_to(moved).as_posix(): digest(path)
|
|
for path in moved.rglob("*")
|
|
if path.is_file() and path.name != "sdk.json"
|
|
}
|
|
self.assertEqual(
|
|
manifest,
|
|
{
|
|
"schemaVersion": 1,
|
|
"target": self.target,
|
|
"sourceCommit": "a" * 40,
|
|
"sourceManifestSha256": self.ci["manifest_sha256"],
|
|
"files": [
|
|
{"path": name, "sha256": actual[name]} for name in sorted(actual)
|
|
],
|
|
},
|
|
)
|
|
pkg_config = os.environ.get("VOICE_PKG_CONFIG") or shutil.which("pkg-config")
|
|
if not pkg_config:
|
|
self.skipTest("pkg-config required for the moved development-input probe")
|
|
result = subprocess.check_output(
|
|
[
|
|
pkg_config,
|
|
"--define-prefix",
|
|
"--cflags",
|
|
"--libs",
|
|
"gstreamer-audio-1.0",
|
|
"gio-2.0",
|
|
],
|
|
env={
|
|
**os.environ,
|
|
"PKG_CONFIG_PATH": "",
|
|
"PKG_CONFIG_LIBDIR": str(moved / "lib/pkgconfig"),
|
|
},
|
|
text=True,
|
|
).strip()
|
|
self.assertEqual(
|
|
shlex.split(result),
|
|
[f"-I{moved.as_posix()}/include", f"-L{moved.as_posix()}/lib", "-lfixture"],
|
|
)
|
|
|
|
def test_native_mutation_and_wrong_target_are_rejected(self):
|
|
with self.assertRaisesRegex(ValueError, "sources and target"):
|
|
export_sdk(self.prefix, self.receipts, "x86_64-apple-darwin", self.output)
|
|
self.library.write_bytes(b"changed")
|
|
with self.assertRaisesRegex(ValueError, "does not match"):
|
|
export_sdk(self.prefix, self.receipts, self.target, self.output)
|
|
self.assertFalse(self.output.exists())
|
|
|
|
def test_development_alias_is_materialized_and_escape_is_rejected(self):
|
|
alias = self.prefix / "lib/libfixture.dylib"
|
|
try:
|
|
alias.symlink_to(self.library.name)
|
|
except OSError:
|
|
self.skipTest("host cannot create the SDK's development symlink")
|
|
export_sdk(self.prefix, self.receipts, self.target, self.output)
|
|
self.assertFalse((self.output / "lib/libfixture.dylib").is_symlink())
|
|
self.assertEqual(
|
|
(self.output / "lib/libfixture.dylib").read_bytes(),
|
|
self.library.read_bytes(),
|
|
)
|
|
shutil.rmtree(self.output)
|
|
alias.unlink()
|
|
alias.symlink_to(self.receipts / "ci.json")
|
|
with self.assertRaisesRegex(ValueError, "inside the prefix"):
|
|
export_sdk(self.prefix, self.receipts, self.target, self.output)
|
|
|
|
def test_nonrelocatable_metadata_and_failed_copy_leave_no_output(self):
|
|
metadata = self.prefix / "lib/pkgconfig/gstreamer-1.0.pc"
|
|
original = metadata.read_text()
|
|
metadata.write_text(original.replace("${pcfiledir}/../..", "/old/build"))
|
|
with self.assertRaisesRegex(ValueError, "rebuild the SDK"):
|
|
export_sdk(self.prefix, self.receipts, self.target, self.output)
|
|
metadata.write_text(original)
|
|
with patch("sdk.shutil.copy2", side_effect=OSError("copy failed")):
|
|
with self.assertRaises(OSError):
|
|
export_sdk(self.prefix, self.receipts, self.target, self.output)
|
|
self.assertFalse(self.output.exists())
|
|
|
|
def test_output_cannot_overwrite_or_nest_inside_inputs(self):
|
|
for output in (self.prefix, self.prefix / "sdk", self.receipts / "sdk"):
|
|
with (
|
|
self.subTest(output=output),
|
|
self.assertRaisesRegex(ValueError, "fresh"),
|
|
):
|
|
export_sdk(self.prefix, self.receipts, self.target, output)
|