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