Skip to content

Commit 4211637

Browse files
committed
test(class): add extends and implements tests
Refs: #326
1 parent 13a74d7 commit 4211637

File tree

9 files changed

+1062
-22
lines changed

9 files changed

+1062
-22
lines changed

src/args.rs

Lines changed: 267 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ impl<'a> Arg<'a> {
177177

178178
impl From<Arg<'_>> for _zend_expected_type {
179179
fn from(arg: Arg) -> Self {
180-
let err = match arg.r#type {
180+
let type_id = match arg.r#type {
181181
DataType::False | DataType::True => _zend_expected_type_Z_EXPECTED_BOOL,
182182
DataType::Long => _zend_expected_type_Z_EXPECTED_LONG,
183183
DataType::Double => _zend_expected_type_Z_EXPECTED_DOUBLE,
@@ -189,9 +189,9 @@ impl From<Arg<'_>> for _zend_expected_type {
189189
};
190190

191191
if arg.allow_null {
192-
err + 1
192+
type_id + 1
193193
} else {
194-
err
194+
type_id
195195
}
196196
}
197197
}
@@ -302,3 +302,267 @@ impl<'a, 'b> ArgParser<'a, 'b> {
302302
Ok(())
303303
}
304304
}
305+
306+
#[cfg(test)]
307+
mod tests {
308+
#![allow(clippy::unwrap_used)]
309+
310+
use super::*;
311+
312+
#[test]
313+
fn test_new() {
314+
let arg = Arg::new("test", DataType::Long);
315+
assert_eq!(arg.name, "test");
316+
assert_eq!(arg.r#type, DataType::Long);
317+
assert!(!arg.as_ref);
318+
assert!(!arg.allow_null);
319+
assert!(!arg.variadic);
320+
assert!(arg.default_value.is_none());
321+
assert!(arg.zval.is_none());
322+
assert!(arg.variadic_zvals.is_empty());
323+
}
324+
325+
#[test]
326+
fn test_as_ref() {
327+
let arg = Arg::new("test", DataType::Long).as_ref();
328+
assert!(arg.as_ref);
329+
}
330+
331+
#[test]
332+
fn test_is_variadic() {
333+
let arg = Arg::new("test", DataType::Long).is_variadic();
334+
assert!(arg.variadic);
335+
}
336+
337+
#[test]
338+
fn test_allow_null() {
339+
let arg = Arg::new("test", DataType::Long).allow_null();
340+
assert!(arg.allow_null);
341+
}
342+
343+
#[test]
344+
fn test_default() {
345+
let arg = Arg::new("test", DataType::Long).default("default");
346+
assert_eq!(arg.default_value, Some("default".to_string()));
347+
348+
// TODO: Validate type
349+
}
350+
351+
#[test]
352+
fn test_consume_no_value() {
353+
let arg = Arg::new("test", DataType::Long);
354+
let result: Result<i32, _> = arg.consume();
355+
assert!(result.is_err());
356+
assert_eq!(result.unwrap_err().name, "test");
357+
}
358+
359+
#[test]
360+
#[cfg(feature = "embed")]
361+
fn test_consume() {
362+
let mut arg = Arg::new("test", DataType::Long);
363+
let mut zval = Zval::from(42);
364+
arg.zval = Some(&mut zval);
365+
366+
let result: Result<i32, _> = arg.consume();
367+
assert_eq!(result.unwrap(), 42);
368+
}
369+
370+
#[test]
371+
fn test_val_no_value() {
372+
let mut arg = Arg::new("test", DataType::Long);
373+
let result: Option<i32> = arg.val();
374+
assert!(result.is_none());
375+
}
376+
377+
#[test]
378+
#[cfg(feature = "embed")]
379+
fn test_val() {
380+
let mut arg = Arg::new("test", DataType::Long);
381+
let mut zval = Zval::from(42);
382+
arg.zval = Some(&mut zval);
383+
384+
let result: Option<i32> = arg.val();
385+
assert_eq!(result.unwrap(), 42);
386+
}
387+
388+
#[test]
389+
#[cfg(feature = "embed")]
390+
fn test_variadic_vals() {
391+
let mut arg = Arg::new("test", DataType::Long).is_variadic();
392+
let mut zval1 = Zval::from(42);
393+
let mut zval2 = Zval::from(43);
394+
arg.variadic_zvals.push(Some(&mut zval1));
395+
arg.variadic_zvals.push(Some(&mut zval2));
396+
397+
let result: Vec<i32> = arg.variadic_vals();
398+
assert_eq!(result, vec![42, 43]);
399+
}
400+
401+
#[test]
402+
fn test_zval_no_value() {
403+
let mut arg = Arg::new("test", DataType::Long);
404+
let result = arg.zval();
405+
assert!(result.is_none());
406+
}
407+
408+
#[test]
409+
#[cfg(feature = "embed")]
410+
fn test_zval() {
411+
let mut arg = Arg::new("test", DataType::Long);
412+
let mut zval = Zval::from(42);
413+
arg.zval = Some(&mut zval);
414+
415+
let result = arg.zval();
416+
assert!(result.is_some());
417+
assert_eq!(result.unwrap().dereference_mut().long(), Some(42));
418+
}
419+
420+
#[test]
421+
fn test_try_call_no_value() {
422+
let arg = Arg::new("test", DataType::Long);
423+
let result = arg.try_call(vec![]);
424+
assert!(result.is_err());
425+
}
426+
427+
#[test]
428+
#[cfg(feature = "embed")]
429+
fn test_try_call_not_callable() {
430+
let mut arg = Arg::new("test", DataType::Long);
431+
let mut zval = Zval::from(42);
432+
arg.zval = Some(&mut zval);
433+
434+
let result = arg.try_call(vec![]);
435+
assert!(result.is_err());
436+
}
437+
438+
// TODO: Test the callable case
439+
440+
#[test]
441+
#[cfg(feature = "embed")]
442+
fn test_as_arg_info() {
443+
let arg = Arg::new("test", DataType::Long);
444+
let arg_info = arg.as_arg_info();
445+
assert!(arg_info.is_ok());
446+
447+
let arg_info = arg_info.unwrap();
448+
assert!(arg_info.default_value.is_null());
449+
450+
let r#type = arg_info.type_;
451+
assert_eq!(r#type.type_mask, 16);
452+
}
453+
454+
#[test]
455+
#[cfg(feature = "embed")]
456+
fn test_as_arg_info_with_default() {
457+
let arg = Arg::new("test", DataType::Long).default("default");
458+
let arg_info = arg.as_arg_info();
459+
assert!(arg_info.is_ok());
460+
461+
let arg_info = arg_info.unwrap();
462+
assert!(!arg_info.default_value.is_null());
463+
464+
let r#type = arg_info.type_;
465+
assert_eq!(r#type.type_mask, 16);
466+
}
467+
468+
#[test]
469+
fn test_type_from_arg() {
470+
let arg = Arg::new("test", DataType::Long);
471+
let actual: _zend_expected_type = arg.into();
472+
assert_eq!(actual, 0);
473+
474+
let arg = Arg::new("test", DataType::Long).allow_null();
475+
let actual: _zend_expected_type = arg.into();
476+
assert_eq!(actual, 1);
477+
478+
let arg = Arg::new("test", DataType::False);
479+
let actual: _zend_expected_type = arg.into();
480+
assert_eq!(actual, 2);
481+
482+
let arg = Arg::new("test", DataType::False).allow_null();
483+
let actual: _zend_expected_type = arg.into();
484+
assert_eq!(actual, 3);
485+
486+
let arg = Arg::new("test", DataType::True);
487+
let actual: _zend_expected_type = arg.into();
488+
assert_eq!(actual, 2);
489+
490+
let arg = Arg::new("test", DataType::True).allow_null();
491+
let actual: _zend_expected_type = arg.into();
492+
assert_eq!(actual, 3);
493+
494+
let arg = Arg::new("test", DataType::String);
495+
let actual: _zend_expected_type = arg.into();
496+
assert_eq!(actual, 4);
497+
498+
let arg = Arg::new("test", DataType::String).allow_null();
499+
let actual: _zend_expected_type = arg.into();
500+
assert_eq!(actual, 5);
501+
502+
let arg = Arg::new("test", DataType::Array);
503+
let actual: _zend_expected_type = arg.into();
504+
assert_eq!(actual, 6);
505+
506+
let arg = Arg::new("test", DataType::Array).allow_null();
507+
let actual: _zend_expected_type = arg.into();
508+
assert_eq!(actual, 7);
509+
510+
let arg = Arg::new("test", DataType::Resource);
511+
let actual: _zend_expected_type = arg.into();
512+
assert_eq!(actual, 14);
513+
514+
let arg = Arg::new("test", DataType::Resource).allow_null();
515+
let actual: _zend_expected_type = arg.into();
516+
assert_eq!(actual, 15);
517+
518+
let arg = Arg::new("test", DataType::Object(None));
519+
let actual: _zend_expected_type = arg.into();
520+
assert_eq!(actual, 18);
521+
522+
let arg = Arg::new("test", DataType::Object(None)).allow_null();
523+
let actual: _zend_expected_type = arg.into();
524+
assert_eq!(actual, 19);
525+
526+
let arg = Arg::new("test", DataType::Double);
527+
let actual: _zend_expected_type = arg.into();
528+
assert_eq!(actual, 20);
529+
530+
let arg = Arg::new("test", DataType::Double).allow_null();
531+
let actual: _zend_expected_type = arg.into();
532+
assert_eq!(actual, 21);
533+
}
534+
535+
#[test]
536+
fn test_param_from_arg() {
537+
let arg = Arg::new("test", DataType::Long)
538+
.default("default")
539+
.allow_null();
540+
let param: Parameter = arg.into();
541+
assert_eq!(param.name, "test".into());
542+
assert_eq!(param.ty, abi::Option::Some(DataType::Long));
543+
assert!(param.nullable);
544+
assert_eq!(param.default, abi::Option::Some("default".into()));
545+
}
546+
547+
#[test]
548+
fn test_arg_parser_new() {
549+
let arg_zvals = vec![None, None];
550+
let parser = ArgParser::new(arg_zvals);
551+
assert_eq!(parser.arg_zvals.len(), 2);
552+
assert!(parser.args.is_empty());
553+
assert!(parser.min_num_args.is_none());
554+
}
555+
556+
#[test]
557+
fn test_arg_parser_arg() {
558+
let arg_zvals = vec![None, None];
559+
let mut parser = ArgParser::new(arg_zvals);
560+
let mut arg = Arg::new("test", DataType::Long);
561+
parser = parser.arg(&mut arg);
562+
assert_eq!(parser.args.len(), 1);
563+
assert_eq!(parser.args[0].name, "test");
564+
assert_eq!(parser.args[0].r#type, DataType::Long);
565+
}
566+
567+
// TODO: test parse
568+
}

src/builders/class.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,100 @@ impl ClassBuilder {
372372
Ok(())
373373
}
374374
}
375+
376+
#[cfg(test)]
377+
mod tests {
378+
use crate::test::test_function;
379+
380+
use super::*;
381+
382+
#[test]
383+
fn test_new() {
384+
let class = ClassBuilder::new("Foo");
385+
assert_eq!(class.name, "Foo");
386+
assert_eq!(class.extends, None);
387+
assert_eq!(class.interfaces, vec![]);
388+
assert_eq!(class.methods.len(), 0);
389+
assert_eq!(class.object_override, None);
390+
assert_eq!(class.properties, vec![]);
391+
assert_eq!(class.constants.len(), 0);
392+
assert_eq!(class.register, None);
393+
assert_eq!(class.docs, &[] as DocComments);
394+
}
395+
396+
#[test]
397+
fn test_extends() {
398+
let extends: ClassEntryInfo = (|| todo!(), "Bar");
399+
let class = ClassBuilder::new("Foo").extends(extends);
400+
assert_eq!(class.extends, Some(extends));
401+
}
402+
403+
#[test]
404+
fn test_implements() {
405+
let implements: ClassEntryInfo = (|| todo!(), "Bar");
406+
let class = ClassBuilder::new("Foo").implements(implements);
407+
assert_eq!(class.interfaces, vec![implements]);
408+
}
409+
410+
#[test]
411+
fn test_method() {
412+
let method = FunctionBuilder::new("foo", test_function);
413+
let class = ClassBuilder::new("Foo").method(method, MethodFlags::Public);
414+
assert_eq!(class.methods.len(), 1);
415+
}
416+
417+
#[test]
418+
fn test_property() {
419+
let class = ClassBuilder::new("Foo").property("bar", PropertyFlags::Public, &["Doc 1"]);
420+
assert_eq!(
421+
class.properties,
422+
vec![(
423+
"bar".to_string(),
424+
PropertyFlags::Public,
425+
&["Doc 1"] as DocComments
426+
)]
427+
);
428+
}
429+
430+
#[test]
431+
#[cfg(feature = "embed")]
432+
fn test_constant() {
433+
let class = ClassBuilder::new("Foo")
434+
.constant("bar", 42, &["Doc 1"])
435+
.expect("Failed to create constant");
436+
assert_eq!(class.constants.len(), 1);
437+
assert_eq!(class.constants[0].0, "bar");
438+
assert_eq!(class.constants[0].2, &["Doc 1"] as DocComments);
439+
}
440+
441+
#[test]
442+
#[cfg(feature = "embed")]
443+
fn test_dyn_constant() {
444+
let class = ClassBuilder::new("Foo")
445+
.dyn_constant("bar", &42, &["Doc 1"])
446+
.expect("Failed to create constant");
447+
assert_eq!(class.constants.len(), 1);
448+
assert_eq!(class.constants[0].0, "bar");
449+
assert_eq!(class.constants[0].2, &["Doc 1"] as DocComments);
450+
}
451+
452+
#[test]
453+
fn test_flags() {
454+
let class = ClassBuilder::new("Foo").flags(ClassFlags::Abstract);
455+
assert_eq!(class.ce.ce_flags, ClassFlags::Abstract.bits());
456+
}
457+
458+
#[test]
459+
fn test_registration() {
460+
let class = ClassBuilder::new("Foo").registration(|_| {});
461+
assert!(class.register.is_some());
462+
}
463+
464+
#[test]
465+
fn test_docs() {
466+
let class = ClassBuilder::new("Foo").docs(&["Doc 1"]);
467+
assert_eq!(class.docs, &["Doc 1"] as DocComments);
468+
}
469+
470+
// TODO: Test the register function
471+
}

0 commit comments

Comments
 (0)