github.com/diamondburned/arikawa@v1.3.14/utils/handler/handler_test.go (about)

     1  package handler
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/diamondburned/arikawa/discord"
    11  	"github.com/diamondburned/arikawa/gateway"
    12  )
    13  
    14  func newMessage(content string) *gateway.MessageCreateEvent {
    15  	return &gateway.MessageCreateEvent{
    16  		Message: discord.Message{Content: content},
    17  	}
    18  }
    19  
    20  func TestCall(t *testing.T) {
    21  	var results = make(chan string)
    22  
    23  	h := &Handler{
    24  		handlers: map[uint64]handler{},
    25  	}
    26  
    27  	// Add handler test
    28  	rm := h.AddHandler(func(m *gateway.MessageCreateEvent) {
    29  		results <- m.Content
    30  	})
    31  
    32  	go h.Call(newMessage("hime arikawa"))
    33  
    34  	if r := <-results; r != "hime arikawa" {
    35  		t.Fatal("Returned results is wrong:", r)
    36  	}
    37  
    38  	// Delete handler test
    39  	rm()
    40  
    41  	go h.Call(newMessage("astolfo"))
    42  
    43  	select {
    44  	case <-results:
    45  		t.Fatal("Unexpected results")
    46  	case <-time.After(5 * time.Millisecond):
    47  		break
    48  	}
    49  
    50  	// Invalid type test
    51  	_, err := h.AddHandlerCheck("this should panic")
    52  	if err == nil {
    53  		t.Fatal("No errors found")
    54  	}
    55  
    56  	// We don't do anything with the returned callback, as there's none.
    57  
    58  	if !strings.Contains(err.Error(), "given interface is not a function") {
    59  		t.Fatal("Unexpected error:", err)
    60  	}
    61  }
    62  
    63  func TestHandler(t *testing.T) {
    64  	var results = make(chan string)
    65  
    66  	h, err := newHandler(func(m *gateway.MessageCreateEvent) {
    67  		results <- m.Content
    68  	})
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  
    73  	const result = "Hime Arikawa"
    74  	var msg = newMessage(result)
    75  
    76  	var msgV = reflect.ValueOf(msg)
    77  	var msgT = msgV.Type()
    78  
    79  	if h.not(msgT) {
    80  		t.Fatal("Event type mismatch")
    81  	}
    82  
    83  	go h.call(msgV)
    84  
    85  	if results := <-results; results != result {
    86  		t.Fatal("Unexpected results:", results)
    87  	}
    88  }
    89  
    90  func TestHandlerChan(t *testing.T) {
    91  	var results = make(chan *gateway.MessageCreateEvent)
    92  
    93  	h, err := newHandler(results)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	const result = "Hime Arikawa"
    99  	var msg = newMessage(result)
   100  
   101  	var msgV = reflect.ValueOf(msg)
   102  	var msgT = msgV.Type()
   103  
   104  	if h.not(msgT) {
   105  		t.Fatal("Event type mismatch")
   106  	}
   107  
   108  	go h.call(msgV)
   109  
   110  	if results := <-results; results.Content != result {
   111  		t.Fatal("Unexpected results:", results)
   112  	}
   113  }
   114  
   115  func TestHandlerChanCancel(t *testing.T) {
   116  	// Never receive from this channel. It is important that this channel is
   117  	// unbuffered.
   118  	var results = make(chan *gateway.MessageCreateEvent)
   119  
   120  	h, err := newHandler(results)
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	const result = "Hime Arikawa"
   126  	var msg = newMessage(result)
   127  
   128  	var msgV = reflect.ValueOf(msg)
   129  	var msgT = msgV.Type()
   130  
   131  	if h.not(msgT) {
   132  		t.Fatal("Event type mismatch")
   133  	}
   134  
   135  	// Channel that waits for call() to die.
   136  	die := make(chan struct{})
   137  
   138  	// Call in a goroutine, which would trigger a close.
   139  	go func() { h.call(msgV); die <- struct{}{} }()
   140  
   141  	// Call the cleanup function, which should stop the send.
   142  	h.cleanup()
   143  
   144  	// Check if we still have things being sent.
   145  	select {
   146  	case <-die:
   147  		// pass
   148  	case <-time.After(200 * time.Millisecond):
   149  		t.Fatal("Timed out waiting for call routine to die.")
   150  	}
   151  
   152  	// Check if we still receive something.
   153  	select {
   154  	case <-results:
   155  		t.Fatal("Unexpected results received.")
   156  	default:
   157  		// pass
   158  	}
   159  }
   160  
   161  func TestHandlerInterface(t *testing.T) {
   162  	var results = make(chan interface{})
   163  
   164  	h, err := newHandler(func(m interface{}) {
   165  		results <- m
   166  	})
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	const result = "Hime Arikawa"
   172  	var msg = newMessage(result)
   173  
   174  	var msgV = reflect.ValueOf(msg)
   175  	var msgT = msgV.Type()
   176  
   177  	if h.not(msgT) {
   178  		t.Fatal("Event type mismatch")
   179  	}
   180  
   181  	go h.call(msgV)
   182  	recv := <-results
   183  
   184  	if msg, ok := recv.(*gateway.MessageCreateEvent); ok {
   185  		if msg.Content == result {
   186  			return
   187  		}
   188  
   189  		t.Fatal("Content mismatch:", msg.Content)
   190  	}
   191  
   192  	t.Fatal("Assertion failed:", recv)
   193  }
   194  
   195  func TestHandlerWaitFor(t *testing.T) {
   196  	inc := make(chan interface{}, 1)
   197  
   198  	h := New()
   199  
   200  	wanted := &gateway.TypingStartEvent{
   201  		ChannelID: 123456,
   202  	}
   203  
   204  	evs := []interface{}{
   205  		&gateway.TypingStartEvent{},
   206  		&gateway.MessageCreateEvent{},
   207  		&gateway.ChannelDeleteEvent{},
   208  		wanted,
   209  	}
   210  
   211  	go func() {
   212  		inc <- h.WaitFor(context.Background(), func(v interface{}) bool {
   213  			tp, ok := v.(*gateway.TypingStartEvent)
   214  			if !ok {
   215  				return false
   216  			}
   217  
   218  			return tp.ChannelID == wanted.ChannelID
   219  		})
   220  	}()
   221  
   222  	// Wait for WaitFor to add its handler:
   223  	time.Sleep(time.Millisecond)
   224  
   225  	for _, ev := range evs {
   226  		h.Call(ev)
   227  	}
   228  
   229  	recv := <-inc
   230  	if recv != wanted {
   231  		t.Fatal("Unexpected receive:", recv)
   232  	}
   233  
   234  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
   235  	defer cancel()
   236  
   237  	// Test timeout
   238  	v := h.WaitFor(ctx, func(v interface{}) bool {
   239  		return false
   240  	})
   241  
   242  	if v != nil {
   243  		t.Fatal("Unexpected value:", v)
   244  	}
   245  }
   246  
   247  func TestHandlerChanFor(t *testing.T) {
   248  	h := New()
   249  
   250  	wanted := &gateway.TypingStartEvent{
   251  		ChannelID: 123456,
   252  	}
   253  
   254  	evs := []interface{}{
   255  		&gateway.TypingStartEvent{},
   256  		&gateway.MessageCreateEvent{},
   257  		&gateway.ChannelDeleteEvent{},
   258  		wanted,
   259  	}
   260  
   261  	inc, cancel := h.ChanFor(func(v interface{}) bool {
   262  		tp, ok := v.(*gateway.TypingStartEvent)
   263  		if !ok {
   264  			return false
   265  		}
   266  
   267  		return tp.ChannelID == wanted.ChannelID
   268  	})
   269  	defer cancel()
   270  
   271  	for _, ev := range evs {
   272  		h.Call(ev)
   273  	}
   274  
   275  	recv := <-inc
   276  	if recv != wanted {
   277  		t.Fatal("Unexpected receive:", recv)
   278  	}
   279  }
   280  
   281  func BenchmarkReflect(b *testing.B) {
   282  	h, err := newHandler(func(m *gateway.MessageCreateEvent) {})
   283  	if err != nil {
   284  		b.Fatal(err)
   285  	}
   286  
   287  	var msg = &gateway.MessageCreateEvent{}
   288  
   289  	b.ResetTimer()
   290  
   291  	for n := 0; n < b.N; n++ {
   292  		var msgV = reflect.ValueOf(msg)
   293  		var msgT = msgV.Type()
   294  
   295  		if h.not(msgT) {
   296  			b.Fatal("Event type mismatch")
   297  		}
   298  
   299  		h.call(msgV)
   300  	}
   301  }