test(tvix/eval): impl Arbitrary for Value
Impl Arbitrary for Value (and NixAttrs and NixList) in the same way we did for NixString. Value currently only generates non-"internal" values (no thunks, AttrNotFound, etc.) and can't generate functions (builtins or closures), because those'd require full generation of tvix bytecode, which is a bit more work than I'd like to do now - there's a `todo!` left in the code for a place where we could allow opting-in to internal values and functions later. Change-Id: I07a59e2b1d89cfaa912d4ecebd642caf4ddb040a Reviewed-on: https://cl.tvl.fyi/c/depot/+/6627 Autosubmit: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su>
This commit is contained in:
		
							parent
							
								
									221d3b9485
								
							
						
					
					
						commit
						f8b3806720
					
				
					 4 changed files with 128 additions and 0 deletions
				
			
		
							
								
								
									
										78
									
								
								tvix/eval/src/value/arbitrary.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								tvix/eval/src/value/arbitrary.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
//! Support for configurable generation of arbitrary nix values
 | 
			
		||||
 | 
			
		||||
use proptest::{prelude::*, strategy::BoxedStrategy};
 | 
			
		||||
use std::{ffi::OsString, rc::Rc};
 | 
			
		||||
 | 
			
		||||
use super::{NixAttrs, NixList, NixString, Value};
 | 
			
		||||
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub enum Parameters {
 | 
			
		||||
    Strategy(BoxedStrategy<Value>),
 | 
			
		||||
    Parameters {
 | 
			
		||||
        generate_internal_values: bool,
 | 
			
		||||
        generate_functions: bool,
 | 
			
		||||
        generate_nested: bool,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Parameters {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self::Parameters {
 | 
			
		||||
            generate_internal_values: false,
 | 
			
		||||
            generate_functions: false,
 | 
			
		||||
            generate_nested: true,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Arbitrary for Value {
 | 
			
		||||
    type Parameters = Parameters;
 | 
			
		||||
    type Strategy = BoxedStrategy<Self>;
 | 
			
		||||
 | 
			
		||||
    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
 | 
			
		||||
        match args {
 | 
			
		||||
            Parameters::Strategy(s) => s,
 | 
			
		||||
            Parameters::Parameters {
 | 
			
		||||
                generate_internal_values,
 | 
			
		||||
                generate_functions,
 | 
			
		||||
                generate_nested,
 | 
			
		||||
            } => {
 | 
			
		||||
                if generate_internal_values || generate_functions {
 | 
			
		||||
                    todo!("Generating internal values and functions not implemented yet")
 | 
			
		||||
                } else if generate_nested {
 | 
			
		||||
                    non_internal_value().boxed()
 | 
			
		||||
                } else {
 | 
			
		||||
                    leaf_value().boxed()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn leaf_value() -> impl Strategy<Value = Value> {
 | 
			
		||||
    use Value::*;
 | 
			
		||||
 | 
			
		||||
    prop_oneof![
 | 
			
		||||
        Just(Null),
 | 
			
		||||
        any::<bool>().prop_map(Bool),
 | 
			
		||||
        any::<i64>().prop_map(Integer),
 | 
			
		||||
        any::<f64>().prop_map(Float),
 | 
			
		||||
        any::<NixString>().prop_map(String),
 | 
			
		||||
        any::<OsString>().prop_map(|s| Path(s.into())),
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn non_internal_value() -> impl Strategy<Value = Value> {
 | 
			
		||||
    leaf_value().prop_recursive(10, 256, 10, |inner| {
 | 
			
		||||
        prop_oneof![
 | 
			
		||||
            any_with::<NixAttrs>((
 | 
			
		||||
                Default::default(),
 | 
			
		||||
                Default::default(),
 | 
			
		||||
                Parameters::Strategy(inner.clone())
 | 
			
		||||
            ))
 | 
			
		||||
            .prop_map(|a| Value::Attrs(Rc::new(a))),
 | 
			
		||||
            any_with::<NixList>((Default::default(), Parameters::Strategy(inner)))
 | 
			
		||||
                .prop_map(Value::List)
 | 
			
		||||
        ]
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue