//! Tests which exercise various aspects of the `For` loop. mod common; use crate::common::*; #[test] fn if_statement_with_dict_loop() { #[derive(Clone)] #[allow(dead_code)] #[repr(C)] struct Args { left: WeldVec, right: WeldVec, } // This code resembles a hash join! let code = " |left: vec[i64], right: vec[i64]| let bd = result(for(left, groupmerger[i64,i64], |b,i,e| merge(b, {e, e}) ) ); result(for(right, appender[{i64, i64}], |b: appender[{i64, i64}], i: i64, ns: i64| if (keyexists(bd, ns), for(lookup(bd, ns), b, |b1: appender[{i64, i64}], i1: i64, ns1: i64| merge(b1, {ns1, ns}) ), b) ))"; let ref conf = default_conf(); let mut left = Vec::with_capacity(20); let mut right = Vec::with_capacity(1000); // 525, 550, ... 1000 for i in 500..1000 { if i % 20 == 0 { left.push(i as i64); } } for i in 0..1000 { right.push(i as i64); } let ref input_data = Args { left: WeldVec::from(&left), right: WeldVec::from(&right), }; let ret_value = compile_and_run(code, conf, input_data); let data = ret_value.data() as *const WeldVec>; let result = unsafe { (*data).clone() }; // Output should be the left-side as pairs (i.e., {525,525}, {550,550},etc.) assert_eq!(result.len as usize, left.len()); let mut sorted = vec![]; for i in 0..(result.len as isize) { let left = unsafe { (*result.data.offset(i)).ele1 }; let right = unsafe { (*result.data.offset(i)).ele2 }; sorted.push((left, right)); } // Compare sorted pairs with the output. sorted.sort(); for (a, (b, c)) in left.into_iter().zip(sorted) { assert_eq!(a, b); assert_eq!(a, c); } } #[test] fn nested_if_statement_loop() { let code = "|p: vec[i64]| result(for(p,merger[i64, +], |bs, i, ns| if(ns >= 3L, if(ns < 7L, merge(bs, ns), bs), bs)))"; let ref conf = default_conf(); let input_vec: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let ref input_data = WeldVec::from(&input_vec); let ret_value = compile_and_run(code, conf, input_data); let data = ret_value.data() as *const i32; let result = unsafe { (*data).clone() }; let output = 18; assert_eq!(result, output); } #[test] fn nested_if_statement_with_builders_loop() { let code = "|p: vec[i64]| let filter = result(for(p,appender[i64], |bs, i, ns|if(ns >= 3L, if(ns < 7L, merge(bs, ns), bs), bs))); result(for(filter, merger[i64, +], |bs2, i2, ns2| merge(bs2, ns2)))"; let ref conf = default_conf(); let input_vec: Vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let ref input_data = WeldVec::from(&input_vec); let ret_value = compile_and_run(code, conf, input_data); let data = ret_value.data() as *const i32; let result = unsafe { (*data).clone() }; let output = 18; assert_eq!(result, output); } #[test] fn nested_appender_loop() { let size = 100; let r0 = vec![0; size as usize]; let r1 = vec![1; size as usize]; let r2 = vec![2; size as usize]; let r3 = vec![3; size as usize]; let r4 = vec![4; size as usize]; // Wrap the arrays in WeldVecs. let wv0 = WeldVec::new(r0.as_ptr() as *const i32, r0.len() as i64); let wv1 = WeldVec::new(r1.as_ptr() as *const i32, r1.len() as i64); let wv2 = WeldVec::new(r2.as_ptr() as *const i32, r2.len() as i64); let wv3 = WeldVec::new(r3.as_ptr() as *const i32, r3.len() as i64); let wv4 = WeldVec::new(r4.as_ptr() as *const i32, r4.len() as i64); let input_data = [wv0, wv1, wv2, wv3, wv4]; let ref arg = WeldVec::new( input_data.as_ptr() as *const WeldVec>, input_data.len() as i64, ); let expect = [r0, r1, r2, r3, r4]; // Computes the identity. let code = "|e0: vec[vec[i32]]| map(e0, |x:vec[i32]| map(x, |y:i32| y))"; let ref conf = default_conf(); let ret_value = compile_and_run(code, conf, arg); let data = ret_value.data() as *const WeldVec>; let result = unsafe { (*data).clone() }; // Make sure we get the same thing back. assert_eq!(result.len, 5); for i in 0..(result.len as isize) { let inner = unsafe { result.data.offset(i) }; let inner_length = unsafe { (*inner).len }; assert_eq!(inner_length, size); for j in 0..(inner_length as isize) { assert_eq!( unsafe { *((*inner).data.offset(i)) }, expect[i as usize][j as usize] ); } } } #[test] fn nested_for_loops() { #[derive(Clone)] #[allow(dead_code)] struct Row { x: i64, y: i32, } let code = "|ys:vec[i64]|result(for(ys, appender[{i64, i32}], |b0, i0, y0| for(ys, b0, |b1, i1, y1| if (y1 > y0, merge(b0, {y0, i32(y1)}), b0))))"; let ref conf = default_conf(); // Input data. let ys = vec![1i64, 3i64, 4i64]; let ref input_data = WeldVec::from(&ys); let ret_value = compile_and_run(code, conf, input_data); let data = ret_value.data() as *const WeldVec; let result = unsafe { (*data).clone() }; assert_eq!(result.len, 3i64); let row = unsafe { (*result.data.offset(0)).clone() }; assert_eq!(row.x, 1i64); assert_eq!(row.y, 3); let row = unsafe { (*result.data.offset(1)).clone() }; assert_eq!(row.x, 1i64); assert_eq!(row.y, 4); let row = unsafe { (*result.data.offset(2)).clone() }; assert_eq!(row.x, 3i64); assert_eq!(row.y, 4); } #[test] fn appender_and_dictmerger_loop() { #[derive(Clone)] #[allow(dead_code)] struct Pair { ele1: i32, ele2: i32, } #[derive(Clone)] #[allow(dead_code)] struct Output { append_out: WeldVec, dict_out: WeldVec, } #[allow(dead_code)] struct Args { x: WeldVec, y: WeldVec, } let code = "|x:vec[i32], y:vec[i32]| let rs = for(zip(x,y),{appender[i32],dictmerger[i32,i32,+]}, |bs,i,e| {merge(bs.$0, e.$0+e.$1), merge(bs.$1, e)}); {result(rs.$0), tovec(result(rs.$1))}"; let ref conf = default_conf(); let keys = [1, 2, 2, 1, 3]; let vals = [2, 3, 4, 2, 1]; let ref input_data = Args { x: WeldVec::from(&keys), y: WeldVec::from(&vals), }; let ret_value = compile_and_run(code, conf, input_data); let data = ret_value.data() as *const Output; let result = unsafe { (*data).clone() }; let output_appender = [3, 5, 6, 3, 4]; let output_dict_keys = [1, 2, 3]; let output_dict_vals = [4, 7, 1]; assert_eq!(result.append_out.len, output_appender.len() as i64); for i in 0..(output_appender.len() as isize) { assert_eq!( unsafe { *result.append_out.data.offset(i) }, output_appender[i as usize] ); } assert_eq!(result.dict_out.len, output_dict_keys.len() as i64); for i in 0..(output_dict_keys.len() as isize) { let mut success = false; let key = unsafe { (*result.dict_out.data.offset(i)).ele1 }; let value = unsafe { (*result.dict_out.data.offset(i)).ele2 }; for j in 0..(output_dict_keys.len()) { if output_dict_keys[j] == key { if output_dict_vals[j] == value { success = true; } } } assert_eq!(success, true); } }