github.com/go-maxhub/gremlins@v1.0.1-0.20231227222204-b03a6a1e3e09/core/engine/workerpool/workerpool_test.go (about) 1 /* 2 * Copyright 2022 The Gremlins Authors 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 workerpool_test 18 19 import ( 20 "go/token" 21 "runtime" 22 "testing" 23 24 "github.com/go-maxhub/gremlins/core/configuration" 25 "github.com/go-maxhub/gremlins/core/engine/workerpool" 26 "github.com/go-maxhub/gremlins/core/mutator" 27 ) 28 29 type ExecutorMock struct { 30 mutant mutator.Mutator 31 outCh chan<- mutator.Mutator 32 } 33 34 func (tj *ExecutorMock) Start(w *workerpool.Worker) { 35 fm := fakeMutant{ 36 name: w.Name, 37 id: w.ID, 38 } 39 tj.outCh <- fm 40 } 41 42 func TestWorker(t *testing.T) { 43 executorQueue := make(chan workerpool.Executor) 44 outCh := make(chan mutator.Mutator) 45 46 worker := workerpool.NewWorker(1, "test") 47 worker.Start(executorQueue) 48 49 tj := &ExecutorMock{ 50 mutant: &fakeMutant{}, 51 outCh: outCh, 52 } 53 54 executorQueue <- tj 55 close(executorQueue) 56 57 m := <-outCh 58 got, ok := m.(fakeMutant) 59 if !ok { 60 t.Fatal("it should be a fakeMutant") 61 } 62 63 if got.name != "test" { 64 t.Errorf("want %q, got %q", "test", got.name) 65 } 66 if got.id != 1 { 67 t.Errorf("want %d, got %d", 1, got.id) 68 } 69 } 70 71 func TestPool(t *testing.T) { 72 t.Run("test executes work", func(t *testing.T) { 73 configuration.Set(configuration.UnleashWorkersKey, 1) 74 defer configuration.Reset() 75 76 outCh := make(chan mutator.Mutator) 77 78 pool := workerpool.Initialize("test") 79 pool.Start() 80 defer pool.Stop() 81 82 tj := &ExecutorMock{ 83 mutant: &fakeMutant{}, 84 outCh: outCh, 85 } 86 87 pool.AppendExecutor(tj) 88 89 m := <-outCh 90 got, ok := m.(fakeMutant) 91 if !ok { 92 t.Fatal("it should be a fakeMutant") 93 } 94 95 if got.name != "test" { 96 t.Errorf("want %q, got %q", "test", got.name) 97 } 98 if got.id != 0 { 99 t.Errorf("want %d, got %d", 0, got.id) 100 } 101 }) 102 103 t.Run("default uses runtime CPUs as number of workers", func(t *testing.T) { 104 configuration.Set(configuration.UnleashWorkersKey, 0) 105 defer configuration.Reset() 106 107 pool := workerpool.Initialize("test") 108 pool.Start() 109 defer pool.Stop() 110 111 if pool.ActiveWorkers() != runtime.NumCPU() { 112 t.Errorf("want %d, got %d", runtime.NumCPU(), pool.ActiveWorkers()) 113 } 114 }) 115 116 t.Run("default uses half of runtime CPUs as number of workers in integration mode", func(t *testing.T) { 117 configuration.Set(configuration.UnleashWorkersKey, 0) 118 configuration.Set(configuration.UnleashIntegrationMode, true) 119 defer configuration.Reset() 120 121 pool := workerpool.Initialize("test") 122 pool.Start() 123 defer pool.Stop() 124 125 if pool.ActiveWorkers() != runtime.NumCPU()/2 { 126 t.Errorf("want %d, got %d", runtime.NumCPU()/2, pool.ActiveWorkers()) 127 } 128 }) 129 130 t.Run("can override CPUs", func(t *testing.T) { 131 configuration.Set(configuration.UnleashWorkersKey, 3) 132 defer configuration.Reset() 133 134 pool := workerpool.Initialize("test") 135 pool.Start() 136 defer pool.Stop() 137 138 if pool.ActiveWorkers() != 3 { 139 t.Errorf("want %d, got %d", 3, pool.ActiveWorkers()) 140 } 141 }) 142 143 t.Run("in integration mode, overrides CPUs by half", func(t *testing.T) { 144 configuration.Set(configuration.UnleashWorkersKey, 2) 145 configuration.Set(configuration.UnleashIntegrationMode, true) 146 defer configuration.Reset() 147 148 pool := workerpool.Initialize("test") 149 pool.Start() 150 defer pool.Stop() 151 152 if pool.ActiveWorkers() != 1 { 153 t.Errorf("want %d, got %d", 1, pool.ActiveWorkers()) 154 } 155 }) 156 } 157 158 type fakeMutant struct { 159 name string 160 id int 161 } 162 163 func (fakeMutant) Type() mutator.Type { 164 panic("not used in test") 165 } 166 167 func (fakeMutant) SetType(_ mutator.Type) { 168 panic("not used in test") 169 } 170 171 func (fakeMutant) Status() mutator.Status { 172 panic("not used in test") 173 } 174 175 func (fakeMutant) SetStatus(_ mutator.Status) { 176 panic("not used in test") 177 } 178 179 func (fakeMutant) Position() token.Position { 180 panic("not used in test") 181 } 182 183 func (fakeMutant) Pos() token.Pos { 184 panic("not used in test") 185 } 186 187 func (fakeMutant) Pkg() string { 188 panic("not used in test") 189 } 190 191 func (fakeMutant) SetWorkdir(_ string) { 192 panic("not used in test") 193 } 194 195 func (fakeMutant) Workdir() string { 196 panic("not used in test") 197 } 198 199 func (fakeMutant) Apply() error { 200 panic("not used in test") 201 } 202 203 func (fakeMutant) Rollback() error { 204 panic("not used in test") 205 }