Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test_samples.rs   Sprache: unbekannt

 
extern crate cargo_metadata;
extern crate semver;
#[macro_use]
extern crate serde_json;

use camino::Utf8PathBuf;
use cargo_metadata::{CargoOpt, DependencyKind, Edition, Metadata, MetadataCommand};

#[test]
fn old_minimal() {
    // Output from oldest supported version (1.24).
    // This intentionally has as many null fields as possible.
    // 1.8 is when metadata was introduced.
    // Older versions not supported because the following are required:
    // - `workspace_members` added in 1.13
    // - `target_directory` added in 1.19
    // - `workspace_root` added in 1.24
    let json = r#"
{
  "packages": [
    {
      "name": "foo",
      "version": "0.1.0",
      "id": "foo 0.1.0 (path+file:///foo)",
      "license": null,
      "license_file": null,
      "description": null,
      "source": null,
      "dependencies": [
        {
          "name": "somedep",
          "source": null,
          "req": "^1.0",
          "kind": null,
          "optional": false,
          "uses_default_features": true,
          "features": [],
          "target": null
        }
      ],
      "targets": [
        {
          "kind": [
            "bin"
          ],
          "crate_types": [
            "bin"
          ],
          "name": "foo",
          "src_path": "/foo/src/main.rs"
        }
      ],
      "features": {},
      "manifest_path": "/foo/Cargo.toml"
    }
  ],
  "workspace_members": [
    "foo 0.1.0 (path+file:///foo)"
  ],
  "resolve": null,
  "target_directory": "/foo/target",
  "version": 1,
  "workspace_root": "/foo"
}
"#;
    let meta: Metadata = serde_json::from_str(json).unwrap();
    assert_eq!(meta.packages.len(), 1);
    let pkg = &meta.packages[0];
    assert_eq!(pkg.name, "foo");
    assert_eq!(pkg.version, semver::Version::parse("0.1.0").unwrap());
    assert_eq!(pkg.authors.len(), 0);
    assert_eq!(pkg.id.to_string(), "foo 0.1.0 (path+file:///foo)");
    assert_eq!(pkg.description, None);
    assert_eq!(pkg.license, None);
    assert_eq!(pkg.license_file, None);
    assert_eq!(pkg.default_run, None);
    assert_eq!(pkg.rust_version, None);
    assert_eq!(pkg.dependencies.len(), 1);
    let dep = &pkg.dependencies[0];
    assert_eq!(dep.name, "somedep");
    assert_eq!(dep.source, None);
    assert_eq!(dep.req, semver::VersionReq::parse("^1.0").unwrap());
    assert_eq!(dep.kind, DependencyKind::Normal);
    assert!(!dep.optional);
    assert!(dep.uses_default_features);
    assert_eq!(dep.features.len(), 0);
    assert!(dep.target.is_none());
    assert_eq!(dep.rename, None);
    assert_eq!(dep.registry, None);
    assert_eq!(pkg.targets.len(), 1);
    let target = &pkg.targets[0];
    assert_eq!(target.name, "foo");
    assert_eq!(target.kind, vec!["bin"]);
    assert_eq!(target.crate_types, vec!["bin"]);
    assert_eq!(target.required_features.len(), 0);
    assert_eq!(target.src_path, "/foo/src/main.rs");
    assert_eq!(target.edition, Edition::E2015);
    assert!(target.doctest);
    assert!(target.test);
    assert!(target.doc);
    assert_eq!(pkg.features.len(), 0);
    assert_eq!(pkg.manifest_path, "/foo/Cargo.toml");
    assert_eq!(pkg.categories.len(), 0);
    assert_eq!(pkg.keywords.len(), 0);
    assert_eq!(pkg.readme, None);
    assert_eq!(pkg.repository, None);
    assert_eq!(pkg.homepage, None);
    assert_eq!(pkg.documentation, None);
    assert_eq!(pkg.edition, Edition::E2015);
    assert_eq!(pkg.metadata, serde_json::Value::Null);
    assert_eq!(pkg.links, None);
    assert_eq!(pkg.publish, None);
    assert_eq!(meta.workspace_members.len(), 1);
    assert_eq!(
        meta.workspace_members[0].to_string(),
        "foo 0.1.0 (path+file:///foo)"
    );
    assert!(meta.resolve.is_none());
    assert_eq!(meta.workspace_root, "/foo");
    assert_eq!(meta.workspace_metadata, serde_json::Value::Null);
    assert_eq!(meta.target_directory, "/foo/target");
}

macro_rules! sorted {
    ($e:expr) => {{
        let mut v = $e.clone();
        v.sort();
        v
    }};
}

fn cargo_version() -> semver::Version {
    let output = std::process::Command::new("cargo")
        .arg("-V")
        .output()
        .expect("Failed to exec cargo.");
    let out = std::str::from_utf8(&output.stdout)
        .expect("invalid utf8")
        .trim();
    let split: Vec<&str> = out.split_whitespace().collect();
    assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out);
    let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed");
    // Don't care about metadata, it is awkward to compare.
    ver.pre = semver::Prerelease::EMPTY;
    ver.build = semver::BuildMetadata::EMPTY;
    ver
}

#[derive(serde::Deserialize, PartialEq, Eq, Debug)]
struct WorkspaceMetadata {
    testobject: TestObject,
}

#[derive(serde::Deserialize, PartialEq, Eq, Debug)]
struct TestObject {
    myvalue: String,
}

#[test]
fn all_the_fields() {
    // All the fields currently generated as of 1.60. This tries to exercise as
    // much as possible.
    let ver = cargo_version();
    let minimum = semver::Version::parse("1.56.0").unwrap();
    if ver < minimum {
        // edition added in 1.30
        // rename added in 1.31
        // links added in 1.33
        // doctest added in 1.37
        // publish added in 1.39
        // dep_kinds added in 1.41
        // test added in 1.47
        // homepage added in 1.49
        // documentation added in 1.49
        // doc added in 1.50
        // path added in 1.51
        // default_run added in 1.55
        // rust_version added in 1.58
        eprintln!("Skipping all_the_fields test, cargo {} is too old.", ver);
        return;
    }
    let meta = MetadataCommand::new()
        .manifest_path("tests/all/Cargo.toml")
        .exec()
        .unwrap();
    assert_eq!(meta.workspace_root.file_name().unwrap(), "all");
    assert_eq!(
        serde_json::from_value::<WorkspaceMetadata>(meta.workspace_metadata).unwrap(),
        WorkspaceMetadata {
            testobject: TestObject {
                myvalue: "abc".to_string()
            }
        }
    );
    assert_eq!(meta.workspace_members.len(), 1);
    assert!(meta.workspace_members[0].to_string().starts_with("all"));

    assert_eq!(meta.packages.len(), 9);
    let all = meta.packages.iter().find(|p| p.name == "all").unwrap();
    assert_eq!(all.version, semver::Version::parse("0.1.0").unwrap());
    assert_eq!(all.authors, vec!["Jane Doe <user@example.com>"]);
    assert!(all.id.to_string().starts_with("all"));
    assert_eq!(all.description, Some("Package description.".to_string()));
    assert_eq!(all.license, Some("MIT/Apache-2.0".to_string()));
    assert_eq!(all.license_file, Some(Utf8PathBuf::from("LICENSE")));
    assert!(all.license_file().unwrap().ends_with("tests/all/LICENSE"));
    assert_eq!(all.publish, Some(vec![]));
    assert_eq!(all.links, Some("foo".to_string()));
    assert_eq!(all.default_run, Some("otherbin".to_string()));
    if ver >= semver::Version::parse("1.58.0").unwrap() {
        assert_eq!(
            all.rust_version,
            Some(semver::VersionReq::parse("1.56").unwrap())
        );
    }

    assert_eq!(all.dependencies.len(), 8);
    let bitflags = all
        .dependencies
        .iter()
        .find(|d| d.name == "bitflags")
        .unwrap();
    assert_eq!(
        bitflags.source,
        Some("registry+https://github.com/rust-lang/crates.io-index".to_string())
    );
    assert!(bitflags.optional);
    assert_eq!(bitflags.req, semver::VersionReq::parse("^1.0").unwrap());

    let path_dep = all
        .dependencies
        .iter()
        .find(|d| d.name == "path-dep")
        .unwrap();
    assert_eq!(path_dep.source, None);
    assert_eq!(path_dep.kind, DependencyKind::Normal);
    assert_eq!(path_dep.req, semver::VersionReq::parse("*").unwrap());
    assert_eq!(
        path_dep.path.as_ref().map(|p| p.ends_with("path-dep")),
        Some(true),
    );

    all.dependencies
        .iter()
        .find(|d| d.name == "namedep")
        .unwrap();

    let featdep = all
        .dependencies
        .iter()
        .find(|d| d.name == "featdep")
        .unwrap();
    assert_eq!(featdep.features, vec!["i128"]);
    assert!(!featdep.uses_default_features);

    let renamed = all
        .dependencies
        .iter()
        .find(|d| d.name == "oldname")
        .unwrap();
    assert_eq!(renamed.rename, Some("newname".to_string()));

    let devdep = all
        .dependencies
        .iter()
        .find(|d| d.name == "devdep")
        .unwrap();
    assert_eq!(devdep.kind, DependencyKind::Development);

    let bdep = all.dependencies.iter().find(|d| d.name == "bdep").unwrap();
    assert_eq!(bdep.kind, DependencyKind::Build);

    let windep = all
        .dependencies
        .iter()
        .find(|d| d.name == "windep")
        .unwrap();
    assert_eq!(
        windep.target.as_ref().map(|x| x.to_string()),
        Some("cfg(windows)".to_string())
    );

    macro_rules! get_file_name {
        ($v:expr) => {
            all.targets
                .iter()
                .find(|t| t.src_path.file_name().unwrap() == $v)
                .unwrap()
        };
    }
    assert_eq!(all.targets.len(), 8);
    let lib = get_file_name!("lib.rs");
    assert_eq!(lib.name, "all");
    assert_eq!(sorted!(lib.kind), vec!["cdylib", "rlib", "staticlib"]);
    assert_eq!(
        sorted!(lib.crate_types),
        vec!["cdylib", "rlib", "staticlib"]
    );
    assert_eq!(lib.required_features.len(), 0);
    assert_eq!(lib.edition, Edition::E2018);
    assert!(lib.doctest);
    assert!(lib.test);
    assert!(lib.doc);

    let main = get_file_name!("main.rs");
    assert_eq!(main.crate_types, vec!["bin"]);
    assert_eq!(main.kind, vec!["bin"]);
    assert!(!main.doctest);
    assert!(main.test);
    assert!(main.doc);

    let otherbin = get_file_name!("otherbin.rs");
    assert_eq!(otherbin.edition, Edition::E2015);
    assert!(!otherbin.doc);

    let reqfeat = get_file_name!("reqfeat.rs");
    assert_eq!(reqfeat.required_features, vec!["feat2"]);

    let ex1 = get_file_name!("ex1.rs");
    assert_eq!(ex1.kind, vec!["example"]);
    assert!(!ex1.test);

    let t1 = get_file_name!("t1.rs");
    assert_eq!(t1.kind, vec!["test"]);

    let b1 = get_file_name!("b1.rs");
    assert_eq!(b1.kind, vec!["bench"]);

    let build = get_file_name!("build.rs");
    assert_eq!(build.kind, vec!["custom-build"]);

    if ver >= semver::Version::parse("1.60.0").unwrap() {
        // 1.60 now reports optional dependencies within the features table
        assert_eq!(all.features.len(), 4);
        assert_eq!(all.features["bitflags"], vec!["dep:bitflags"]);
    } else {
        assert_eq!(all.features.len(), 3);
    }
    assert_eq!(all.features["feat1"].len(), 0);
    assert_eq!(all.features["feat2"].len(), 0);
    assert_eq!(sorted!(all.features["default"]), vec!["bitflags", "feat1"]);

    assert!(all.manifest_path.ends_with("all/Cargo.toml"));
    assert_eq!(all.categories, vec!["command-line-utilities"]);
    assert_eq!(all.keywords, vec!["cli"]);
    assert_eq!(all.readme, Some(Utf8PathBuf::from("README.md")));
    assert!(all.readme().unwrap().ends_with("tests/all/README.md"));
    assert_eq!(
        all.repository,
        Some("https://github.com/oli-obk/cargo_metadata/".to_string())
    );
    assert_eq!(
        all.homepage,
        Some("https://github.com/oli-obk/cargo_metadata/".to_string())
    );
    assert_eq!(
        all.documentation,
        Some("https://docs.rs/cargo_metadata/".to_string())
    );
    assert_eq!(all.edition, Edition::E2018);
    assert_eq!(
        all.metadata,
        json!({
            "docs": {
                "rs": {
                    "all-features": true,
                    "default-target": "x86_64-unknown-linux-gnu",
                    "rustc-args": ["--example-rustc-arg"]
                }
            }
        })
    );

    let resolve = meta.resolve.as_ref().unwrap();
    assert!(resolve
        .root
        .as_ref()
        .unwrap()
        .to_string()
        .starts_with("all"));

    assert_eq!(resolve.nodes.len(), 9);
    let path_dep = resolve
        .nodes
        .iter()
        .find(|n| n.id.to_string().starts_with("path-dep"))
        .unwrap();
    assert_eq!(path_dep.deps.len(), 0);
    assert_eq!(path_dep.dependencies.len(), 0);
    assert_eq!(path_dep.features.len(), 0);

    let bitflags = resolve
        .nodes
        .iter()
        .find(|n| n.id.to_string().starts_with("bitflags"))
        .unwrap();
    assert_eq!(bitflags.features, vec!["default"]);

    let featdep = resolve
        .nodes
        .iter()
        .find(|n| n.id.to_string().starts_with("featdep"))
        .unwrap();
    assert_eq!(featdep.features, vec!["i128"]);

    let all = resolve
        .nodes
        .iter()
        .find(|n| n.id.to_string().starts_with("all"))
        .unwrap();
    assert_eq!(all.dependencies.len(), 8);
    assert_eq!(all.deps.len(), 8);
    let newname = all.deps.iter().find(|d| d.name == "newname").unwrap();
    assert!(newname.pkg.to_string().starts_with("oldname"));
    // Note the underscore here.
    let path_dep = all.deps.iter().find(|d| d.name == "path_dep").unwrap();
    assert!(path_dep.pkg.to_string().starts_with("path-dep"));
    assert_eq!(path_dep.dep_kinds.len(), 1);
    let kind = &path_dep.dep_kinds[0];
    assert_eq!(kind.kind, DependencyKind::Normal);
    assert!(kind.target.is_none());

    let namedep = all
        .deps
        .iter()
        .find(|d| d.name == "different_name")
        .unwrap();
    assert!(namedep.pkg.to_string().starts_with("namedep"));
    assert_eq!(sorted!(all.features), vec!["bitflags", "default", "feat1"]);

    let bdep = all.deps.iter().find(|d| d.name == "bdep").unwrap();
    assert_eq!(bdep.dep_kinds.len(), 1);
    let kind = &bdep.dep_kinds[0];
    assert_eq!(kind.kind, DependencyKind::Build);
    assert!(kind.target.is_none());

    let devdep = all.deps.iter().find(|d| d.name == "devdep").unwrap();
    assert_eq!(devdep.dep_kinds.len(), 1);
    let kind = &devdep.dep_kinds[0];
    assert_eq!(kind.kind, DependencyKind::Development);
    assert!(kind.target.is_none());

    let windep = all.deps.iter().find(|d| d.name == "windep").unwrap();
    assert_eq!(windep.dep_kinds.len(), 1);
    let kind = &windep.dep_kinds[0];
    assert_eq!(kind.kind, DependencyKind::Normal);
    assert_eq!(
        kind.target.as_ref().map(|x| x.to_string()),
        Some("cfg(windows)".to_string())
    );
}

#[test]
fn alt_registry() {
    // This is difficult to test (would need to set up a custom index).
    // Just manually check the JSON is handled.
    let json = r#"
{
  "packages": [
    {
      "name": "alt",
      "version": "0.1.0",
      "id": "alt 0.1.0 (path+file:///alt)",
      "source": null,
      "dependencies": [
        {
          "name": "alt2",
          "source": "registry+https://example.com",
          "req": "^0.1",
          "kind": null,
          "rename": null,
          "optional": false,
          "uses_default_features": true,
          "features": [],
          "target": null,
          "registry": "https://example.com"
        }
      ],
      "targets": [
        {
          "kind": [
            "lib"
          ],
          "crate_types": [
            "lib"
          ],
          "name": "alt",
          "src_path": "/alt/src/lib.rs",
          "edition": "2018"
        }
      ],
      "features": {},
      "manifest_path": "/alt/Cargo.toml",
      "metadata": null,
      "authors": [],
      "categories": [],
      "keywords": [],
      "readme": null,
      "repository": null,
      "edition": "2018",
      "links": null
    }
  ],
  "workspace_members": [
    "alt 0.1.0 (path+file:///alt)"
  ],
  "resolve": null,
  "target_directory": "/alt/target",
  "version": 1,
  "workspace_root": "/alt"
}
"#;
    let meta: Metadata = serde_json::from_str(json).unwrap();
    assert_eq!(meta.packages.len(), 1);
    let alt = &meta.packages[0];
    let deps = &alt.dependencies;
    assert_eq!(deps.len(), 1);
    let dep = &deps[0];
    assert_eq!(dep.registry, Some("https://example.com".to_string()));
}

#[test]
fn current_dir() {
    let meta = MetadataCommand::new()
        .current_dir("tests/all/namedep")
        .exec()
        .unwrap();
    let namedep = meta.packages.iter().find(|p| p.name == "namedep").unwrap();
    assert!(namedep.name.starts_with("namedep"));
}

#[test]
fn parse_stream_is_robust() {
    // Proc macros can print stuff to stdout, which naturally breaks JSON messages.
    // Let's check that we don't die horribly in this case, and report an error.
    let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false}
Evil proc macro was here!
{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false}
"##;
    let mut n_messages = 0;
    let mut text = String::new();
    for message in cargo_metadata::Message::parse_stream(json_output.as_bytes()) {
        let message = message.unwrap();
        match message {
            cargo_metadata::Message::TextLine(line) => text = line,
            _ => n_messages += 1,
        }
    }
    assert_eq!(n_messages, 2);
    assert_eq!(text, "Evil proc macro was here!");
}

#[test]
fn advanced_feature_configuration() {
    fn build_features<F: FnOnce(&mut MetadataCommand) -> &mut MetadataCommand>(
        func: F,
    ) -> Vec<String> {
        let mut meta = MetadataCommand::new();
        let meta = meta.manifest_path("tests/all/Cargo.toml");

        let meta = func(meta);
        let meta = meta.exec().unwrap();

        let resolve = meta.resolve.as_ref().unwrap();

        let all = resolve
            .nodes
            .iter()
            .find(|n| n.id.to_string().starts_with("all"))
            .unwrap();

        all.features.clone()
    }

    // Default behavior; tested above
    let default_features = build_features(|meta| meta);
    assert_eq!(
        sorted!(default_features),
        vec!["bitflags", "default", "feat1"]
    );

    // Manually specify the same default features
    let manual_features = build_features(|meta| {
        meta.features(CargoOpt::NoDefaultFeatures)
            .features(CargoOpt::SomeFeatures(vec![
                "feat1".into(),
                "bitflags".into(),
            ]))
    });
    assert_eq!(sorted!(manual_features), vec!["bitflags", "feat1"]);

    // Multiple SomeFeatures is same as one longer SomeFeatures
    let manual_features = build_features(|meta| {
        meta.features(CargoOpt::NoDefaultFeatures)
            .features(CargoOpt::SomeFeatures(vec!["feat1".into()]))
            .features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
    });
    assert_eq!(sorted!(manual_features), vec!["feat1", "feat2"]);

    // No features + All features == All features
    let all_features = build_features(|meta| {
        meta.features(CargoOpt::AllFeatures)
            .features(CargoOpt::NoDefaultFeatures)
    });
    assert_eq!(
        sorted!(all_features),
        vec!["bitflags", "default", "feat1", "feat2"]
    );

    // The '--all-features' flag supersedes other feature flags
    let all_flag_variants = build_features(|meta| {
        meta.features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
            .features(CargoOpt::NoDefaultFeatures)
            .features(CargoOpt::AllFeatures)
    });
    assert_eq!(sorted!(all_flag_variants), sorted!(all_features));
}

#[test]
fn depkind_to_string() {
    assert_eq!(DependencyKind::Normal.to_string(), "normal");
    assert_eq!(DependencyKind::Development.to_string(), "dev");
    assert_eq!(DependencyKind::Build.to_string(), "build");
    assert_eq!(DependencyKind::Unknown.to_string(), "Unknown");
}

#[test]
fn basic_workspace_root_package_exists() {
    // First try with dependencies
    let meta = MetadataCommand::new()
        .manifest_path("tests/basic_workspace/Cargo.toml")
        .exec()
        .unwrap();
    assert_eq!(meta.root_package().unwrap().name, "ex_bin");
    // Now with no_deps, it should still work exactly the same
    let meta = MetadataCommand::new()
        .manifest_path("tests/basic_workspace/Cargo.toml")
        .no_deps()
        .exec()
        .unwrap();
    assert_eq!(
        meta.root_package()
            .expect("workspace root still exists when no_deps used")
            .name,
        "ex_bin"
    );
}

[ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge