#![allow(dead_code)]
use api_parity_rs::{parity, parity_impl, ParityEntry, Status};
struct Widget;
#[parity_impl(path = "ext.widget.Widget", status = Implemented, since = "1.0")]
impl Widget {
#[parity(path = ".foo", status = Implemented)]
fn foo(&self) {}
#[parity(path = ".bar", status = Partial, comment = "missing batch mode")]
fn bar(&self) {}
#[parity(path = ".baz", status = Unimplemented, comment = "todo", issue = 42)]
fn baz(&self) {}
}
#[test]
fn parity_impl_registers_class_and_relative_children() {
let prefix = "ext.widget.Widget";
let entries: Vec<&ParityEntry> = inventory::iter::<ParityEntry>
.into_iter()
.filter(|e| e.path.starts_with(prefix))
.collect();
let paths: Vec<&str> = entries.iter().map(|e| e.path).collect();
assert!(paths.contains(&"ext.widget.Widget"));
assert!(paths.contains(&"ext.widget.Widget.foo"));
assert!(paths.contains(&"ext.widget.Widget.bar"));
assert!(paths.contains(&"ext.widget.Widget.baz"));
assert_eq!(entries.len(), 4);
let class = entries
.iter()
.find(|e| e.path == "ext.widget.Widget")
.unwrap();
assert_eq!(class.implementation, "Widget");
assert_eq!(class.status, Status::Implemented);
assert_eq!(class.since, Some("1.0"));
let foo = entries
.iter()
.find(|e| e.path == "ext.widget.Widget.foo")
.unwrap();
assert_eq!(foo.implementation, "Widget::foo");
assert_eq!(foo.status, Status::Implemented);
assert_eq!(foo.comment, None);
let baz = entries
.iter()
.find(|e| e.path == "ext.widget.Widget.baz")
.unwrap();
assert_eq!(baz.status, Status::Unimplemented);
assert_eq!(baz.comment, Some("todo"));
assert_eq!(baz.issue, Some(42));
}
struct Naked;
#[parity_impl]
impl Naked {
#[parity(path = "ext.naked.absolute_only", status = Implemented)]
fn whatever(&self) {}
}
#[test]
fn parity_impl_without_parent_path_registers_absolute_child() {
let entries: Vec<&ParityEntry> = inventory::iter::<ParityEntry>
.into_iter()
.filter(|e| e.path.starts_with("ext.naked."))
.collect();
assert_eq!(entries.len(), 1, "no class-level entry should appear");
let e = entries[0];
assert_eq!(e.path, "ext.naked.absolute_only");
assert_eq!(e.implementation, "Naked::whatever");
}
#[parity(path = "ext.free.solo", status = Partial, comment = "wip")]
fn solo() {}
#[test]
fn parity_on_free_fn_uses_module_path() {
let e = inventory::iter::<ParityEntry>
.into_iter()
.find(|e| e.path == "ext.free.solo")
.expect("entry should be registered");
assert!(
e.implementation.ends_with("::solo"),
"implementation = {}",
e.implementation,
);
assert_eq!(e.status, Status::Partial);
assert_eq!(e.comment, Some("wip"));
}
#[parity(path = "ext.type.gizmo", status = Implemented)]
struct Gizmo {
id: u64,
}
#[parity(path = "ext.type.color", status = Partial, comment = "no alpha")]
enum Color {
Red,
Green,
}
#[parity(path = "ext.type.datatype", status = Implemented)]
type DataType = std::collections::HashMap<String, String>;
#[test]
fn parity_on_type_definitions_uses_module_path() {
let find = |path: &str| {
inventory::iter::<ParityEntry>
.into_iter()
.find(|e| e.path == path)
.unwrap_or_else(|| panic!("entry {path} should be registered"))
};
let gizmo = find("ext.type.gizmo");
assert!(
gizmo.implementation.ends_with("::Gizmo"),
"implementation = {}",
gizmo.implementation,
);
assert_eq!(gizmo.status, Status::Implemented);
let color = find("ext.type.color");
assert!(color.implementation.ends_with("::Color"));
assert_eq!(color.status, Status::Partial);
let dt = find("ext.type.datatype");
assert!(
dt.implementation.ends_with("::DataType"),
"implementation = {}",
dt.implementation,
);
assert!(
!dt.implementation.contains("HashMap"),
"alias must record the local name, not the backing type: {}",
dt.implementation,
);
}
#[cfg(feature = "serde")]
#[test]
fn dump_to_writer_emits_sorted_envelope() {
use api_parity_rs::dump_to_writer;
let mut buf: Vec<u8> = Vec::new();
dump_to_writer("test-source", "9.9.9", &mut buf).unwrap();
let s = String::from_utf8(buf).unwrap();
let v: serde_json::Value = serde_json::from_str(&s).unwrap();
assert_eq!(v["schema_version"], 1);
assert_eq!(v["kind"], "port");
assert_eq!(v["language"], "rust");
assert_eq!(v["source"], "test-source");
assert_eq!(v["version"], "9.9.9");
let arr = v["entries"].as_array().unwrap();
assert!(arr.len() >= 9, "expected ≥9 entries, got {}", arr.len());
for w in arr.windows(2) {
assert!(
w[0]["path"].as_str().unwrap() <= w[1]["path"].as_str().unwrap(),
"entries must be sorted by path",
);
}
}