use std::path::{Path, PathBuf};
use ripvec_core::entry_points::{
EntryPoint, EntryPointDetector, EntryPointKind, GoEntryDetector, PythonEntryDetector,
RustEntryDetector, detector_for,
};
fn has(entries: &[EntryPoint], name: &str, kind: EntryPointKind) -> bool {
entries.iter().any(|e| e.name == name && e.kind == kind)
}
#[test]
fn rust_detects_pub_fn_main() {
let src = "
pub fn main() {
println!(\"hi\");
}
";
let entries = RustEntryDetector.detect(src, Path::new("/tmp/synth/src/main.rs"));
assert!(
has(&entries, "main", EntryPointKind::Main),
"expected Main entry for `pub fn main`, got {entries:?}"
);
}
#[test]
fn rust_detects_test_attribute() {
let src = "
#[test]
fn foo() {}
";
let entries = RustEntryDetector.detect(src, Path::new("/tmp/synth/src/lib.rs"));
assert!(
has(&entries, "foo", EntryPointKind::Test),
"expected Test entry for `#[test] fn foo`, got {entries:?}"
);
}
#[test]
fn rust_detects_no_mangle() {
let src = "
#[no_mangle]
pub extern \"C\" fn bar() {}
";
let entries = RustEntryDetector.detect(src, Path::new("/tmp/synth/src/lib.rs"));
assert!(
has(&entries, "bar", EntryPointKind::Ffi),
"expected Ffi entry for `#[no_mangle] pub extern \"C\" fn bar`, got {entries:?}"
);
}
#[test]
fn rust_detects_proc_macro() {
let src = "
#[proc_macro_derive(Foo)]
pub fn derive_foo(input: TokenStream) -> TokenStream { input }
";
let entries = RustEntryDetector.detect(src, Path::new("/tmp/synth/src/lib.rs"));
assert!(
has(&entries, "derive_foo", EntryPointKind::ProcMacro),
"expected ProcMacro entry for `#[proc_macro_derive(Foo)] pub fn derive_foo`, got {entries:?}"
);
}
#[test]
fn rust_detects_lib_rs_pub_fn_as_library_export() {
let src = "
pub fn public_api() {}
fn private_helper() {}
";
let entries = RustEntryDetector.detect(src, Path::new("/tmp/synth/src/lib.rs"));
assert!(
has(&entries, "public_api", EntryPointKind::LibraryExport),
"expected LibraryExport entry for pub fn in lib.rs, got {entries:?}"
);
assert!(
!has(&entries, "private_helper", EntryPointKind::LibraryExport),
"private_helper should not be LibraryExport, got {entries:?}"
);
}
#[test]
fn rust_detects_build_rs() {
let src = "
fn main() {
println!(\"cargo:rerun-if-changed=foo\");
}
";
let entries = RustEntryDetector.detect(src, Path::new("/tmp/synth/build.rs"));
assert!(
entries
.iter()
.any(|e| e.kind == EntryPointKind::BuildScript),
"expected BuildScript entry for build.rs, got {entries:?}"
);
assert!(
has(&entries, "main", EntryPointKind::Main),
"expected Main entry for build.rs `fn main`, got {entries:?}"
);
}
#[test]
fn python_detects_main_block() {
let src = "
def main():
pass
if __name__ == \"__main__\":
main()
";
let entries = PythonEntryDetector.detect(src, Path::new("/tmp/synth/app.py"));
assert!(
has(&entries, "__main__", EntryPointKind::Main),
"expected Main entry for `if __name__ == \"__main__\":` block, got {entries:?}"
);
}
#[test]
fn python_detects_test_function() {
let src = "
def test_addition():
assert 1 + 1 == 2
";
let entries = PythonEntryDetector.detect(src, Path::new("/tmp/synth/test_math.py"));
assert!(
has(&entries, "test_addition", EntryPointKind::Test),
"expected Test entry for `def test_addition` in test_math.py, got {entries:?}"
);
}
#[test]
#[allow(
non_snake_case,
reason = "test name matches briefing spec test:python_detects___all___export"
)]
fn python_detects___all___export() {
let src = "
__all__ = [\"foo\", \"bar\"]
def foo():
pass
def bar():
pass
def _internal():
pass
";
let entries = PythonEntryDetector.detect(src, Path::new("/tmp/synth/mypkg/api.py"));
assert!(
has(&entries, "foo", EntryPointKind::LibraryExport),
"expected LibraryExport entry for `foo` in __all__, got {entries:?}"
);
assert!(
has(&entries, "bar", EntryPointKind::LibraryExport),
"expected LibraryExport entry for `bar` in __all__, got {entries:?}"
);
assert!(
!has(&entries, "_internal", EntryPointKind::LibraryExport),
"_internal should not be LibraryExport, got {entries:?}"
);
}
#[test]
fn go_detects_func_main() {
let src = "
package main
func main() {
println(\"hi\")
}
";
let entries = GoEntryDetector.detect(src, Path::new("/tmp/synth/cmd/app/main.go"));
assert!(
has(&entries, "main", EntryPointKind::Main),
"expected Main entry for `func main` in `package main`, got {entries:?}"
);
}
#[test]
fn go_detects_test_function() {
let src = "
package mypkg
import \"testing\"
func TestFoo(t *testing.T) {
if 1 + 1 != 2 {
t.Fatal(\"math is broken\")
}
}
";
let entries = GoEntryDetector.detect(src, Path::new("/tmp/synth/mypkg/foo_test.go"));
assert!(
has(&entries, "TestFoo", EntryPointKind::Test),
"expected Test entry for `func TestFoo`, got {entries:?}"
);
}
#[test]
fn go_detects_exported_name() {
let src = "
package mypkg
func PublicHelper() int {
return 42
}
func privateHelper() int {
return 0
}
";
let entries = GoEntryDetector.detect(src, Path::new("/tmp/synth/mypkg/helpers.go"));
assert!(
has(&entries, "PublicHelper", EntryPointKind::LibraryExport),
"expected LibraryExport entry for `PublicHelper`, got {entries:?}"
);
assert!(
!has(&entries, "privateHelper", EntryPointKind::LibraryExport),
"privateHelper should not be LibraryExport, got {entries:?}"
);
}
#[test]
fn go_detects_init_function() {
let src = "
package mypkg
func init() {
setupSomething()
}
";
let entries = GoEntryDetector.detect(src, Path::new("/tmp/synth/mypkg/setup.go"));
assert!(
has(&entries, "init", EntryPointKind::Init),
"expected Init entry for `func init`, got {entries:?}"
);
}
#[test]
fn detector_for_returns_correct_implementor() {
let rust_detector = detector_for("rust").expect("rust detector exists");
let rust_entries = rust_detector.detect("fn main() {}\n", Path::new("/tmp/x/src/main.rs"));
assert!(
has(&rust_entries, "main", EntryPointKind::Main),
"rust detector should detect main, got {rust_entries:?}"
);
let py_detector = detector_for("python").expect("python detector exists");
let py_entries = py_detector.detect(
"if __name__ == \"__main__\":\n pass\n",
Path::new("/tmp/x/app.py"),
);
assert!(
has(&py_entries, "__main__", EntryPointKind::Main),
"python detector should detect dunder main, got {py_entries:?}"
);
let go_detector = detector_for("go").expect("go detector exists");
let go_entries = go_detector.detect(
"package main\nfunc main() {}\n",
Path::new("/tmp/x/main.go"),
);
assert!(
has(&go_entries, "main", EntryPointKind::Main),
"go detector should detect main, got {go_entries:?}"
);
assert!(
detector_for("rs").is_some(),
"detector_for(\"rs\") should return RustEntryDetector"
);
assert!(
detector_for("py").is_some(),
"detector_for(\"py\") should return PythonEntryDetector"
);
assert!(
detector_for("pyi").is_some(),
"detector_for(\"pyi\") should return PythonEntryDetector"
);
assert!(
detector_for("haskell").is_none(),
"detector_for(\"haskell\") should return None"
);
let _ = PathBuf::new();
}