github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/event/subscription_test.go (about)

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