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