github.com/haraldrudell/parl@v0.4.176/iters/function_test.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package iters
     7  
     8  import (
     9  	"testing"
    10  
    11  	"github.com/haraldrudell/parl/internal/cyclebreaker"
    12  	"github.com/haraldrudell/parl/perrors"
    13  )
    14  
    15  func TestFunction(t *testing.T) {
    16  	var value1, value2 = 1, 2
    17  	var values = []int{value1, value2}
    18  
    19  	var err error
    20  	var value, zeroValue, iterationVariable int
    21  	var hasValue, condition bool
    22  	var actIterator Iterator[int]
    23  
    24  	var iterator Iterator[int]
    25  	var reset = func() {
    26  		iterator = NewFunctionIterator(newHasFunc(values).IteratorFunction)
    27  	}
    28  	// Init() Cond() Next() Same() Cancel()
    29  	var _ Slice[int]
    30  
    31  	// Init should return zero value and iterator
    32  	reset()
    33  	iterationVariable, actIterator = iterator.Init()
    34  	if iterationVariable != zeroValue {
    35  		t.Errorf("Init iterationVariable %d exp %d", iterationVariable, zeroValue)
    36  	}
    37  	if actIterator != iterator {
    38  		t.Error("Init iterator bad")
    39  	}
    40  
    41  	// Cond should return true and update value
    42  	reset()
    43  	value = zeroValue
    44  	condition = iterator.Cond(&value)
    45  	if !condition {
    46  		t.Error("Cond condition false")
    47  	}
    48  	if value != value1 {
    49  		t.Errorf("Cond value %d exp %d", value, value1)
    50  	}
    51  
    52  	// Next should return first value
    53  	reset()
    54  	value, hasValue = iterator.Next()
    55  	if !hasValue {
    56  		t.Error("Next hasValue false")
    57  	}
    58  	if value != value1 {
    59  		t.Errorf("Next value %d exp %d", value, value1)
    60  	}
    61  
    62  	// Cancel should return no error
    63  	reset()
    64  	err = iterator.Cancel()
    65  	if err != nil {
    66  		t.Errorf("Cancel err: %s", perrors.Short(err))
    67  	}
    68  
    69  	// CondCond should return second value
    70  	reset()
    71  	condition = iterator.Cond(&value)
    72  	_ = condition
    73  	value = zeroValue
    74  	condition = iterator.Cond(&value)
    75  	if !condition {
    76  		t.Error("CondCond condition false")
    77  	}
    78  	if value != value2 {
    79  		t.Errorf("Cond value %d exp %d", value, value2)
    80  	}
    81  
    82  	// CondCondCond should return no value
    83  	// request IsSame value twice should:
    84  	//   - retrieve the first value and return it
    85  	//   - then return the same value again
    86  	//
    87  	// Cond should return true and update value
    88  	reset()
    89  	condition = iterator.Cond(&value)
    90  	_ = condition
    91  	condition = iterator.Cond(&value)
    92  	_ = condition
    93  	value = zeroValue
    94  	condition = iterator.Cond(&value)
    95  	if condition {
    96  		t.Error("CondCondCond condition true")
    97  	}
    98  	if value != zeroValue {
    99  		t.Errorf("CondCondCond value %d exp %d", value, zeroValue)
   100  	}
   101  
   102  	// NextNext should return second value
   103  	reset()
   104  	value, hasValue = iterator.Next()
   105  	_ = value
   106  	_ = hasValue
   107  	value, hasValue = iterator.Next()
   108  	if !hasValue {
   109  		t.Error("NextNext hasValue false")
   110  	}
   111  	if value != value2 {
   112  		t.Errorf("NextNext value %d exp %d", value, value2)
   113  	}
   114  
   115  	// NextNextNext should return no value
   116  	reset()
   117  	value, hasValue = iterator.Next()
   118  	_ = value
   119  	_ = hasValue
   120  	value, hasValue = iterator.Next()
   121  	_ = value
   122  	_ = hasValue
   123  	value, hasValue = iterator.Next()
   124  	if hasValue {
   125  		t.Error("NextNextNext hasValue true")
   126  	}
   127  	if value != zeroValue {
   128  		t.Errorf("NextNextNext value %d exp %d", value, zeroValue)
   129  	}
   130  
   131  	// CancelCond should return false
   132  	reset()
   133  	err = iterator.Cancel()
   134  	_ = err
   135  	condition = iterator.Cond(&value)
   136  	if condition {
   137  		t.Error("CancelCond condition true")
   138  	}
   139  
   140  	// CancelNext should return no value
   141  	reset()
   142  	err = iterator.Cancel()
   143  	_ = err
   144  	value, hasValue = iterator.Next()
   145  	if hasValue {
   146  		t.Error("CancelNext hasValue true")
   147  	}
   148  	if value != zeroValue {
   149  		t.Errorf("CancelNext value %d exp %d", value, zeroValue)
   150  	}
   151  }
   152  
   153  type hasFunc[T any] struct {
   154  	slice []T
   155  	index int
   156  }
   157  
   158  func newHasFunc[T any](slice []T) (s *hasFunc[T]) { return &hasFunc[T]{slice: slice} }
   159  func (s *hasFunc[T]) IteratorFunction(isCancel bool) (value T, err error) {
   160  	if isCancel {
   161  		return
   162  	} else if s.index >= len(s.slice) {
   163  		err = cyclebreaker.ErrEndCallbacks
   164  		return
   165  	}
   166  	value = s.slice[s.index]
   167  	s.index++
   168  
   169  	return
   170  }