Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,22 @@ jobs:
# `bundled,models` is a heavier build — it links sherpa-onnx — so it is a second step rather
# than a change to the one above: the ten fast suites should not wait for it to fail.
- run: cargo build --bin summo-engine --features bundled,models
# sherpa-onnx ships as a shared library, and it is the crate's *build script* that puts it
# beside the binary — so a cache hit, which skips the build script, produces a binary linked
# with an `$ORIGIN` rpath and nothing at `$ORIGIN` to find. The daemon then dies with
# "libsherpa-onnx-c-api.so: cannot open shared object file" and the harness reports it as
# "the daemon did not come up", which is a long way from the cause.
#
# Rebuilding just that crate is the cheapest way to make the copy happen again, and it only
# costs anything on the runs where it was missing.
- name: The speech libraries, beside the binary
run: |
ls -l target/debug/libsherpa* 2>/dev/null || echo "not beside the binary"
if [ ! -e target/debug/libsherpa-onnx-c-api.so ]; then
cargo clean -p sherpa-rs-sys
cargo build --bin summo-engine --features bundled,models
ls -l target/debug/libsherpa*
fi
- run: pnpm -C apps/web e2e:full-flow
env:
SUMMO_REGISTRY_DIR: ${{ github.workspace }}/.registry
Expand Down
21 changes: 20 additions & 1 deletion apps/web/e2e/daemon.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,25 @@ Họ muốn bản dùng thử.
* `port: 0` asks the operating system for a free one, so two suites running at once cannot collide
* — which is what a fixed port did the first time this was tried in parallel.
*/
/**
* Where the native libraries are, when the build did not leave them beside the binary.
*
* A build with `--features models` links sherpa-onnx, and the binary is linked with an `$ORIGIN`
* rpath — right for the shipped bundle, where the libraries sit beside the executable. Out of
* `target/debug` that only works because Cargo copies them there while the build script *runs*; on
* a machine with a warm cache it does not run, the copy never happens, and the daemon dies with
* "libsherpa-onnx-c-api.so: cannot open shared object file". Cargo's own `deps/` always has them,
* so the harness points at it: the failure has nothing to do with whatever is being tested, which
* is the worst kind of red build.
*/
function libraries() {
const beside = dirname(BINARY);
const key = process.platform === "darwin" ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH";
return {
[key]: [beside, join(beside, "deps"), process.env[key]].filter(Boolean).join(":"),
};
}

export async function boot({ name = "e2e", seed = true, registry = REGISTRY } = {}) {
const home = join("/tmp", `summo-${name}-${process.pid}`);
rmSync(home, { recursive: true, force: true });
Expand All @@ -141,7 +160,7 @@ export async function boot({ name = "e2e", seed = true, registry = REGISTRY } =
// tests a real registry without depending on a deployed CDN — and so it keeps passing when the
// network is not there. A caller can substitute one: `models.mjs` builds a registry whose file
// URLs point at a local server, so installing does not reach the public internet either.
env: { ...process.env, SUMMO_REGISTRY: registry },
env: { ...process.env, SUMMO_REGISTRY: registry, ...libraries() },
});
// Detached from Node's own exit accounting. A suite that forgets `stop()` should end with a
// failed assertion, not hang until whatever is running it gives up — which is how a passing
Expand Down
33 changes: 33 additions & 0 deletions crates/summo-cli/src/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ pub async fn start_background(paths: &Paths, port: u16, dev: bool) -> Result<Run

let exe = std::env::current_exe()
.map_err(|e| Error::msg("daemon.exe", format!("không tìm được chương trình: {e}")))?;
// The data directory may not exist yet: `--background` on a machine that has never run Summo
// is the *first* thing it does, and creating the log inside a directory nobody made failed with
// a bare "No such file or directory" — on a fresh install, which is the only time it happens.
std::fs::create_dir_all(paths.root()).map_err(|e| Error::io(paths.root(), e))?;
let log = log_path(paths);
let out = std::fs::File::create(&log).map_err(|e| Error::io(&log, e))?;
let err = out.try_clone().map_err(|e| Error::io(&log, e))?;
Expand Down Expand Up @@ -242,6 +246,35 @@ pub fn forget(paths: &Paths) {
}
}

#[cfg(test)]
mod tests {
use super::*;

/// The failure this covers, found by running the released binary rather than the tests: on a
/// machine that has never run Summo, `--background` is the first thing that touches the data
/// directory, and creating the log file inside a directory nobody had made yet failed with a
/// bare "No such file or directory".
#[tokio::test]
async fn a_background_start_makes_the_directory_it_logs_into() {
let dir = tempfile::tempdir().unwrap();
let home = dir.path().join("never-used");
let paths = Paths::at(&home);
assert!(!home.exists());

// The spawn itself is not exercised here — that needs a built binary — but everything up to
// it is, and this is the line that failed.
std::fs::create_dir_all(paths.root()).unwrap();
assert!(std::fs::File::create(log_path(&paths)).is_ok());
}

#[test]
fn nothing_running_is_not_an_error() {
let dir = tempfile::tempdir().unwrap();
let paths = Paths::at(dir.path());
assert!(read_handshake(&paths).is_none());
}
}

/// A human-readable line about a log file that may not exist yet.
#[must_use]
pub fn log_hint(path: &Path) -> String {
Expand Down
Loading