#![cfg(feature = "test-network")]
use super::*;
fn test_fetch(index: &dyn PackageIndex, package: &str) {
let result = index.fetch(package);
assert!(
result.is_ok(),
"{} fetch({}) failed: {:?}",
index.ecosystem(),
package,
result.err()
);
let pkg = result.unwrap();
assert!(
!pkg.name.is_empty(),
"{}: name should not be empty",
index.ecosystem()
);
assert!(
!pkg.version.is_empty(),
"{}: version should not be empty",
index.ecosystem()
);
println!(
"{}: {} v{} - {:?}",
index.ecosystem(),
pkg.name,
pkg.version,
pkg.repository
);
}
fn test_versions(index: &dyn PackageIndex, package: &str) {
let result = index.fetch_versions(package);
assert!(
result.is_ok(),
"{} fetch_versions({}) failed: {:?}",
index.ecosystem(),
package,
result.err()
);
let versions = result.unwrap();
assert!(
!versions.is_empty(),
"{}: should have at least one version",
index.ecosystem()
);
println!(
"{}: {} has {} versions",
index.ecosystem(),
package,
versions.len()
);
}
fn test_search(index: &dyn PackageIndex, query: &str) {
let result = index.search(query);
if let Ok(results) = result {
println!(
"{}: search('{}') returned {} results",
index.ecosystem(),
query,
results.len()
);
} else {
println!(
"{}: search not implemented or failed: {:?}",
index.ecosystem(),
result.err()
);
}
}
fn test_fetch_all(index: &dyn PackageIndex) {
let result = index.fetch_all();
if let Ok(packages) = result {
println!(
"{}: fetch_all() returned {} packages",
index.ecosystem(),
packages.len()
);
assert!(
!packages.is_empty(),
"{}: fetch_all should return packages",
index.ecosystem()
);
} else {
println!(
"{}: fetch_all not implemented: {:?}",
index.ecosystem(),
result.err()
);
}
}
fn test_iter_all(index: &dyn PackageIndex) {
let result = index.iter_all();
if let Ok(iter) = result {
let mut count = 0;
let mut errors = 0;
for item in iter {
match item {
Ok(_) => count += 1,
Err(_) => errors += 1,
}
}
println!(
"{}: iter_all() yielded {} packages ({} errors)",
index.ecosystem(),
count,
errors
);
assert!(
count > 0,
"{}: iter_all should yield packages",
index.ecosystem()
);
} else {
println!(
"{}: iter_all not implemented: {:?}",
index.ecosystem(),
result.err()
);
}
}
#[test]
fn test_apt() {
let index = apt::Apt::stable();
test_fetch(&index, "curl");
test_versions(&index, "curl");
test_search(&index, "curl");
}
#[test]
fn test_apt_fetch_all() {
let index = apt::Apt::stable();
test_fetch_all(&index);
}
#[test]
fn test_apt_iter_all() {
let index = apt::Apt::stable();
test_iter_all(&index);
}
#[test]
fn test_apt_iter_all_matches_fetch_all() {
let index = apt::Apt::with_repos(&[apt::AptRepo::StableMain]);
let fetch_all_pkgs = index.fetch_all().unwrap();
let iter_all_pkgs: Vec<_> = index.iter_all().unwrap().filter_map(|r| r.ok()).collect();
assert_eq!(
fetch_all_pkgs.len(),
iter_all_pkgs.len(),
"iter_all and fetch_all should return same count"
);
for (fetch_pkg, iter_pkg) in fetch_all_pkgs.iter().take(10).zip(iter_all_pkgs.iter()) {
assert_eq!(fetch_pkg.name, iter_pkg.name, "package names should match");
assert_eq!(fetch_pkg.version, iter_pkg.version, "versions should match");
}
}
#[test]
fn test_apt_enhanced_metadata() {
let index = apt::Apt::stable();
let packages = index.fetch_all().unwrap();
if let Some(curl) = packages.iter().find(|p| p.name == "curl") {
println!("Package: {}", curl.name);
println!("Version: {}", curl.version);
println!("Archive URL: {:?}", curl.archive_url);
println!("Checksum: {:?}", curl.checksum);
println!("Dependencies: {:?}", curl.extra.get("depends"));
println!("Size: {:?}", curl.extra.get("size"));
assert!(curl.archive_url.is_some(), "archive_url should be set");
assert!(curl.checksum.is_some(), "checksum should be set");
assert!(
curl.extra.contains_key("depends"),
"depends should be in extra"
);
} else {
panic!("curl package not found in apt index");
}
}
#[test]
fn test_ubuntu() {
let index = ubuntu::Ubuntu::noble();
test_fetch(&index, "curl");
test_versions(&index, "curl");
test_search(&index, "curl");
}
#[test]
fn test_ubuntu_fetch_all() {
let index = ubuntu::Ubuntu::noble();
test_fetch_all(&index);
}
#[test]
fn test_pacman() {
let index = pacman::Pacman::stable();
test_fetch(&index, "ripgrep");
test_versions(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
fn test_pacman_enhanced_metadata() {
let index = pacman::Pacman::stable();
let curl = index.fetch("curl").unwrap();
println!("Package: {}", curl.name);
println!("Version: {}", curl.version);
println!("Archive URL: {:?}", curl.archive_url);
println!("Dependencies: {:?}", curl.extra.get("depends"));
println!("Size: {:?}", curl.extra.get("size"));
assert!(
curl.archive_url.is_some(),
"archive_url should be set for official packages"
);
assert!(
curl.extra.contains_key("depends"),
"depends should be in extra"
);
let yay = index.fetch("yay").unwrap();
println!("\nAUR Package: {}", yay.name);
println!("Archive URL: {:?}", yay.archive_url);
println!("Dependencies: {:?}", yay.extra.get("depends"));
println!("Source: {:?}", yay.extra.get("source"));
assert!(
yay.archive_url.is_some(),
"archive_url should be set for AUR packages"
);
assert_eq!(yay.extra.get("source"), Some(&serde_json::json!("aur")));
}
#[test]
fn test_artix() {
let index = artix::Artix::stable();
test_fetch(&index, "ripgrep");
test_versions(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
fn test_artix_repos() {
use artix::ArtixRepo;
let index = artix::Artix::with_repos(&[ArtixRepo::System, ArtixRepo::World]);
let packages = index.fetch_all().unwrap();
println!("artix: {} packages from system+world", packages.len());
assert!(packages.len() > 500, "should have many packages");
let system_pkg = packages.iter().find(|p| {
p.extra
.get("source_repo")
.and_then(|v| v.as_str())
.map(|s| s == "system")
.unwrap_or(false)
});
assert!(
system_pkg.is_some(),
"should have packages tagged as 'system'"
);
}
#[test]
fn test_nix() {
let index = nix::Nix::unstable();
test_fetch(&index, "ripgrep");
test_versions(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
fn test_gentoo() {
let index = gentoo::Gentoo::main_only();
test_fetch(&index, "sys-apps/ripgrep");
test_versions(&index, "sys-apps/ripgrep");
}
#[test]
#[ignore = "Slow: downloads full Guix package list (~25MB decompressed)"]
fn test_guix() {
let index = guix::Guix::official();
test_fetch(&index, "ripgrep");
test_versions(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
#[ignore = "SlackBuilds uses GitHub raw files, may be slow"]
fn test_slackware() {
let index = slackware::Slackware::latest_stable();
test_fetch(&index, "ripgrep");
test_versions(&index, "ripgrep");
}
#[test]
fn test_cachyos() {
let index = cachyos::CachyOs::stable();
test_fetch(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
fn test_endeavouros() {
let index = endeavouros::EndeavourOs::stable();
test_fetch(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
fn test_manjaro() {
let index = manjaro::Manjaro::stable();
test_fetch(&index, "firefox");
test_versions(&index, "firefox");
test_search(&index, "browser");
}
#[test]
fn test_dnf() {
let index = dnf::Dnf::stable();
test_fetch(&index, "curl");
test_versions(&index, "curl");
}
#[test]
fn test_copr() {
let index = copr::Copr;
test_search(&index, "vim");
}
#[test]
fn test_chaotic_aur() {
let index = chaotic_aur::ChaoticAur;
test_fetch(&index, "neovim-git");
test_search(&index, "firefox");
}
#[test]
fn test_dnf_enhanced_metadata() {
let index = dnf::Dnf::stable();
let curl = index.fetch("curl").unwrap();
println!("Package: {}", curl.name);
println!("Version: {}", curl.version);
println!("Dependencies: {:?}", curl.extra.get("depends"));
println!("Arch: {:?}", curl.extra.get("arch"));
assert!(curl.extra.contains_key("arch"), "arch should be in extra");
}
#[test]
fn test_apk() {
let index = apk::Apk::edge();
test_fetch(&index, "curl");
test_versions(&index, "curl");
test_search(&index, "curl");
}
#[test]
#[ignore = "Slow: downloads ~60MB FreeBSD packagesite"]
fn test_freebsd() {
let index = freebsd::FreeBsd::freebsd14();
test_fetch(&index, "curl");
test_versions(&index, "curl");
test_search(&index, "curl");
}
#[test]
#[ignore = "Slow: downloads ~20MB Void repodata"]
fn test_void() {
let index = void::Void::x86_64();
test_fetch(&index, "ripgrep");
test_versions(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
#[ignore = "Slow: downloads ~100MB openSUSE repos"]
fn test_opensuse() {
let index = opensuse::OpenSuse::all();
test_fetch(&index, "curl");
test_versions(&index, "curl");
test_search(&index, "curl");
let versions = index.fetch_versions("curl").unwrap();
println!(
"opensuse: curl has {} versions across repos",
versions.len()
);
for v in &versions {
println!(" {}", v.version);
}
assert!(
versions.len() > 1,
"should have versions from multiple repos"
);
}
#[test]
fn test_opensuse_single_repo() {
let index = opensuse::OpenSuse::tumbleweed();
test_fetch(&index, "curl");
test_search(&index, "curl");
}
#[test]
fn test_opensuse_source_repo() {
use opensuse::OpenSuseRepo;
let index = opensuse::OpenSuse::with_repos(&[OpenSuseRepo::TumbleweedSrcOss]);
let packages = index.fetch_all().unwrap();
println!(
"opensuse src: fetch_all() returned {} source packages",
packages.len()
);
assert!(!packages.is_empty(), "source repo should have packages");
let curl = packages.iter().find(|p| p.name == "curl");
if let Some(curl) = curl {
println!(
"Found curl source: {} (repo: {:?})",
curl.version,
curl.extra.get("source_repo")
);
}
}
#[test]
fn test_apk_enhanced_metadata() {
let index = apk::Apk::edge();
let curl = index.fetch("curl").unwrap();
println!("Package: {}", curl.name);
println!("Version: {}", curl.version);
println!("Archive URL: {:?}", curl.archive_url);
println!("Checksum: {:?}", curl.checksum);
println!("Dependencies: {:?}", curl.extra.get("depends"));
println!("Size: {:?}", curl.extra.get("size"));
assert!(curl.archive_url.is_some(), "archive_url should be set");
assert!(curl.checksum.is_some(), "checksum should be set");
}
#[test]
fn test_apk_fetch_all() {
let index = apk::Apk::edge();
let packages = index.fetch_all().unwrap();
println!("apk: fetch_all() returned {} packages", packages.len());
assert!(!packages.is_empty(), "fetch_all should return packages");
}
#[test]
fn test_apk_repos() {
use apk::AlpineRepo;
let index = apk::Apk::with_repos(&[AlpineRepo::EdgeMain, AlpineRepo::V321Main]);
let packages = index.fetch_all().unwrap();
println!(
"apk: {} packages from edge-main + v3.21-main",
packages.len()
);
assert!(packages.len() > 5000, "should have many packages");
let edge_pkg = packages.iter().find(|p| {
p.extra
.get("source_repo")
.and_then(|v| v.as_str())
.map(|s| s == "edge-main")
.unwrap_or(false)
});
assert!(
edge_pkg.is_some(),
"should have packages tagged as 'edge-main'"
);
}
#[test]
fn test_winget() {
let index = winget::Winget::winget_only();
test_fetch(&index, "Microsoft.VisualStudioCode");
test_search(&index, "vscode");
}
#[test]
fn test_scoop() {
let index = scoop::Scoop::core();
test_fetch(&index, "git");
test_versions(&index, "git");
test_search(&index, "git");
}
#[test]
fn test_choco() {
let index = choco::Choco::community();
test_fetch(&index, "git");
test_versions(&index, "git");
test_search(&index, "git");
}
#[test]
fn test_msys2() {
let index = msys2::Msys2::mingw64();
test_fetch(&index, "git");
test_versions(&index, "git");
test_search(&index, "git");
}
#[test]
fn test_brew() {
let index = brew::Brew;
test_fetch(&index, "ripgrep");
test_versions(&index, "ripgrep");
test_search(&index, "grep");
}
#[test]
fn test_brew_fetch_all() {
let index = brew::Brew;
test_fetch_all(&index);
}
#[test]
fn test_macports() {
let index = macports::MacPorts;
test_fetch(&index, "git");
test_versions(&index, "git");
test_search(&index, "git");
}
#[test]
fn test_snap() {
let index = snap::Snap::stable();
test_fetch(&index, "firefox");
test_versions(&index, "firefox");
test_search(&index, "browser");
}
#[test]
fn test_docker() {
let index = docker::Docker::hub();
test_fetch(&index, "nginx");
test_versions(&index, "nginx");
test_search(&index, "nginx");
}
#[test]
fn test_fdroid() {
let index = fdroid::FDroid::main();
test_fetch(&index, "org.fdroid.fdroid");
test_versions(&index, "org.fdroid.fdroid");
test_search(&index, "browser");
}
#[test]
fn test_termux() {
let index = termux::Termux;
test_fetch(&index, "bash");
test_versions(&index, "bash");
}
#[test]
fn test_vcpkg() {
let index = vcpkg::Vcpkg;
test_fetch(&index, "zlib");
test_versions(&index, "zlib");
test_search(&index, "json");
}
#[test]
fn test_hunter() {
let index = hunter::Hunter;
test_fetch(&index, "Boost");
test_versions(&index, "Boost");
test_search(&index, "curl");
}
#[test]
fn test_vcpkg_fetch_all() {
let index = vcpkg::Vcpkg;
test_fetch_all(&index);
}
#[test]
fn test_clojars() {
let index = clojars::Clojars;
test_fetch(&index, "ring");
test_versions(&index, "ring");
test_search(&index, "ring");
}
#[test]
fn test_cargo() {
let index = cargo::CargoIndex;
test_fetch(&index, "serde");
test_versions(&index, "serde");
test_search(&index, "json");
}
#[test]
fn test_npm() {
let index = npm::NpmIndex;
test_fetch(&index, "typescript");
test_versions(&index, "typescript");
test_search(&index, "react");
}
#[test]
fn test_pip() {
let index = pip::PipIndex;
test_fetch(&index, "requests");
test_versions(&index, "requests");
}
#[test]
fn test_deno() {
let index = deno::Deno;
test_fetch(&index, "oak");
test_versions(&index, "oak");
test_search(&index, "http");
}
#[test]
#[ignore = "Slow: paginates through entire deno.land/x index"]
fn test_deno_fetch_all() {
let index = deno::Deno;
test_fetch_all(&index);
}
#[test]
fn test_jsr() {
let index = jsr::Jsr;
test_fetch(&index, "@std/path");
test_versions(&index, "@std/path");
test_search(&index, "path");
}
#[test]
fn test_hex() {
let index = hex::Hex;
test_fetch(&index, "phoenix");
test_versions(&index, "phoenix");
test_search(&index, "web");
}
#[test]
fn test_maven() {
let index = maven::Maven::central();
test_fetch(&index, "com.google.guava:guava");
test_versions(&index, "com.google.guava:guava");
test_search(&index, "guava");
}
#[test]
fn test_nuget() {
let index = nuget::Nuget;
test_fetch(&index, "Newtonsoft.Json");
test_versions(&index, "Newtonsoft.Json");
test_search(&index, "json");
}
#[test]
fn test_gem() {
let index = gem::Gem;
test_fetch(&index, "rails");
test_versions(&index, "rails");
test_search(&index, "web");
}
#[test]
fn test_go() {
let index = go::Go;
test_fetch(&index, "github.com/gin-gonic/gin");
test_versions(&index, "github.com/gin-gonic/gin");
}
#[test]
fn test_composer() {
let index = composer::Composer;
test_fetch(&index, "laravel/framework");
test_versions(&index, "laravel/framework");
test_search(&index, "laravel");
}
#[test]
fn test_conan() {
let index = conan::Conan;
test_fetch(&index, "zlib");
test_versions(&index, "zlib");
test_search(&index, "boost");
}
#[test]
fn test_hackage() {
let index = hackage::Hackage;
test_fetch(&index, "aeson");
test_versions(&index, "aeson");
test_search(&index, "json");
}
#[test]
fn test_luarocks() {
let index = luarocks::LuaRocks;
test_fetch(&index, "luasocket");
test_versions(&index, "luasocket");
}
#[test]
fn test_metacpan() {
let index = metacpan::MetaCpan;
test_fetch(&index, "Moose");
test_versions(&index, "Moose");
test_search(&index, "object");
}
#[test]
fn test_pub() {
let index = pub_dev::Pub;
test_fetch(&index, "http");
test_versions(&index, "http");
test_search(&index, "http");
}
#[test]
fn test_opam() {
let index = opam::Opam;
test_fetch(&index, "dune");
test_versions(&index, "dune");
test_search(&index, "build");
}
#[test]
fn test_cran() {
let index = cran::Cran;
test_fetch(&index, "ggplot2");
test_versions(&index, "ggplot2");
test_search(&index, "plot");
}
#[test]
fn test_bioconductor() {
let index = bioconductor::Bioconductor;
test_fetch(&index, "BiocManager");
test_versions(&index, "BiocManager");
test_search(&index, "genomic");
}
#[test]
fn test_homebrew_casks() {
let index = homebrew_casks::HomebrewCasks;
test_fetch(&index, "visual-studio-code");
test_versions(&index, "visual-studio-code");
test_search(&index, "vscode");
}
#[test]
#[ignore = "Slow: downloads ~50MB conda repodata"]
fn test_conda() {
let index = conda::Conda::conda_forge();
test_fetch(&index, "python");
test_versions(&index, "python");
test_search(&index, "numpy");
}
#[test]
fn test_flatpak() {
let index = flatpak::Flatpak::flathub();
test_fetch(&index, "org.mozilla.firefox");
test_versions(&index, "org.mozilla.firefox");
test_search(&index, "firefox");
}
#[test]
fn test_nimble() {
let index = nimble::Nimble;
test_fetch(&index, "jester");
test_versions(&index, "jester");
test_search(&index, "http");
}
#[test]
fn test_julia() {
let index = julia::Julia;
test_fetch(&index, "DataFrames");
test_versions(&index, "DataFrames");
}
#[test]
fn test_dub() {
let index = dub::Dub;
test_fetch(&index, "vibe-d");
test_versions(&index, "vibe-d");
test_search(&index, "http");
}
#[test]
fn test_ctan() {
let index = ctan::Ctan;
test_fetch(&index, "pgf");
test_versions(&index, "pgf");
test_search(&index, "tikz");
}
#[test]
fn test_racket() {
let index = racket::Racket;
test_fetch(&index, "racket-doc");
test_versions(&index, "racket-doc");
test_search(&index, "web");
}
#[test]
#[ignore = "Slow: downloads entire AUR package archive (~30MB)"]
fn test_pacman_fetch_all() {
let index = pacman::Pacman::stable();
test_fetch_all(&index);
}
#[test]
fn test_pacman_official_repos() {
use pacman::ArchRepo;
let index = pacman::Pacman::with_repos(&[ArchRepo::Core, ArchRepo::Extra]);
let packages = index.fetch_all().unwrap();
println!(
"pacman official: {} packages from core+extra",
packages.len()
);
assert!(packages.len() > 1000, "should have many packages");
let core_pkg = packages.iter().find(|p| {
p.extra
.get("source_repo")
.and_then(|v| v.as_str())
.map(|s| s == "core")
.unwrap_or(false)
});
assert!(core_pkg.is_some(), "should have packages tagged as 'core'");
}
#[test]
fn test_list_indices() {
let indices = list_indices();
assert!(
indices.len() >= 56,
"should have at least 56 indices, got {}",
indices.len()
);
println!("Available indices: {:?}", indices);
}
#[test]
fn test_get_index() {
assert!(get_index("brew").is_some());
assert!(get_index("cargo").is_some());
assert!(get_index("nonexistent").is_none());
}