use std::path::PathBuf;
use std::sync::Arc;
use deq_runtime::controller::ParseByName;
use deq_runtime::decoder::blackbox_decoder::{self, black_box_decoder_server::BlackBoxDecoder};
use deq_runtime::decoder::{DecoderType, DynDecoder, DynLibDecoder};
use deq_runtime::util::BitVector;
use serde_json::json;
use tonic::Request;
fn plugin_path() -> PathBuf {
let exe = std::env::current_exe().expect("current_exe");
let profile_dir = exe.ancestors().nth(2).expect("profile dir above deps/").to_path_buf();
let name = format!(
"{}deq_decoder_reference_plugin{}",
std::env::consts::DLL_PREFIX,
std::env::consts::DLL_SUFFIX
);
profile_dir.join(name)
}
fn sample_hypergraph() -> blackbox_decoder::DecodingHypergraph {
blackbox_decoder::DecodingHypergraph {
vertex_num: 3,
hyperedges: vec![
blackbox_decoder::Hyperedge {
vertices: vec![0, 1],
probability: 0.1,
},
blackbox_decoder::Hyperedge {
vertices: vec![1, 2],
probability: 0.1,
},
],
}
}
fn syndrome(size: u64, set_vertices: &[u64]) -> BitVector {
let mut data = vec![0u8; usize::try_from(size.div_ceil(8)).unwrap()];
for &v in set_vertices {
data[(v / 8) as usize] |= 1 << (7 - (v % 8) as u8);
}
BitVector { size, data }
}
#[tokio::test]
async fn load_and_decode_through_grpc_surface() {
let path = plugin_path();
assert!(
path.exists(),
"reference plugin not found at {} (run `cargo build -p deq-decoder-reference-plugin`)",
path.display()
);
let config = json!({ "parallel": 1, "library": path });
let decoder = Arc::new(DynLibDecoder::new(config));
let hid = BlackBoxDecoder::load_hypergraph(&*decoder, Request::new(sample_hypergraph()))
.await
.expect("load_hypergraph")
.into_inner()
.hid;
let decode = |set_vertices: Vec<u64>| {
let decoder = decoder.clone();
async move {
BlackBoxDecoder::decode_loaded(
&*decoder,
Request::new(blackbox_decoder::LoadedDecodingProblem {
hid,
syndrome: Some(syndrome(3, &set_vertices)),
..Default::default()
}),
)
.await
.expect("decode_loaded")
.into_inner()
.subgraph
}
};
assert_eq!(decode(vec![0]).await, vec![0]); assert_eq!(decode(vec![1]).await, vec![0, 1]); assert_eq!(decode(vec![]).await, Vec::<u64>::new()); }
#[tokio::test]
async fn isolated_zero_vertex_is_supported() {
let path = plugin_path();
assert!(
path.exists(),
"reference plugin not found at {} (run `cargo build -p deq-decoder-reference-plugin`)",
path.display()
);
let decoder = DynDecoder::BlackBoxDynLib(Arc::new(DynLibDecoder::new(json!({
"parallel": 1,
"library": path,
}))));
let hypergraph = blackbox_decoder::DecodingHypergraph {
vertex_num: 2,
hyperedges: vec![blackbox_decoder::Hyperedge {
vertices: vec![0],
probability: 0.1,
}],
};
let syndrome = syndrome(2, &[0]);
decoder
.decode(blackbox_decoder::DecodingProblem {
hypergraph: Some(hypergraph.clone()),
syndrome: Some(syndrome.clone()),
loss: None,
})
.await
.unwrap();
let hid = decoder.load_hypergraph(hypergraph).await.unwrap().hid;
decoder
.decode_loaded(blackbox_decoder::LoadedDecodingProblem {
hid,
syndrome: Some(syndrome),
..Default::default()
})
.await
.unwrap();
}
#[test]
fn cli_name_selects_dynlib() {
assert_eq!(DecoderType::from_name("black-box-dyn-lib"), Some(DecoderType::BlackBoxDynLib));
assert!(DecoderType::variant_names().contains(&"black-box-dyn-lib"));
let config = json!({ "parallel": 1, "library": plugin_path() });
let decoder = DecoderType::BlackBoxDynLib.create(config);
assert!(matches!(decoder, DynDecoder::BlackBoxDynLib(_)));
}