github.com/core-coin/go-core/v2@v2.1.9/event/subscription_test.go (about)

     1  // Copyright 2016 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-core library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package event
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"testing"
    23  	"time"
    24  )
    25  
    26  var errInts = errors.New("error in subscribeInts")
    27  
    28  func subscribeInts(max, fail int, c chan<- int) Subscription {
    29  	return NewSubscription(func(quit <-chan struct{}) error {
    30  		for i := 0; i < max; i++ {
    31  			if i >= fail {
    32  				return errInts
    33  			}
    34  			select {
    35  			case c <- i:
    36  			case <-quit:
    37  				return nil
    38  			}
    39  		}
    40  		return nil
    41  	})
    42  }
    43  
    44  func TestNewSubscriptionError(t *testing.T) {
    45  	t.Parallel()
    46  
    47  	channel := make(chan int)
    48  	sub := subscribeInts(10, 2, channel)
    49  loop:
    50  	for want := 0; want < 10; want++ {
    51  		select {
    52  		case got := <-channel:
    53  			if got != want {
    54  				t.Fatalf("wrong int %d, want %d", got, want)
    55  			}
    56  		case err := <-sub.Err():
    57  			if err != errInts {
    58  				t.Fatalf("wrong error: got %q, want %q", err, errInts)
    59  			}
    60  			if want != 2 {
    61  				t.Fatalf("got errInts at int %d, should be received at 2", want)
    62  			}
    63  			break loop
    64  		}
    65  	}
    66  	sub.Unsubscribe()
    67  
    68  	err, ok := <-sub.Err()
    69  	if err != nil {
    70  		t.Fatal("got non-nil error after Unsubscribe")
    71  	}
    72  	if ok {
    73  		t.Fatal("channel still open after Unsubscribe")
    74  	}
    75  }
    76  
    77  func TestResubscribe(t *testing.T) {
    78  	t.Parallel()
    79  
    80  	var i int
    81  	nfails := 6
    82  	sub := Resubscribe(100*time.Millisecond, func(ctx context.Context) (Subscription, error) {
    83  		// fmt.Printf("call #%d @ %v\n", i, time.Now())
    84  		i++
    85  		if i == 2 {
    86  			// Delay the second failure a bit to reset the resubscribe interval.
    87  			time.Sleep(200 * time.Millisecond)
    88  		}
    89  		if i < nfails {
    90  			return nil, errors.New("oops")
    91  		}
    92  		sub := NewSubscription(func(unsubscribed <-chan struct{}) error { return nil })
    93  		return sub, nil
    94  	})
    95  
    96  	<-sub.Err()
    97  	if i != nfails {
    98  		t.Fatalf("resubscribe function called %d times, want %d times", i, nfails)
    99  	}
   100  }
   101  
   102  func TestResubscribeAbort(t *testing.T) {
   103  	t.Parallel()
   104  
   105  	done := make(chan error, 1)
   106  	sub := Resubscribe(0, func(ctx context.Context) (Subscription, error) {
   107  		select {
   108  		case <-ctx.Done():
   109  			done <- nil
   110  		case <-time.After(2 * time.Second):
   111  			done <- errors.New("context given to resubscribe function not canceled within 2s")
   112  		}
   113  		return nil, nil
   114  	})
   115  
   116  	sub.Unsubscribe()
   117  	if err := <-done; err != nil {
   118  		t.Fatal(err)
   119  	}
   120  }