...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/workflow/controllers/parallel_node_reconciler_test.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/workflow/controllers

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package controllers
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"reflect"
    22  	"sort"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	. "github.com/onsi/ginkgo/v2"
    28  	. "github.com/onsi/gomega"
    29  	corev1 "k8s.io/api/core/v1"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/types"
    32  	"sigs.k8s.io/controller-runtime/pkg/client"
    33  
    34  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    35  )
    36  
    37  // unit tests
    38  func Test_getTaskNameFromGeneratedName(t *testing.T) {
    39  	type args struct {
    40  		generatedNodeName string
    41  	}
    42  	tests := []struct {
    43  		name string
    44  		args args
    45  		want string
    46  	}{
    47  		{
    48  			"common case",
    49  			args{"name-1"},
    50  			"name",
    51  		}, {
    52  			"common case",
    53  			args{"name-1-2"},
    54  			"name-1",
    55  		}, {
    56  			"common case",
    57  			args{"name"},
    58  			"name",
    59  		}, {
    60  			"common case",
    61  			args{"name-"},
    62  			"name",
    63  		},
    64  		{
    65  			"common case",
    66  			args{"-name"},
    67  			"",
    68  		},
    69  	}
    70  	for _, tt := range tests {
    71  		t.Run(tt.name, func(t *testing.T) {
    72  			if got := getTaskNameFromGeneratedName(tt.args.generatedNodeName); got != tt.want {
    73  				t.Errorf("getTaskNameFromGeneratedName() = %v, want %v", got, tt.want)
    74  			}
    75  		})
    76  	}
    77  }
    78  
    79  func Test_relativeComplementSet(t *testing.T) {
    80  	type args struct {
    81  		former []string
    82  		latter []string
    83  	}
    84  	tests := []struct {
    85  		name string
    86  		args args
    87  		want []string
    88  	}{
    89  		{
    90  			name: "common_case",
    91  			args: args{
    92  				former: []string{"a", "b", "c"},
    93  				latter: []string{},
    94  			},
    95  			want: []string{"a", "b", "c"},
    96  		}, {
    97  			name: "common_case",
    98  			args: args{
    99  				former: []string{"a", "b", "c"},
   100  				latter: []string{"b", "c"},
   101  			},
   102  			want: []string{"a"},
   103  		}, {
   104  			name: "common_case",
   105  			args: args{
   106  				former: []string{"a", "b", "c"},
   107  				latter: []string{"c", "a"},
   108  			},
   109  			want: []string{"b"},
   110  		}, {
   111  			name: "common_case",
   112  			args: args{
   113  				former: []string{"a", "b", "c"},
   114  				latter: []string{"c", "b", "d"},
   115  			},
   116  			want: []string{"a"},
   117  		},
   118  	}
   119  	for _, test := range tests {
   120  		t.Run(test.name, func(t *testing.T) {
   121  			got := setDifference(test.args.former, test.args.latter)
   122  			sort.Strings(got)
   123  			sort.Strings(test.want)
   124  			if !reflect.DeepEqual(got, test.want) {
   125  				t.Errorf("getTaskNameFromGeneratedName() = %v, want %v", got, test.want)
   126  			}
   127  		})
   128  	}
   129  }
   130  
   131  // integration tests
   132  var _ = Describe("Workflow", func() {
   133  	var ns string
   134  	BeforeEach(func() {
   135  		ctx := context.TODO()
   136  		newNs := corev1.Namespace{
   137  			ObjectMeta: metav1.ObjectMeta{
   138  				GenerateName: "chaos-mesh-",
   139  			},
   140  			Spec: corev1.NamespaceSpec{},
   141  		}
   142  		Expect(kubeClient.Create(ctx, &newNs)).To(Succeed())
   143  		ns = newNs.Name
   144  		By(fmt.Sprintf("create new namespace %s", ns))
   145  	})
   146  
   147  	AfterEach(func() {
   148  		ctx := context.TODO()
   149  		nsToDelete := corev1.Namespace{}
   150  		Expect(kubeClient.Get(ctx, types.NamespacedName{Name: ns}, &nsToDelete)).To(Succeed())
   151  		Expect(kubeClient.Delete(ctx, &nsToDelete)).To(Succeed())
   152  		By(fmt.Sprintf("cleanup namespace %s", ns))
   153  	})
   154  
   155  	Context("with one parallel node", func() {
   156  		Context("with one simple parallel node", func() {
   157  
   158  			It("should spawn all the children at the same time", func() {
   159  				By("create simple workflow")
   160  				ctx := context.TODO()
   161  				simpleParallelWorkflow := v1alpha1.Workflow{
   162  					ObjectMeta: metav1.ObjectMeta{
   163  						Name:      "simple-parallel",
   164  						Namespace: ns,
   165  					},
   166  					Spec: v1alpha1.WorkflowSpec{
   167  						Entry: "parallel",
   168  						Templates: []v1alpha1.Template{
   169  							{
   170  								Name: "parallel",
   171  								Type: v1alpha1.TypeParallel,
   172  								Children: []string{
   173  									"network-chaos",
   174  									"pod-chaos",
   175  									"stress-chaos",
   176  								},
   177  							}, {
   178  								Name: "network-chaos",
   179  								Type: v1alpha1.TypeNetworkChaos,
   180  								EmbedChaos: &v1alpha1.EmbedChaos{
   181  									NetworkChaos: &v1alpha1.NetworkChaosSpec{
   182  										PodSelector: v1alpha1.PodSelector{
   183  											Selector: v1alpha1.PodSelectorSpec{
   184  												GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
   185  													Namespaces: []string{ns},
   186  													LabelSelectors: map[string]string{
   187  														"app": "not-exist",
   188  													},
   189  												},
   190  											},
   191  											Mode: v1alpha1.AllMode,
   192  										},
   193  										Action: v1alpha1.PartitionAction,
   194  									},
   195  								},
   196  							}, {
   197  								Name: "pod-chaos",
   198  								Type: v1alpha1.TypePodChaos,
   199  								EmbedChaos: &v1alpha1.EmbedChaos{
   200  									PodChaos: &v1alpha1.PodChaosSpec{
   201  										ContainerSelector: v1alpha1.ContainerSelector{
   202  											PodSelector: v1alpha1.PodSelector{
   203  												Selector: v1alpha1.PodSelectorSpec{
   204  													GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
   205  														Namespaces: []string{ns},
   206  														LabelSelectors: map[string]string{
   207  															"app": "not-exist",
   208  														},
   209  													},
   210  												},
   211  												Mode: v1alpha1.AllMode,
   212  											},
   213  										},
   214  										Action: v1alpha1.PodKillAction,
   215  									},
   216  								},
   217  							},
   218  							{
   219  								Name: "stress-chaos",
   220  								Type: v1alpha1.TypeStressChaos,
   221  								EmbedChaos: &v1alpha1.EmbedChaos{
   222  									StressChaos: &v1alpha1.StressChaosSpec{
   223  										ContainerSelector: v1alpha1.ContainerSelector{
   224  											PodSelector: v1alpha1.PodSelector{
   225  												Selector: v1alpha1.PodSelectorSpec{
   226  													GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
   227  														Namespaces: []string{ns},
   228  														LabelSelectors: map[string]string{
   229  															"app": "not-exist",
   230  														},
   231  													},
   232  												},
   233  												Mode: v1alpha1.AllMode,
   234  											},
   235  										},
   236  										Stressors: &v1alpha1.Stressors{
   237  											CPUStressor: &v1alpha1.CPUStressor{
   238  												Stressor: v1alpha1.Stressor{
   239  													Workers: 2,
   240  												},
   241  											}},
   242  									},
   243  								},
   244  							},
   245  						},
   246  					}}
   247  				Expect(kubeClient.Create(ctx, &simpleParallelWorkflow)).To(Succeed())
   248  
   249  				By("assert that all resource has been created")
   250  
   251  				By("assert that 1 entry node and 3 chaos nodes created")
   252  				Eventually(func() int {
   253  					workflowNodeList := v1alpha1.WorkflowNodeList{}
   254  					Expect(kubeClient.List(ctx, &workflowNodeList, &client.ListOptions{Namespace: ns})).To(Succeed())
   255  					return len(workflowNodeList.Items)
   256  				}, 10*time.Second, time.Second).Should(Equal(4))
   257  
   258  				By("assert that network chaos has been created")
   259  				Eventually(func() bool {
   260  					chaosList := v1alpha1.NetworkChaosList{}
   261  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   262  					if len(chaosList.Items) != 1 {
   263  						return false
   264  					}
   265  					return strings.HasPrefix(chaosList.Items[0].Name, "network-chaos")
   266  				}, 10*time.Second, time.Second).Should(BeTrue())
   267  
   268  				By("assert that pod chaos has been created")
   269  				Eventually(func() bool {
   270  					chaosList := v1alpha1.PodChaosList{}
   271  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   272  					if len(chaosList.Items) != 1 {
   273  						return false
   274  					}
   275  					return strings.HasPrefix(chaosList.Items[0].Name, "pod-chaos")
   276  				}, 10*time.Second, time.Second).Should(BeTrue())
   277  
   278  				By("assert that stress chaos has been created")
   279  				Eventually(func() bool {
   280  					chaosList := v1alpha1.StressChaosList{}
   281  					Expect(kubeClient.List(ctx, &chaosList, &client.ListOptions{Namespace: ns})).To(Succeed())
   282  					if len(chaosList.Items) != 1 {
   283  						return false
   284  					}
   285  					return strings.HasPrefix(chaosList.Items[0].Name, "stress-chaos")
   286  				}, 10*time.Second, time.Second).Should(BeTrue())
   287  			})
   288  		})
   289  	})
   290  })
   291