nu_plugin_vulkan_matrix 0.1.2

GPU matrix operations for Nushell using Vulkan
use crate::gpu::{download_array, upload_array};
use crate::resident::Resources;
use ndarray::{ArrayD, IxDyn};
use nu_protocol::{Span, Value};
use std::sync::{Arc, Barrier};

#[test]
fn handles_keep_metadata_and_inflight_resources_without_reusing_ids() {
    let span = Span::unknown();
    let gpu = crate::test_gpu::gpu().clone();
    let mut resources = Resources::new().unwrap();
    let mut restarted = Resources::new().unwrap();
    let make = || upload_array(&gpu, ArrayD::from_elem(IxDyn(&[2, 3]), 7.0_f64)).unwrap();
    let value = resources
        .insert(gpu.clone(), make(), "d0", "f64", span)
        .unwrap();
    let cloned = value.clone();
    let metadata = value
        .as_custom_value()
        .unwrap()
        .to_base_value(span)
        .unwrap();
    assert_eq!(
        metadata.as_record().unwrap().get("dtype").unwrap(),
        &Value::string("f64", span)
    );
    let held = resources.get(&cloned, span).unwrap();
    let weak = Arc::downgrade(&held);
    let barrier = Arc::new(Barrier::new(2));
    let worker_barrier = barrier.clone();
    let worker = std::thread::spawn(move || {
        worker_barrier.wait();
        download_array::<f64>(&held.gpu, &held.tensor).unwrap()
    });
    resources.remove(value.as_custom_value().unwrap());
    assert!(resources.is_empty());
    assert!(resources.get(&cloned, span).is_err());
    barrier.wait();
    assert_eq!(
        worker.join().unwrap(),
        ArrayD::from_elem(IxDyn(&[2, 3]), 7.0)
    );
    assert!(weak.upgrade().is_none());
    let next = resources
        .insert(gpu.clone(), make(), "d0", "f64", span)
        .unwrap();
    assert!(resources.get(&value, span).is_err());
    assert!(resources.get(&next, span).is_ok());
    let fresh = restarted
        .insert(gpu.clone(), make(), "d0", "f64", span)
        .unwrap();
    assert!(restarted.get(&value, span).is_err());
    assert!(resources.get(&fresh, span).is_err());
    restarted.remove(value.as_custom_value().unwrap());
    assert!(restarted.get(&fresh, span).is_ok());
    resources.remove(fresh.as_custom_value().unwrap());
    assert!(!resources.is_empty());
    assert!(next.as_custom_value().unwrap().notify_plugin_on_drop());
}