summaryrefslogtreecommitdiff
path: root/plugins/warp/tests/container.rs
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/warp/tests/container.rs')
-rw-r--r--plugins/warp/tests/container.rs280
1 files changed, 280 insertions, 0 deletions
diff --git a/plugins/warp/tests/container.rs b/plugins/warp/tests/container.rs
new file mode 100644
index 00000000..31b47377
--- /dev/null
+++ b/plugins/warp/tests/container.rs
@@ -0,0 +1,280 @@
+use std::collections::HashSet;
+use std::path::PathBuf;
+use std::str::FromStr;
+use uuid::Uuid;
+use warp::r#type::class::BooleanClass;
+use warp::r#type::class::TypeClass::Void;
+use warp::r#type::guid::TypeGUID;
+use warp::r#type::{ComputedType, Type};
+use warp::signature::function::{Function, FunctionGUID};
+use warp::symbol::{Symbol, SymbolClass};
+use warp::target::Target;
+use warp_ninja::container::disk::DiskContainer;
+use warp_ninja::container::memory::{MemoryContainer, MemorySource};
+use warp_ninja::container::{Container, ContainerError, SourceId, SourcePath};
+
+fn type_0() -> (TypeGUID, Type) {
+ let ty = Type::builder()
+ .name("type_0")
+ .class(BooleanClass::builder().width(1).build())
+ .build();
+ (TypeGUID::from(&ty), ty)
+}
+
+fn type_1() -> (TypeGUID, Type) {
+ let ty = Type::builder()
+ .name("type_1")
+ .class(BooleanClass::builder().width(4).build())
+ .build();
+ (TypeGUID::from(&ty), ty)
+}
+
+fn type_2() -> (TypeGUID, Type) {
+ let ty = Type::builder()
+ .name("type_2")
+ .class(BooleanClass::builder().width(8).build())
+ .build();
+ (TypeGUID::from(&ty), ty)
+}
+
+fn func_0() -> (FunctionGUID, Function) {
+ let guid = FunctionGUID::from(Uuid::from_str("d4e56ec8-1f2b-4a87-9f2c-bc3f10c4d8e9").unwrap());
+ let function = Function {
+ guid,
+ symbol: Symbol {
+ name: "func_0".to_string(),
+ modifiers: Default::default(),
+ class: SymbolClass::Function,
+ },
+ // TODO: We might want to give this an actual function type.
+ ty: Some(Type::builder::<String, _>().class(Void).build()),
+ constraints: Default::default(),
+ comments: vec![],
+ variables: vec![],
+ };
+ (guid, function)
+}
+
+fn func_1() -> (FunctionGUID, Function) {
+ let guid = FunctionGUID::from(Uuid::from_str("b713c293-463a-5baa-b31b-ed010510d5c0").unwrap());
+ let function = Function {
+ guid,
+ symbol: Symbol {
+ name: "func_1".to_string(),
+ modifiers: Default::default(),
+ class: SymbolClass::Function,
+ },
+ // TODO: We might want to give this an actual function type.
+ ty: Some(Type::builder::<String, _>().class(Void).build()),
+ constraints: Default::default(),
+ comments: vec![],
+ variables: vec![],
+ };
+ (guid, function)
+}
+
+#[test]
+fn test_sources_with_type_guid() {
+ let source1 = SourceId::new();
+ let source2 = SourceId::new();
+ let (guid_1, ty_1) = type_0();
+ let (guid_2, ty_2) = type_1();
+
+ let container = MemoryContainer::new()
+ .with_source_type(source1, guid_1, ty_1)
+ .with_source_type(source1, guid_2, ty_2.clone())
+ .with_source_type(source2, guid_2, ty_2);
+
+ let result = container
+ .sources_with_type_guid(&guid_2)
+ .expect("Failed to get sources");
+ // HashSet used for unordered comparison
+ let result_set: HashSet<_> = result.into_iter().collect();
+ let expected_set: HashSet<_> = vec![source1, source2].into_iter().collect();
+ assert_eq!(result_set, expected_set);
+
+ let result = container
+ .sources_with_type_guid(&guid_1)
+ .expect("Failed to get sources");
+ // HashSet used for unordered comparison
+ let result_set: HashSet<_> = result.into_iter().collect();
+ let expected_set: HashSet<_> = vec![source1].into_iter().collect();
+ assert_eq!(result_set, expected_set);
+}
+
+#[test]
+fn test_sources_with_function_guid() {
+ let target = Target::default();
+
+ let source1 = SourceId::new();
+ let source2 = SourceId::new();
+ let (guid_1, fn_1) = func_0();
+ let (guid_2, fn_2) = func_1();
+
+ let container = MemoryContainer::new()
+ .with_source_function(source1, guid_1, fn_1)
+ .with_source_function(source1, guid_2, fn_2.clone())
+ .with_source_function(source2, guid_2, fn_2);
+
+ let result = container
+ .sources_with_function_guid(&target, &guid_2)
+ .expect("Failed to get sources");
+ // HashSet used for unordered comparison
+ let result_set: HashSet<_> = result.into_iter().collect();
+ let expected_set: HashSet<_> = vec![source1, source2].into_iter().collect();
+ assert_eq!(result_set, expected_set);
+
+ let result = container
+ .sources_with_function_guid(&target, &guid_1)
+ .expect("Failed to get sources");
+ assert_eq!(result, vec![source1]);
+}
+
+#[test]
+fn test_sources_with_type_guids() {
+ let source1 = SourceId::new();
+ let source2 = SourceId::new();
+ let (guid_1, ty_1) = type_0();
+ let (guid_2, ty_2) = type_1();
+ let (guid_3, ty_3) = type_2();
+
+ let container = MemoryContainer::new()
+ .with_source_type(source1, guid_1, ty_1)
+ .with_source_type(source1, guid_2, ty_2.clone())
+ .with_source_type(source2, guid_2, ty_2)
+ .with_source_type(source2, guid_3, ty_3);
+
+ let result = container
+ .sources_with_type_guids(&[guid_2.clone(), guid_3.clone()])
+ .expect("Failed to get sources");
+ assert_eq!(result.len(), 2);
+ assert!(result.get(&guid_2).unwrap().contains(&source1));
+ assert!(result.get(&guid_2).unwrap().contains(&source2));
+ assert!(result.get(&guid_3).unwrap().contains(&source2));
+}
+
+#[test]
+fn test_add_types() {
+ let source1 = SourceId::new();
+ let source2 = SourceId::new();
+ let (guid_1, ty_1) = type_0();
+ let (guid_2, ty_2) = type_1();
+ let mut container = MemoryContainer::new()
+ .with_source(
+ source1,
+ MemorySource {
+ writable: false,
+ ..Default::default()
+ },
+ )
+ .with_source_type(source1, guid_1, ty_1.clone())
+ .with_source_type(source2, guid_2, ty_2.clone());
+
+ assert_eq!(
+ container.add_types(&source1, &[ty_1.clone()]),
+ Err(ContainerError::SourceNotWritable(source1)),
+ "Source should not be writable"
+ );
+ assert_eq!(
+ container.add_types(&source2, &[ty_1.clone()]),
+ Ok(()),
+ "Source should be writable"
+ );
+ container
+ .type_with_guid(&source1, &guid_1)
+ .expect("Failed to get existing type");
+ container
+ .type_with_guid(&source2, &guid_1)
+ .expect("Failed to get added type");
+ container
+ .type_with_guid(&source2, &guid_2)
+ .expect("Failed to get existing type");
+}
+
+#[test]
+fn test_disk_container() {
+ // We are going to use the OUT_DIR as the disk container path, this might have other artifacts in it
+ // so it's a good test to make sure that we handle bad files gracefully.
+ let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable is not set");
+ let out_dir_path: PathBuf = out_dir.parse().expect("Failed to parse OUT_DIR as path");
+
+ // TODO: Use a temp file for this instead lol.
+ let added_type_path = out_dir_path.join("added_type.warp");
+ // Make sure that we have deleted the previous runs artifacts.
+ if std::fs::exists(&added_type_path).unwrap() {
+ std::fs::remove_file(&added_type_path).expect("Failed to remove existing file");
+ }
+
+ // Write a simple test to open a file with DiskContainer
+ let mut container = DiskContainer::new_from_dir(out_dir_path.clone());
+
+ // Just pass in the default target, there is no target specified in the file.
+ let target = Target::default();
+
+ // Test type retrieval.
+ // Type -> type_10 : 2f6d2876-ec42-5ca1-bee3-f12fe91d7e13
+ let type_0 = TypeGUID::from(Uuid::from_str("2f6d2876-ec42-5ca1-bee3-f12fe91d7e13").unwrap());
+ let sources: Vec<SourceId> = container
+ .sources_with_type_guid(&type_0)
+ .expect("Failed to get sources")
+ .into_iter()
+ .collect();
+ assert_eq!(sources.len(), 1);
+ let result_type_0 = container
+ .type_with_guid(&sources[0], &type_0)
+ .expect("Failed to get type")
+ .expect("Type not found");
+ assert_eq!(result_type_0.name, Some("type_10".to_string()));
+ let result_type_guids_0 = container
+ .type_guids_with_name(&sources[0], "type_10")
+ .expect("Failed to get type guids");
+ assert_eq!(result_type_guids_0.len(), 1);
+ assert_eq!(result_type_guids_0[0], type_0);
+
+ // Test function retrieval.
+ // Function -> function_95 : d5da0413-a020-5db8-b838-4d0ea8bd3dcb
+ let func_0 =
+ FunctionGUID::from(Uuid::from_str("d5da0413-a020-5db8-b838-4d0ea8bd3dcb").unwrap());
+ let func_sources = container
+ .sources_with_function_guid(&target, &func_0)
+ .expect("Failed to get sources");
+ assert_eq!(func_sources.len(), 1);
+ let result_func_0 = container
+ .functions_with_guid(&target, &func_sources[0], &func_0)
+ .expect("Failed to get functions");
+ assert_eq!(result_func_0.len(), 1);
+ assert_eq!(result_func_0[0].symbol.name, "function_95".to_string());
+
+ // Test adding a type to an existing disk source.
+ let mut result_type_0_mut = result_type_0.clone();
+ result_type_0_mut.name = Some("added_type".to_string());
+ let computed_result_type_0 = ComputedType::new(result_type_0_mut);
+ container
+ .add_types(&sources[0], &[computed_result_type_0.ty])
+ .expect("Failed to add type");
+ let result_type_1 = container
+ .type_guids_with_name(&sources[0], "added_type")
+ .expect("Failed to get added type");
+ assert_eq!(
+ result_type_1,
+ vec![computed_result_type_0.guid],
+ "Added type was not found in the existing source"
+ );
+
+ // Test commiting the updated source.
+ // NOTE: Because we don't want to modify the file, we are going to change the source path
+ // before trying to commit it, this is a bit hacky and should not really be done in real code.
+ let source = container
+ .sources
+ .get_mut(&sources[0])
+ .expect("Container does not contain the source");
+ source.path = SourcePath::new(out_dir_path.join("added_type.warp"));
+ container
+ .commit_source(&sources[0])
+ .expect("Failed to commit source");
+ assert_eq!(
+ std::fs::exists(&added_type_path).unwrap(),
+ true,
+ "File was not created"
+ );
+}