1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package core
17
18 import (
19 "reflect"
20 "testing"
21
22 corev1 "k8s.io/api/core/v1"
23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24
25 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
26 )
27
28 func Test_convertWorkflow(t *testing.T) {
29 type args struct {
30 kubeWorkflow v1alpha1.Workflow
31 }
32 tests := []struct {
33 name string
34 args args
35 want WorkflowMeta
36 }{
37 {
38 name: "simple workflow",
39 args: args{
40 v1alpha1.Workflow{
41 TypeMeta: metav1.TypeMeta{},
42 ObjectMeta: metav1.ObjectMeta{
43 Namespace: "fake-namespace",
44 Name: "fake-workflow-0",
45 },
46 Spec: v1alpha1.WorkflowSpec{
47 Entry: "an-entry",
48 },
49 Status: v1alpha1.WorkflowStatus{},
50 },
51 },
52 want: WorkflowMeta{
53 Namespace: "fake-namespace",
54 Name: "fake-workflow-0",
55 Entry: "an-entry",
56 Status: WorkflowUnknown,
57 },
58 }, {
59 name: "running workflow",
60 args: args{
61 v1alpha1.Workflow{
62 TypeMeta: metav1.TypeMeta{},
63 ObjectMeta: metav1.ObjectMeta{
64 Namespace: "fake-namespace",
65 Name: "fake-workflow-0",
66 },
67 Spec: v1alpha1.WorkflowSpec{
68 Entry: "an-entry",
69 },
70 Status: v1alpha1.WorkflowStatus{
71 Conditions: []v1alpha1.WorkflowCondition{
72 {
73 Type: v1alpha1.WorkflowConditionScheduled,
74 Status: corev1.ConditionTrue,
75 Reason: "",
76 },
77 },
78 },
79 },
80 },
81 want: WorkflowMeta{
82 Namespace: "fake-namespace",
83 Name: "fake-workflow-0",
84 Entry: "an-entry",
85 Status: WorkflowRunning,
86 },
87 }, {
88 name: "running workflow",
89 args: args{
90 v1alpha1.Workflow{
91 TypeMeta: metav1.TypeMeta{},
92 ObjectMeta: metav1.ObjectMeta{
93 Namespace: "fake-namespace",
94 Name: "fake-workflow-0",
95 },
96 Spec: v1alpha1.WorkflowSpec{
97 Entry: "an-entry",
98 },
99 Status: v1alpha1.WorkflowStatus{
100 Conditions: []v1alpha1.WorkflowCondition{
101 {
102 Type: v1alpha1.WorkflowConditionAccomplished,
103 Status: corev1.ConditionUnknown,
104 Reason: "",
105 },
106 {
107 Type: v1alpha1.WorkflowConditionScheduled,
108 Status: corev1.ConditionTrue,
109 Reason: "",
110 },
111 },
112 },
113 },
114 },
115 want: WorkflowMeta{
116 Namespace: "fake-namespace",
117 Name: "fake-workflow-0",
118 Entry: "an-entry",
119 Status: WorkflowRunning,
120 },
121 }, {
122 name: "running workflow",
123 args: args{
124 v1alpha1.Workflow{
125 TypeMeta: metav1.TypeMeta{},
126 ObjectMeta: metav1.ObjectMeta{
127 Namespace: "fake-namespace",
128 Name: "fake-workflow-0",
129 },
130 Spec: v1alpha1.WorkflowSpec{
131 Entry: "an-entry",
132 },
133 Status: v1alpha1.WorkflowStatus{
134 Conditions: []v1alpha1.WorkflowCondition{
135 {
136 Type: v1alpha1.WorkflowConditionAccomplished,
137 Status: corev1.ConditionFalse,
138 Reason: "",
139 },
140 {
141 Type: v1alpha1.WorkflowConditionScheduled,
142 Status: corev1.ConditionTrue,
143 Reason: "",
144 },
145 },
146 },
147 },
148 },
149 want: WorkflowMeta{
150 Namespace: "fake-namespace",
151 Name: "fake-workflow-0",
152 Entry: "an-entry",
153 Status: WorkflowRunning,
154 },
155 }, {
156 name: "succeed workflow",
157 args: args{
158 v1alpha1.Workflow{
159 TypeMeta: metav1.TypeMeta{},
160 ObjectMeta: metav1.ObjectMeta{
161 Namespace: "fake-namespace",
162 Name: "fake-workflow-0",
163 },
164 Spec: v1alpha1.WorkflowSpec{
165 Entry: "an-entry",
166 },
167 Status: v1alpha1.WorkflowStatus{
168 Conditions: []v1alpha1.WorkflowCondition{
169 {
170 Type: v1alpha1.WorkflowConditionAccomplished,
171 Status: corev1.ConditionTrue,
172 Reason: "",
173 },
174 {
175 Type: v1alpha1.WorkflowConditionScheduled,
176 Status: corev1.ConditionTrue,
177 Reason: "",
178 },
179 },
180 },
181 },
182 },
183 want: WorkflowMeta{
184 Namespace: "fake-namespace",
185 Name: "fake-workflow-0",
186 Entry: "an-entry",
187 Status: WorkflowSucceed,
188 },
189 }, {
190 name: "converting UID",
191 args: args{
192 v1alpha1.Workflow{
193 TypeMeta: metav1.TypeMeta{},
194 ObjectMeta: metav1.ObjectMeta{
195 Namespace: "fake-namespace",
196 Name: "fake-workflow-0",
197 UID: "uid-of-workflow",
198 },
199 Spec: v1alpha1.WorkflowSpec{
200 Entry: "an-entry",
201 },
202 Status: v1alpha1.WorkflowStatus{
203 Conditions: []v1alpha1.WorkflowCondition{
204 {
205 Type: v1alpha1.WorkflowConditionAccomplished,
206 Status: corev1.ConditionTrue,
207 Reason: "",
208 },
209 {
210 Type: v1alpha1.WorkflowConditionScheduled,
211 Status: corev1.ConditionTrue,
212 Reason: "",
213 },
214 },
215 },
216 },
217 },
218 want: WorkflowMeta{
219 Namespace: "fake-namespace",
220 Name: "fake-workflow-0",
221 Entry: "an-entry",
222 Status: WorkflowSucceed,
223 UID: "uid-of-workflow",
224 },
225 },
226 }
227 for _, tt := range tests {
228 t.Run(tt.name, func(t *testing.T) {
229 if got := convertWorkflow(tt.args.kubeWorkflow); !reflect.DeepEqual(got, tt.want) {
230 t.Errorf("convertWorkflow() = %v, want %v", got, tt.want)
231 }
232 })
233 }
234 }
235
236 func Test_convertWorkflowDetail(t *testing.T) {
237 type args struct {
238 kubeWorkflow v1alpha1.Workflow
239 kubeNodes []v1alpha1.WorkflowNode
240 }
241 tests := []struct {
242 name string
243 args args
244 want WorkflowDetail
245 wantErr bool
246 }{
247 {
248 name: "simple workflow detail with no nodes",
249 args: args{
250 kubeWorkflow: v1alpha1.Workflow{
251 TypeMeta: metav1.TypeMeta{},
252 ObjectMeta: metav1.ObjectMeta{
253 Namespace: "another-namespace",
254 Name: "another-fake-workflow",
255 },
256 Spec: v1alpha1.WorkflowSpec{
257 Entry: "another-entry",
258 Templates: nil,
259 },
260 Status: v1alpha1.WorkflowStatus{},
261 },
262 kubeNodes: nil,
263 },
264 want: WorkflowDetail{
265 WorkflowMeta: WorkflowMeta{
266 Namespace: "another-namespace",
267 Name: "another-fake-workflow",
268 Entry: "another-entry",
269 Status: WorkflowUnknown,
270 },
271 Topology: Topology{
272 Nodes: []Node{},
273 },
274 KubeObject: KubeObjectDesc{
275 Meta: KubeObjectMeta{
276 Name: "another-fake-workflow",
277 Namespace: "another-namespace",
278 },
279 Spec: v1alpha1.WorkflowSpec{
280 Entry: "another-entry",
281 },
282 },
283 },
284 },
285
286 }
287 for _, tt := range tests {
288 t.Run(tt.name, func(t *testing.T) {
289 got, err := convertWorkflowDetail(tt.args.kubeWorkflow, tt.args.kubeNodes)
290 if (err != nil) != tt.wantErr {
291 t.Errorf("convertWorkflowDetail() error = %v, wantErr %v", err, tt.wantErr)
292 return
293 }
294 if !reflect.DeepEqual(got, tt.want) {
295 t.Errorf("convertWorkflowDetail() got = %v, want %v", got, tt.want)
296 }
297 })
298 }
299 }
300
301 func Test_convertWorkflowNode(t *testing.T) {
302 type args struct {
303 kubeWorkflowNode v1alpha1.WorkflowNode
304 }
305 tests := []struct {
306 name string
307 args args
308 want Node
309 wantErr bool
310 }{
311 {
312 name: "simple node",
313 args: args{kubeWorkflowNode: v1alpha1.WorkflowNode{
314 TypeMeta: metav1.TypeMeta{},
315 ObjectMeta: metav1.ObjectMeta{
316 Namespace: "fake-namespace",
317 Name: "fake-node-0",
318 },
319 Spec: v1alpha1.WorkflowNodeSpec{
320 WorkflowName: "fake-workflow-0",
321 TemplateName: "fake-template-0",
322 Type: v1alpha1.TypeJVMChaos,
323 },
324 Status: v1alpha1.WorkflowNodeStatus{},
325 }},
326 want: Node{
327 Name: "fake-node-0",
328 Type: ChaosNode,
329 Serial: nil,
330 Parallel: nil,
331 Template: "fake-template-0",
332 State: NodeRunning,
333 },
334 }, {
335 name: "serial node",
336 args: args{
337 kubeWorkflowNode: v1alpha1.WorkflowNode{
338 TypeMeta: metav1.TypeMeta{},
339 ObjectMeta: metav1.ObjectMeta{
340 Namespace: "fake-namespace",
341 Name: "fake-serial-node-0",
342 },
343 Spec: v1alpha1.WorkflowNodeSpec{
344 TemplateName: "fake-serial-node",
345 WorkflowName: "fake-workflow-0",
346 Type: v1alpha1.TypeSerial,
347 Children: []string{"child-0", "child-1"},
348 },
349 Status: v1alpha1.WorkflowNodeStatus{},
350 },
351 },
352 want: Node{
353 Name: "fake-serial-node-0",
354 Type: SerialNode,
355 Serial: []NodeNameWithTemplate{
356 {Name: "", Template: "child-0"},
357 {Name: "", Template: "child-1"},
358 },
359 Parallel: nil,
360 Template: "fake-serial-node",
361 State: NodeRunning,
362 },
363 },
364 {
365 name: "parallel node",
366 args: args{
367 kubeWorkflowNode: v1alpha1.WorkflowNode{
368 TypeMeta: metav1.TypeMeta{},
369 ObjectMeta: metav1.ObjectMeta{
370 Namespace: "fake-namespace",
371 Name: "parallel-node-0",
372 },
373 Spec: v1alpha1.WorkflowNodeSpec{
374 TemplateName: "parallel-node",
375 WorkflowName: "another-fake-workflow",
376 Type: v1alpha1.TypeParallel,
377 Children: []string{"child-1", "child-0"},
378 },
379 Status: v1alpha1.WorkflowNodeStatus{},
380 },
381 },
382 want: Node{
383 Name: "parallel-node-0",
384 Type: ParallelNode,
385 Serial: nil,
386 Parallel: []NodeNameWithTemplate{
387 {Name: "", Template: "child-1"},
388 {Name: "", Template: "child-0"},
389 },
390 Template: "parallel-node",
391 State: NodeRunning,
392 },
393 },
394 {
395 name: "some chaos",
396 args: args{
397 kubeWorkflowNode: v1alpha1.WorkflowNode{
398 TypeMeta: metav1.TypeMeta{},
399 ObjectMeta: metav1.ObjectMeta{
400 Namespace: "fake-namespace",
401 Name: "io-chaos-0",
402 },
403 Spec: v1alpha1.WorkflowNodeSpec{
404 TemplateName: "io-chaos",
405 WorkflowName: "another-workflow-0",
406 Type: v1alpha1.TypeIOChaos,
407 EmbedChaos: &v1alpha1.EmbedChaos{
408 IOChaos: &v1alpha1.IOChaosSpec{
409 ContainerSelector: v1alpha1.ContainerSelector{
410 PodSelector: v1alpha1.PodSelector{
411 Mode: v1alpha1.OneMode,
412 },
413 },
414 Action: "delay",
415 Delay: "100ms",
416 Path: "/fake/path",
417 Percent: 100,
418 VolumePath: "/fake/path",
419 },
420 },
421 },
422 Status: v1alpha1.WorkflowNodeStatus{},
423 },
424 },
425 want: Node{
426 Name: "io-chaos-0",
427 Type: ChaosNode,
428 Serial: nil,
429 Parallel: nil,
430 Template: "io-chaos",
431 State: NodeRunning,
432 },
433 },
434 {
435 name: "accomplished node",
436 args: args{
437 kubeWorkflowNode: v1alpha1.WorkflowNode{
438 TypeMeta: metav1.TypeMeta{},
439 ObjectMeta: metav1.ObjectMeta{
440 Namespace: "fake-namespace",
441 Name: "the-entry-0",
442 },
443 Spec: v1alpha1.WorkflowNodeSpec{
444 TemplateName: "the-entry",
445 WorkflowName: "fake-workflow-0",
446 Type: v1alpha1.TypeSerial,
447 Children: []string{"unimportant-task-0"},
448 },
449 Status: v1alpha1.WorkflowNodeStatus{
450 Conditions: []v1alpha1.WorkflowNodeCondition{
451 {
452 Type: v1alpha1.ConditionAccomplished,
453 Status: corev1.ConditionTrue,
454 Reason: "unit test mocked true",
455 },
456 },
457 },
458 },
459 },
460 want: Node{
461 Name: "the-entry-0",
462 Type: SerialNode,
463 State: NodeSucceed,
464 Serial: []NodeNameWithTemplate{
465 {Name: "", Template: "unimportant-task-0"},
466 },
467 Parallel: nil,
468 Template: "the-entry",
469 },
470 },
471 {
472 name: "deadline exceed node",
473 args: args{kubeWorkflowNode: v1alpha1.WorkflowNode{
474 TypeMeta: metav1.TypeMeta{},
475 ObjectMeta: metav1.ObjectMeta{
476 Namespace: "fake-namespace",
477 Name: "deadline-exceed-node-0",
478 },
479 Spec: v1alpha1.WorkflowNodeSpec{
480 TemplateName: "deadline-exceed-node",
481 WorkflowName: "some-workflow",
482 Type: v1alpha1.TypePodChaos,
483 },
484 Status: v1alpha1.WorkflowNodeStatus{
485 Conditions: []v1alpha1.WorkflowNodeCondition{
486 {
487 Type: v1alpha1.ConditionDeadlineExceed,
488 Status: corev1.ConditionTrue,
489 Reason: "unit test mocked true",
490 },
491 },
492 },
493 }},
494 want: Node{
495 Name: "deadline-exceed-node-0",
496 Type: ChaosNode,
497 State: NodeSucceed,
498 Serial: nil,
499 Parallel: nil,
500 Template: "deadline-exceed-node",
501 },
502 },
503 {
504 name: "appending uid",
505 args: args{
506 kubeWorkflowNode: v1alpha1.WorkflowNode{
507 TypeMeta: metav1.TypeMeta{},
508 ObjectMeta: metav1.ObjectMeta{
509 Namespace: "fake-namespace",
510 Name: "the-entry-0",
511 UID: "uid-of-workflow-node",
512 },
513 Spec: v1alpha1.WorkflowNodeSpec{
514 TemplateName: "the-entry",
515 WorkflowName: "fake-workflow-0",
516 Type: v1alpha1.TypeSerial,
517 Children: []string{"unimportant-task-0"},
518 },
519 Status: v1alpha1.WorkflowNodeStatus{
520 Conditions: []v1alpha1.WorkflowNodeCondition{
521 {
522 Type: v1alpha1.ConditionAccomplished,
523 Status: corev1.ConditionTrue,
524 Reason: "unit test mocked true",
525 },
526 },
527 },
528 },
529 },
530 want: Node{
531 Name: "the-entry-0",
532 Type: SerialNode,
533 State: NodeSucceed,
534 Serial: []NodeNameWithTemplate{
535 {Name: "", Template: "unimportant-task-0"},
536 },
537 Parallel: nil,
538 Template: "the-entry",
539 UID: "uid-of-workflow-node",
540 },
541 },
542 {
543 name: "task node",
544 args: args{
545 kubeWorkflowNode: v1alpha1.WorkflowNode{
546 ObjectMeta: metav1.ObjectMeta{
547 Name: "mocking-task-node-0",
548 Namespace: "mocked-namespace",
549 },
550 Spec: v1alpha1.WorkflowNodeSpec{
551 TemplateName: "mocking-task-node",
552 WorkflowName: "fake-workflow-0",
553 Type: v1alpha1.TypeTask,
554 ConditionalBranches: []v1alpha1.ConditionalBranch{
555 {
556 Target: "one-node",
557 Expression: "exitCode == 0",
558 },
559 {
560 Target: "another-node",
561 Expression: "exitCode != 0",
562 },
563 },
564 },
565 Status: v1alpha1.WorkflowNodeStatus{
566 ConditionalBranchesStatus: &v1alpha1.ConditionalBranchesStatus{
567 Branches: []v1alpha1.ConditionalBranchStatus{
568 {
569 Target: "one-node",
570 EvaluationResult: corev1.ConditionFalse,
571 },
572 {
573 Target: "another-node",
574 EvaluationResult: corev1.ConditionTrue,
575 },
576 },
577 Context: nil,
578 },
579 ActiveChildren: []corev1.LocalObjectReference{
580 {
581 Name: "another-node-0",
582 },
583 },
584 },
585 },
586 },
587 want: Node{
588 Name: "mocking-task-node-0",
589 Type: TaskNode,
590 State: NodeRunning,
591 ConditionalBranches: []ConditionalBranch{
592 {
593 NodeNameWithTemplate: NodeNameWithTemplate{
594 Template: "one-node",
595 Name: "",
596 },
597 Expression: "exitCode == 0",
598 },
599 {
600 NodeNameWithTemplate: NodeNameWithTemplate{
601 Template: "another-node",
602 Name: "another-node-0",
603 },
604 Expression: "exitCode != 0",
605 },
606 },
607 Template: "mocking-task-node",
608 },
609 wantErr: false,
610 },
611 }
612 for _, tt := range tests {
613 t.Run(tt.name, func(t *testing.T) {
614 got, err := convertWorkflowNode(tt.args.kubeWorkflowNode)
615 if (err != nil) != tt.wantErr {
616 t.Errorf("convertWorkflowNode() error = %v, wantErr %v", err, tt.wantErr)
617 return
618 }
619 if !reflect.DeepEqual(got, tt.want) {
620 t.Errorf("convertWorkflowNode() got = %v, want %v", got, tt.want)
621 }
622 })
623 }
624 }
625
626 func Test_composeTaskAndNodes(t *testing.T) {
627 type args struct {
628 children []string
629 nodes []string
630 }
631 tests := []struct {
632 name string
633 args args
634 want []NodeNameWithTemplate
635 }{
636 {
637 name: "ordered with serial",
638 args: args{
639 children: []string{"node-0", "node-1", "node-0", "node-2", "node-3"},
640 nodes: []string{"node-0-instance", "node-1-instance", "node-0-another_instance"},
641 },
642 want: []NodeNameWithTemplate{
643 {
644 Name: "node-0-instance",
645 Template: "node-0",
646 }, {
647 Name: "node-1-instance",
648 Template: "node-1",
649 }, {
650 Name: "node-0-another_instance",
651 Template: "node-0",
652 }, {
653 Name: "",
654 Template: "node-2",
655 }, {
656 Name: "",
657 Template: "node-3",
658 },
659 },
660 },
661 }
662 for _, tt := range tests {
663 t.Run(tt.name, func(t *testing.T) {
664 if got := composeSerialTaskAndNodes(tt.args.children, tt.args.nodes); !reflect.DeepEqual(got, tt.want) {
665 t.Errorf("composeSerialTaskAndNodes() = %v, want %v", got, tt.want)
666 }
667 })
668 }
669 }
670
671 func Test_composeParallelTaskAndNodes(t *testing.T) {
672 type args struct {
673 children []string
674 nodes []string
675 }
676 tests := []struct {
677 name string
678 args args
679 want []NodeNameWithTemplate
680 }{
681 {
682 name: "parallel",
683 args: args{
684 children: []string{"node-a", "node-b", "node-a", "node-c", "node-d"},
685 nodes: []string{"node-a-instance", "node-a-another_instance", "node-d-instance"},
686 },
687 want: []NodeNameWithTemplate{
688 {
689 Name: "node-a-instance",
690 Template: "node-a",
691 }, {
692 Name: "",
693 Template: "node-b",
694 }, {
695 Name: "node-a-another_instance",
696 Template: "node-a",
697 }, {
698 Name: "",
699 Template: "node-c",
700 }, {
701 Name: "node-d-instance",
702 Template: "node-d",
703 },
704 },
705 },
706 }
707 for _, tt := range tests {
708 t.Run(tt.name, func(t *testing.T) {
709 if got := composeParallelTaskAndNodes(tt.args.children, tt.args.nodes); !reflect.DeepEqual(got, tt.want) {
710 t.Errorf("composeParallelTaskAndNodes() = %v, want %v", got, tt.want)
711 }
712 })
713 }
714 }
715
716 func Test_composeTaskConditionalBranches(t *testing.T) {
717 type args struct {
718 conditionalBranches []v1alpha1.ConditionalBranch
719 nodes []string
720 }
721 tests := []struct {
722 name string
723 args args
724 want []ConditionalBranch
725 }{
726 {
727 name: "task node all of the branch is selected",
728 args: args{
729 conditionalBranches: []v1alpha1.ConditionalBranch{
730 {
731 Target: "template-a",
732 Expression: "a: whatever valid or not",
733 },
734 {
735 Target: "template-b",
736 Expression: "b: whatever valid or not",
737 },
738 {
739 Target: "template-c",
740 Expression: "c: whatever valid or not",
741 },
742 },
743 nodes: []string{
744 "template-a-0",
745 "template-b-0",
746 "template-c-0",
747 },
748 },
749 want: []ConditionalBranch{
750 {
751 NodeNameWithTemplate: NodeNameWithTemplate{
752 Name: "template-a-0",
753 Template: "template-a",
754 },
755 Expression: "a: whatever valid or not",
756 },
757 {
758 NodeNameWithTemplate: NodeNameWithTemplate{
759 Name: "template-b-0",
760 Template: "template-b",
761 },
762 Expression: "b: whatever valid or not",
763 },
764 {
765 NodeNameWithTemplate: NodeNameWithTemplate{
766 Name: "template-c-0",
767 Template: "template-c",
768 },
769 Expression: "c: whatever valid or not",
770 },
771 },
772 },
773 {
774 name: "none of the branch is selected",
775 args: args{
776 conditionalBranches: []v1alpha1.ConditionalBranch{
777 {
778 Target: "template-a",
779 Expression: "a: whatever valid or not",
780 },
781 {
782 Target: "template-b",
783 Expression: "b: whatever valid or not",
784 },
785 {
786 Target: "template-c",
787 Expression: "c: whatever valid or not",
788 },
789 },
790 nodes: []string{},
791 },
792 want: []ConditionalBranch{
793 {
794 NodeNameWithTemplate: NodeNameWithTemplate{
795 Name: "",
796 Template: "template-a",
797 },
798 Expression: "a: whatever valid or not",
799 },
800 {
801 NodeNameWithTemplate: NodeNameWithTemplate{
802 Name: "",
803 Template: "template-b",
804 },
805 Expression: "b: whatever valid or not",
806 },
807 {
808 NodeNameWithTemplate: NodeNameWithTemplate{
809 Name: "",
810 Template: "template-c",
811 },
812 Expression: "c: whatever valid or not",
813 },
814 },
815 },
816 {
817 name: "part of the branch is selected",
818 args: args{
819 conditionalBranches: []v1alpha1.ConditionalBranch{
820 {
821 Target: "template-a",
822 Expression: "a: whatever valid or not",
823 },
824 {
825 Target: "template-b",
826 Expression: "b: whatever valid or not",
827 },
828 {
829 Target: "template-c",
830 Expression: "c: whatever valid or not",
831 },
832 },
833 nodes: []string{
834 "template-a-0",
835 },
836 },
837 want: []ConditionalBranch{
838 {
839 NodeNameWithTemplate: NodeNameWithTemplate{
840 Name: "template-a-0",
841 Template: "template-a",
842 },
843 Expression: "a: whatever valid or not",
844 },
845 {
846 NodeNameWithTemplate: NodeNameWithTemplate{
847 Name: "",
848 Template: "template-b",
849 },
850 Expression: "b: whatever valid or not",
851 },
852 {
853 NodeNameWithTemplate: NodeNameWithTemplate{
854 Name: "",
855 Template: "template-c",
856 },
857 Expression: "c: whatever valid or not",
858 },
859 },
860 },
861 }
862 for _, tt := range tests {
863 t.Run(tt.name, func(t *testing.T) {
864 if got := composeTaskConditionalBranches(tt.args.conditionalBranches, tt.args.nodes); !reflect.DeepEqual(got, tt.want) {
865 t.Errorf("composeTaskConditionalBranches() = %v, want %v", got, tt.want)
866 }
867 })
868 }
869 }
870