github.com/haraldrudell/parl@v0.4.176/closer_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 parl
     7  
     8  import (
     9  	"errors"
    10  	"strconv"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/haraldrudell/parl/perrors"
    15  )
    16  
    17  func TestCloser(t *testing.T) {
    18  	message := "close of closed channel"
    19  	messageNil := "close of nil channel"
    20  
    21  	var ch chan struct{}
    22  	var err error
    23  	var c chan struct{}
    24  
    25  	ch = make(chan struct{})
    26  	Closer(ch, &err)
    27  	if err != nil {
    28  		t.Errorf("Closer err: %v exp nil", err)
    29  	}
    30  
    31  	err = nil
    32  	Closer(ch, &err)
    33  	if err == nil || !strings.Contains(err.Error(), message) {
    34  		t.Errorf("Closer closed err: %v exp %q", err, message)
    35  	}
    36  
    37  	ch = c
    38  	err = nil
    39  	Closer(ch, &err)
    40  	if err == nil || !strings.Contains(err.Error(), messageNil) {
    41  		t.Errorf("Closer nil err: %v exp %q", err, messageNil)
    42  	}
    43  }
    44  
    45  func TestCloserSend(t *testing.T) {
    46  	message := "close of closed channel"
    47  	messageNil := "close of nil channel"
    48  
    49  	var ch chan<- struct{}
    50  	var err error
    51  	var c chan<- struct{}
    52  
    53  	ch = make(chan<- struct{})
    54  	CloserSend(ch, &err)
    55  	if err != nil {
    56  		t.Errorf("Closer err: %v exp nil", err)
    57  	}
    58  
    59  	err = nil
    60  	CloserSend(ch, &err)
    61  	if err == nil || !strings.Contains(err.Error(), message) {
    62  		t.Errorf("Closer closed err: %v exp %q", err, message)
    63  	}
    64  
    65  	ch = c
    66  	err = nil
    67  	CloserSend(ch, &err)
    68  	if err == nil || !strings.Contains(err.Error(), messageNil) {
    69  		t.Errorf("Closer nil err: %v exp %q", err, messageNil)
    70  	}
    71  }
    72  
    73  func TestClose(t *testing.T) {
    74  	// “nil pointer”
    75  	//	- part of panic message:
    76  	//	- “runtime error: invalid memory address or nil pointer dereference”
    77  	var message = "nil pointer"
    78  	// “x”
    79  	var messageX = "x"
    80  	// “y”
    81  	var messageY = "y"
    82  
    83  	var err error
    84  
    85  	// a successful Close should not return error
    86  	Close(newTestClosable(nil), &err)
    87  	if err != nil {
    88  		t.Errorf("Close err: %v", err)
    89  	}
    90  
    91  	// Close of nil io.Closable should return error, not panic
    92  	err = nil
    93  	Close(nil, &err)
    94  
    95  	// err: panic detected in parl.Close:
    96  	// “runtime error: invalid memory address or nil pointer dereference”
    97  	// at parl.Close()-closer.go:40
    98  	//t.Logf("err: %s", perrors.Short(err))
    99  	//t.Fail()
   100  
   101  	if err == nil || !strings.Contains(err.Error(), message) {
   102  		t.Errorf("Close err: %v exp %q", err, message)
   103  	}
   104  
   105  	// a failed Close should append to err
   106  	//	- err should become X with Y appended
   107  	err = errors.New(messageX)
   108  	Close(newTestClosable(errors.New(messageY)), &err)
   109  	// errs is a list of associated errors, oldest first
   110  	//	- first X, then Y
   111  	var errs = perrors.ErrorList(err)
   112  	if len(errs) != 2 || errs[0].Error() != messageX || !strings.HasSuffix(errs[1].Error(), messageY) {
   113  		var quoteList = make([]string, len(errs))
   114  		for i, err := range errs {
   115  			quoteList[i] = strconv.Quote(err.Error())
   116  		}
   117  		// erss bad: ["x" "parl.Close y"]
   118  		t.Errorf("erss bad: %v", quoteList)
   119  	}
   120  }
   121  
   122  // testClosable is an [io.Closable] with configurable fail error
   123  type testClosable struct{ err error }
   124  
   125  // newTestClosable returns a closable whose Close always fails with err
   126  func newTestClosable(err error) (closable *testClosable) { return &testClosable{err: err} }
   127  
   128  // Close returns a configured error
   129  func (tc *testClosable) Close() (err error) { return tc.err }