github.com/splunk/dan1-qbec@v0.7.3/internal/commands/common_test.go (about) 1 /* 2 Copyright 2019 Splunk Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package commands 18 19 import ( 20 "bytes" 21 "fmt" 22 "sync" 23 "testing" 24 25 "github.com/pkg/errors" 26 "github.com/splunk/qbec/internal/model" 27 "github.com/stretchr/testify/assert" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestRunInParallelNoObjects(t *testing.T) { 32 err := runInParallel([]model.K8sLocalObject{}, func(o model.K8sLocalObject) error { return nil }, 5) 33 require.Nil(t, err) 34 } 35 36 type input struct { 37 component string 38 env string 39 namespace string 40 name string 41 } 42 43 func (i input) makeObject() model.K8sLocalObject { 44 data := map[string]interface{}{ 45 "apiVersion": "v1", 46 "kind": "ConfigMap", 47 "metadata": map[string]interface{}{ 48 "namespace": i.namespace, 49 "name": i.name, 50 }, 51 "data": map[string]interface{}{ 52 "foo": "bar", 53 }, 54 } 55 return model.NewK8sLocalObject(data, "app1", "t1", i.component, i.env) 56 } 57 58 func (i input) String() string { 59 return fmt.Sprintf("%s:%s:%s:%s", i.component, i.env, i.namespace, i.name) 60 } 61 62 func TestRunInParallel(t *testing.T) { 63 var l sync.Mutex 64 seen := map[string]bool{} 65 setSeen := func(s string) { 66 l.Lock() 67 defer l.Unlock() 68 seen[s] = true 69 } 70 worker := func(o model.K8sLocalObject) error { 71 str := fmt.Sprintf("%s:%s:%s:%s", o.Component(), o.Environment(), o.GetNamespace(), o.GetName()) 72 setSeen(str) 73 return nil 74 } 75 inputs := []input{ 76 {component: "c1", env: "dev", namespace: "default", name: "c1"}, 77 {component: "c1", env: "dev", namespace: "default", name: "c2"}, 78 {component: "c1", env: "dev", namespace: "default", name: "c3"}, 79 {component: "c1", env: "dev", namespace: "default", name: "c4"}, 80 {component: "c2", env: "dev", namespace: "kube-system", name: "k1"}, 81 {component: "c2", env: "dev", namespace: "kube-system", name: "k2"}, 82 {component: "c2", env: "dev", namespace: "kube-system", name: "k3"}, 83 {component: "c3", env: "dev", namespace: "kube-public", name: "p1"}, 84 {component: "c3", env: "dev", namespace: "kube-public", name: "p2"}, 85 {component: "c3", env: "dev", namespace: "kube-public", name: "p3"}, 86 } 87 var objs []model.K8sLocalObject 88 for _, in := range inputs { 89 objs = append(objs, in.makeObject()) 90 } 91 92 err := runInParallel(objs, worker, 5) 93 require.Nil(t, err) 94 a := assert.New(t) 95 for _, in := range inputs { 96 a.Contains(seen, in.String()) 97 } 98 99 seen = map[string]bool{} 100 worker = func(o model.K8sLocalObject) error { 101 str := fmt.Sprintf("%s:%s:%s:%s", o.Component(), o.Environment(), o.GetNamespace(), o.GetName()) 102 setSeen(str) 103 if o.GetNamespace() == "kube-system" { 104 return errors.New("kserr") 105 } 106 return nil 107 } 108 109 err = runInParallel(objs, worker, 0) 110 require.NotNil(t, err) 111 a.True(len(seen) < len(inputs)) 112 a.Contains(err.Error(), "/v1, Kind=ConfigMap:kube-system:k1: kserr") 113 } 114 115 func TestUsageError(t *testing.T) { 116 ue := newUsageError("foobar") 117 a := assert.New(t) 118 a.True(isUsageError(ue)) 119 a.Equal("foobar", ue.Error()) 120 } 121 122 func TestRuntimeError(t *testing.T) { 123 re := NewRuntimeError(errors.New("foobar")) 124 a := assert.New(t) 125 a.True(IsRuntimeError(re)) 126 a.False(isUsageError(re)) 127 a.Equal("foobar", re.Error()) 128 } 129 130 func TestWrapError(t *testing.T) { 131 ue := newUsageError("foobar") 132 a := assert.New(t) 133 a.Nil(wrapError(nil)) 134 a.True(isUsageError(wrapError(ue))) 135 a.True(IsRuntimeError(wrapError(errors.New("foobar")))) 136 } 137 138 func TestStats(t *testing.T) { 139 data := map[string]int{ 140 "processed": 10, 141 "success": 9, 142 "failure": 1, 143 } 144 var buf bytes.Buffer 145 printStats(&buf, data) 146 expected := `--- 147 stats: 148 failure: 1 149 processed: 10 150 success: 9 151 152 ` 153 assert.Equal(t, expected, buf.String()) 154 }