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  }