vitess.io/vitess@v0.16.2/go/event/event_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreedto in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package event
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  )
    24  
    25  type testInterface1 interface {
    26  	TestFunc1()
    27  }
    28  
    29  type testInterface2 interface {
    30  	TestFunc2()
    31  }
    32  
    33  type testEvent1 struct {
    34  }
    35  
    36  type testEvent2 struct {
    37  	triggered bool
    38  }
    39  
    40  func (testEvent1) TestFunc1() {}
    41  
    42  func (*testEvent2) TestFunc2() {}
    43  
    44  func clearListeners() {
    45  	listenersMutex.Lock()
    46  	defer listenersMutex.Unlock()
    47  
    48  	listeners = make(map[reflect.Type][]any)
    49  	interfaces = make([]reflect.Type, 0)
    50  }
    51  
    52  func TestStaticListener(t *testing.T) {
    53  	clearListeners()
    54  
    55  	triggered := false
    56  	AddListener(func(testEvent1) { triggered = true })
    57  	AddListener(func(testEvent2) { t.Errorf("wrong listener type triggered") })
    58  	Dispatch(testEvent1{})
    59  
    60  	if !triggered {
    61  		t.Errorf("static listener failed to trigger")
    62  	}
    63  }
    64  
    65  func TestPointerListener(t *testing.T) {
    66  	clearListeners()
    67  
    68  	testEvent := new(testEvent2)
    69  	AddListener(func(ev *testEvent2) { ev.triggered = true })
    70  	AddListener(func(testEvent2) { t.Errorf("non-pointer listener triggered on pointer type") })
    71  	Dispatch(testEvent)
    72  
    73  	if !testEvent.triggered {
    74  		t.Errorf("pointer listener failed to trigger")
    75  	}
    76  }
    77  
    78  func TestInterfaceListener(t *testing.T) {
    79  	clearListeners()
    80  
    81  	triggered := false
    82  	AddListener(func(testInterface1) { triggered = true })
    83  	AddListener(func(testInterface2) { t.Errorf("interface listener triggered on non-matching type") })
    84  	Dispatch(testEvent1{})
    85  
    86  	if !triggered {
    87  		t.Errorf("interface listener failed to trigger")
    88  	}
    89  }
    90  
    91  func TestEmptyInterfaceListener(t *testing.T) {
    92  	clearListeners()
    93  
    94  	triggered := false
    95  	AddListener(func(any) { triggered = true })
    96  	Dispatch("this should match any")
    97  
    98  	if !triggered {
    99  		t.Errorf("any listener failed to trigger")
   100  	}
   101  }
   102  
   103  func TestMultipleListeners(t *testing.T) {
   104  	clearListeners()
   105  
   106  	triggered1, triggered2 := false, false
   107  	AddListener(func(testEvent1) { triggered1 = true })
   108  	AddListener(func(testEvent1) { triggered2 = true })
   109  	Dispatch(testEvent1{})
   110  
   111  	if !triggered1 || !triggered2 {
   112  		t.Errorf("not all matching listeners triggered")
   113  	}
   114  }
   115  
   116  func TestBadListenerWrongInputs(t *testing.T) {
   117  	clearListeners()
   118  
   119  	defer func() {
   120  		err := recover()
   121  
   122  		if err == nil {
   123  			t.Errorf("bad listener func (wrong # of inputs) failed to trigger panic")
   124  			return
   125  		}
   126  
   127  		blErr, ok := err.(BadListenerError)
   128  		if !ok {
   129  			panic(err) // this is not the error we were looking for; re-panic
   130  		}
   131  
   132  		want := "bad listener func: listener must take exactly one input argument"
   133  		if got := blErr.Error(); got != want {
   134  			t.Errorf(`BadListenerError.Error() = "%s", want "%s"`, got, want)
   135  		}
   136  	}()
   137  
   138  	AddListener(func() {})
   139  	Dispatch(testEvent1{})
   140  }
   141  
   142  func TestBadListenerWrongType(t *testing.T) {
   143  	clearListeners()
   144  
   145  	defer func() {
   146  		err := recover()
   147  
   148  		if err == nil {
   149  			t.Errorf("bad listener type (not a func) failed to trigger panic")
   150  		}
   151  
   152  		blErr, ok := err.(BadListenerError)
   153  		if !ok {
   154  			panic(err) // this is not the error we were looking for; re-panic
   155  		}
   156  
   157  		want := "bad listener func: listener must be a function"
   158  		if got := blErr.Error(); got != want {
   159  			t.Errorf(`BadListenerError.Error() = "%s", want "%s"`, got, want)
   160  		}
   161  	}()
   162  
   163  	AddListener("this is not a function")
   164  	Dispatch(testEvent1{})
   165  }
   166  
   167  func TestAsynchronousDispatch(t *testing.T) {
   168  	clearListeners()
   169  
   170  	triggered := make(chan bool)
   171  	AddListener(func(testEvent1) { triggered <- true })
   172  	go Dispatch(testEvent1{})
   173  
   174  	select {
   175  	case <-triggered:
   176  	case <-time.After(time.Second):
   177  		t.Errorf("asynchronous dispatch failed to trigger listener")
   178  	}
   179  }
   180  
   181  func TestDispatchPointerToValueInterfaceListener(t *testing.T) {
   182  	clearListeners()
   183  
   184  	triggered := false
   185  	AddListener(func(ev testInterface1) {
   186  		triggered = true
   187  	})
   188  	Dispatch(&testEvent1{})
   189  
   190  	if !triggered {
   191  		t.Errorf("Dispatch by pointer failed to trigger interface listener")
   192  	}
   193  }
   194  
   195  func TestDispatchValueToValueInterfaceListener(t *testing.T) {
   196  	clearListeners()
   197  
   198  	triggered := false
   199  	AddListener(func(ev testInterface1) {
   200  		triggered = true
   201  	})
   202  	Dispatch(testEvent1{})
   203  
   204  	if !triggered {
   205  		t.Errorf("Dispatch by value failed to trigger interface listener")
   206  	}
   207  }
   208  
   209  func TestDispatchPointerToPointerInterfaceListener(t *testing.T) {
   210  	clearListeners()
   211  
   212  	triggered := false
   213  	AddListener(func(testInterface2) { triggered = true })
   214  	Dispatch(&testEvent2{})
   215  
   216  	if !triggered {
   217  		t.Errorf("interface listener failed to trigger for pointer")
   218  	}
   219  }
   220  
   221  func TestDispatchValueToPointerInterfaceListener(t *testing.T) {
   222  	clearListeners()
   223  
   224  	AddListener(func(testInterface2) {
   225  		t.Errorf("interface listener triggered for value dispatch")
   226  	})
   227  	Dispatch(testEvent2{})
   228  }
   229  
   230  type testUpdateEvent struct {
   231  	update any
   232  }
   233  
   234  func (ev *testUpdateEvent) Update(update any) {
   235  	ev.update = update
   236  }
   237  
   238  func TestDispatchUpdate(t *testing.T) {
   239  	clearListeners()
   240  
   241  	triggered := false
   242  	AddListener(func(*testUpdateEvent) {
   243  		triggered = true
   244  	})
   245  
   246  	ev := &testUpdateEvent{}
   247  	DispatchUpdate(ev, "hello")
   248  
   249  	if !triggered {
   250  		t.Errorf("listener failed to trigger on DispatchUpdate()")
   251  	}
   252  	want := "hello"
   253  	if got := ev.update.(string); got != want {
   254  		t.Errorf("ev.update = %#v, want %#v", got, want)
   255  	}
   256  }