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  }