@@ -438,6 +438,13 @@ type TestData struct {
438438 Active bool
439439}
440440
441+ // Nested struct that contains both a struct and pointer to struct
442+ type NestedStruct struct {
443+ Config TestConfig
444+ DataPtr * TestData
445+ Metadata string
446+ }
447+
441448// Task function that accepts a struct and pointer to struct
442449func taskWithStructParams (config TestConfig , data * TestData ) (string , error ) {
443450 if data == nil {
@@ -446,6 +453,14 @@ func taskWithStructParams(config TestConfig, data *TestData) (string, error) {
446453 return fmt .Sprintf ("%s-%d: %s (ID: %d, Active: %t)" , config .Name , config .Value , data .Message , data .ID , data .Active ), nil
447454}
448455
456+ // Task function that accepts a nested struct with both struct and pointer fields
457+ func taskWithNestedStruct (nested NestedStruct ) (string , error ) {
458+ if nested .DataPtr == nil {
459+ return "" , fmt .Errorf ("nested.DataPtr cannot be nil" )
460+ }
461+ return fmt .Sprintf ("%s: %s-%d | %s (ID: %d, Active: %t)" , nested .Metadata , nested .Config .Name , nested .Config .Value , nested .DataPtr .Message , nested .DataPtr .ID , nested .DataPtr .Active ), nil
462+ }
463+
449464// TestNewRunnerWithStructParameters tests the runner with struct and pointer-to-struct parameters
450465func TestNewRunnerWithStructParameters (t * testing.T ) {
451466 tests := []struct {
@@ -560,3 +575,111 @@ func TestNewRunnerWithStructParameters(t *testing.T) {
560575 })
561576 }
562577}
578+
579+ // TestNewRunnerWithNestedStruct tests the runner with nested structs containing both struct and pointer fields
580+ func TestNewRunnerWithNestedStruct (t * testing.T ) {
581+ tests := []struct {
582+ name string
583+ param interface {}
584+ wantErr bool
585+ wantResult string
586+ }{
587+ {
588+ name : "Direct Nested Struct with Struct and Pointer" ,
589+ param : NestedStruct {
590+ Config : TestConfig {
591+ Name : "nested-config" ,
592+ Value : 100 ,
593+ },
594+ DataPtr : & TestData {
595+ ID : 10 ,
596+ Message : "nested data" ,
597+ Active : true ,
598+ },
599+ Metadata : "meta-direct" ,
600+ },
601+ wantErr : false ,
602+ wantResult : "meta-direct: nested-config-100 | nested data (ID: 10, Active: true)" ,
603+ },
604+ {
605+ name : "Map to Nested Struct Conversion" ,
606+ param : map [string ]interface {}{
607+ "Config" : map [string ]interface {}{
608+ "Name" : "map-config" ,
609+ "Value" : 200 ,
610+ },
611+ "DataPtr" : map [string ]interface {}{
612+ "ID" : 20 ,
613+ "Message" : "map data" ,
614+ "Active" : false ,
615+ },
616+ "Metadata" : "meta-from-map" ,
617+ },
618+ wantErr : false ,
619+ wantResult : "meta-from-map: map-config-200 | map data (ID: 20, Active: false)" ,
620+ },
621+ {
622+ name : "Map with Type Conversions in Nested Struct" ,
623+ param : map [string ]interface {}{
624+ "Config" : map [string ]interface {}{
625+ "Name" : "type-conv" ,
626+ "Value" : 300.5 , // float64 to int
627+ },
628+ "DataPtr" : map [string ]interface {}{
629+ "ID" : 30.0 , // float64 to int
630+ "Message" : "type conversion" ,
631+ "Active" : true ,
632+ },
633+ "Metadata" : "meta-type-conv" ,
634+ },
635+ wantErr : false ,
636+ wantResult : "meta-type-conv: type-conv-300 | type conversion (ID: 30, Active: true)" ,
637+ },
638+ }
639+
640+ for _ , test := range tests {
641+ t .Run (test .name , func (t * testing.T ) {
642+ mockTask , err := model .NewTask (taskWithNestedStruct )
643+ require .NoError (t , err , "Failed to create mock task" )
644+
645+ job := & model.Job {
646+ TaskName : mockTask .Name ,
647+ Parameters : []interface {}{
648+ test .param ,
649+ },
650+ Options : & model.Options {
651+ OnError : & model.OnError {
652+ Timeout : 5.0 ,
653+ },
654+ },
655+ }
656+
657+ runner , err := NewRunnerFromJob (mockTask , job )
658+ if test .wantErr {
659+ assert .Error (t , err , "NewRunnerFromJob should return an error" )
660+ return
661+ }
662+
663+ require .NoError (t , err , "NewRunnerFromJob should not return an error" )
664+ assert .NotNil (t , runner )
665+
666+ go runner .Run (context .Background ())
667+
668+ outerLoop:
669+ for {
670+ select {
671+ case err := <- runner .ErrorChannel :
672+ assert .NoError (t , err , "Runner should not return an error" )
673+ break outerLoop
674+ case results := <- runner .ResultsChannel :
675+ assert .NotNil (t , results )
676+ assert .Len (t , results , 1 )
677+ assert .Equal (t , test .wantResult , results [0 ])
678+ break outerLoop
679+ case <- time .After (2 * time .Second ):
680+ t .Fatal ("Test timed out" )
681+ }
682+ }
683+ })
684+ }
685+ }
0 commit comments