github.com/yanishoss/schedulo@v1.2.2/internal/core/stack_manager_test.go (about)

     1  package core
     2  
     3  import (
     4  	"math/rand"
     5  	"testing"
     6  	"time"
     7  )
     8  
     9  var config = StackManagerConfig{
    10  	StacksNumber:         20000,
    11  	DefaultStackCapacity: 50,
    12  	MaxStackCapacity:     100,
    13  }
    14  
    15  var ev = generateEvents(2 * config.StacksNumber * config.DefaultStackCapacity)
    16  
    17  func TestStackManager(t *testing.T) {
    18  	var config = StackManagerConfig{
    19  		StacksNumber:         5,
    20  		DefaultStackCapacity: 300,
    21  	}
    22  
    23  	s := newStackManager(config)
    24  
    25  	if len(s.stacks) != config.StacksNumber {
    26  		t.Fatalf("The stack manager doesn't have enough stacks: expect %d, got %d\n", config.StacksNumber, s.stacks.Len())
    27  	}
    28  
    29  	if s.stacks[0].cap < config.DefaultStackCapacity {
    30  		t.Fatalf("The stack manager doesn't have enough stack capacity: expect %d, got %d\n", config.DefaultStackCapacity, s.stacks[0].len)
    31  	}
    32  
    33  	ev := generateEvents(config.DefaultStackCapacity*config.StacksNumber + 10)
    34  
    35  	for i, e := range ev {
    36  		if i == config.DefaultStackCapacity*config.StacksNumber-1 {
    37  			break
    38  		}
    39  
    40  		_ = s.Push(e)
    41  	}
    42  
    43  	for i := 0; i < s.stacks[0].len; i++ {
    44  		ev := s.stacks[0].Get(i)
    45  
    46  		if i-1 >= 0 {
    47  			evBefore := s.stacks[0].Get(i - 1)
    48  
    49  			if ev.ShouldExecuteAt.Before(evBefore.ShouldExecuteAt) {
    50  				t.Fatalf("The stack must be sorted timestamp ascending wise\n")
    51  			}
    52  		}
    53  
    54  		if i+1 <= s.stacks[0].len-1 {
    55  			evAfter := s.stacks[0].Get(i + 1)
    56  
    57  			if ev.ShouldExecuteAt.After(evAfter.ShouldExecuteAt) {
    58  				t.Fatalf("The stack must be sorted timestamp ascending wise\n")
    59  			}
    60  		}
    61  	}
    62  
    63  	for i, e := range ev[config.DefaultStackCapacity*config.StacksNumber-1:] {
    64  		if i == config.DefaultStackCapacity*config.StacksNumber-1 {
    65  			break
    66  		}
    67  
    68  		_ = s.Push(e)
    69  	}
    70  
    71  	if s.stacks[0].cap <= config.DefaultStackCapacity {
    72  		t.Fatalf("The stack capacity must be expanded as new events have been pushed: %d capacity\n", s.stacks[0].cap)
    73  	}
    74  
    75  	if err := s.resize(7); err != nil {
    76  		t.Error(err)
    77  	}
    78  
    79  	if len(s.stacks) != 7 {
    80  		t.Fatalf("The number of stack must be resized: expect:%d, got:%d\n", 7, len(s.stacks))
    81  	}
    82  
    83  	oldLen := s.Len()
    84  
    85  	if err := s.resize(2); err != nil {
    86  		t.Error(err)
    87  	}
    88  
    89  	if s.stacks.Len() != 2 {
    90  		t.Fatalf("The stack manager has not been resized: expected:%d, got:%d", 2, s.stacks.Len())
    91  	}
    92  
    93  	if s.Len() != oldLen {
    94  		t.Fatalf("Elements have been lost while resizing the stack manager: expected:%d, got:%d\n", oldLen, s.Len())
    95  	}
    96  
    97  	ev = generateEvents(2*maxDefaultStackCapacity - len(ev) + 1)
    98  
    99  	var err1 error
   100  	for _, e := range ev {
   101  		err := s.Push(e)
   102  
   103  		if err != nil {
   104  			err1 = err
   105  		}
   106  	}
   107  
   108  	if err1 == nil {
   109  		t.Fatalf("Max capacity has been reached but no error was raised\n")
   110  	} else {
   111  		t.Logf("This error code is normal: %s\n", err1.Error())
   112  	}
   113  
   114  	if err := s.resize(1); err == nil {
   115  		t.Fatalf("Max capacity has already been reached but no error was raised\n")
   116  	}
   117  }
   118  
   119  func BenchmarkInsertingBelowCapacity(b *testing.B) {
   120  	b.StopTimer()
   121  	s := newStackManager(config)
   122  
   123  	smpl := ev[:config.DefaultStackCapacity*config.StacksNumber]
   124  
   125  	b.StartTimer()
   126  	for _, e := range smpl {
   127  		err := s.Push(e)
   128  
   129  		if err != nil {
   130  			b.Error(err)
   131  		}
   132  	}
   133  }
   134  
   135  func BenchmarkInsertingPastCapacity(b *testing.B) {
   136  	b.StopTimer()
   137  	s := newStackManager(config)
   138  
   139  	smpl := ev[:config.StacksNumber*config.DefaultStackCapacity-1]
   140  
   141  	for _, e := range smpl {
   142  		err := s.Push(e)
   143  
   144  		if err != nil {
   145  			b.Error(err)
   146  		}
   147  	}
   148  
   149  	smpl2 := ev[config.StacksNumber*config.DefaultStackCapacity:]
   150  
   151  	b.StartTimer()
   152  	for _, e := range smpl2 {
   153  		err := s.Push(e)
   154  
   155  		if err != nil {
   156  			b.Error(err)
   157  		}
   158  	}
   159  }
   160  
   161  func randomID(n int) ID {
   162  	const CHARACTERS = "AZERTYUIOPQSDFGHJKLMWXCVBN1234567890"
   163  
   164  	str := ""
   165  
   166  	for i := 0; i < n; i++ {
   167  		j := rand.Intn(len(CHARACTERS) - 1)
   168  
   169  		str += string(CHARACTERS[j])
   170  	}
   171  
   172  	return ID(str)
   173  }
   174  
   175  func generateEvents(n int) []event {
   176  	const idSize = 8
   177  
   178  	ev := make([]event, n)
   179  
   180  	for i := 0; i < n; i++ {
   181  		ev[i] = event{
   182  			Mode:            TimestampMode,
   183  			ShouldExecuteAt: time.Now().Add(time.Duration(time.Second.Nanoseconds() * int64(i+1))),
   184  			ID:              randomID(idSize),
   185  		}
   186  	}
   187  
   188  	return ev
   189  }