2020-05-30 00:34:53 +02:00
|
|
|
// Copyright The OpenTelemetry Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package global
|
|
|
|
|
|
|
|
import (
|
2020-06-01 19:38:05 +02:00
|
|
|
"bytes"
|
2020-05-30 00:34:53 +02:00
|
|
|
"errors"
|
2020-06-09 21:07:23 +02:00
|
|
|
"fmt"
|
2020-06-01 19:38:05 +02:00
|
|
|
"log"
|
2020-05-30 00:34:53 +02:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
)
|
|
|
|
|
2020-06-01 19:38:05 +02:00
|
|
|
type errLogger []string
|
|
|
|
|
|
|
|
func (l *errLogger) Write(p []byte) (int, error) {
|
|
|
|
msg := bytes.TrimRight(p, "\n")
|
|
|
|
(*l) = append(*l, string(msg))
|
|
|
|
return len(msg), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *errLogger) Reset() {
|
|
|
|
*l = errLogger([]string{})
|
|
|
|
}
|
2020-05-30 00:34:53 +02:00
|
|
|
|
2020-06-01 19:38:05 +02:00
|
|
|
func (l *errLogger) Got() []string {
|
|
|
|
return []string(*l)
|
2020-05-30 00:34:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type HandlerTestSuite struct {
|
|
|
|
suite.Suite
|
|
|
|
|
2020-06-01 19:38:05 +02:00
|
|
|
origHandler *handler
|
2020-06-01 20:50:35 +02:00
|
|
|
errLogger *errLogger
|
2020-05-30 00:34:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HandlerTestSuite) SetupSuite() {
|
2020-06-01 19:38:05 +02:00
|
|
|
s.errLogger = new(errLogger)
|
2020-06-01 20:50:35 +02:00
|
|
|
s.origHandler = globalHandler
|
|
|
|
globalHandler = &handler{
|
2020-06-01 19:38:05 +02:00
|
|
|
l: log.New(s.errLogger, "", 0),
|
|
|
|
}
|
2020-05-30 00:34:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HandlerTestSuite) TearDownSuite() {
|
2020-06-01 20:50:35 +02:00
|
|
|
globalHandler = s.origHandler
|
2020-05-30 00:34:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HandlerTestSuite) SetupTest() {
|
2020-06-01 19:38:05 +02:00
|
|
|
s.errLogger.Reset()
|
2020-05-30 00:34:53 +02:00
|
|
|
}
|
|
|
|
|
2020-06-01 18:28:27 +02:00
|
|
|
func (s *HandlerTestSuite) TestGlobalHandler() {
|
2020-06-01 19:38:05 +02:00
|
|
|
errs := []string{"one", "two"}
|
|
|
|
Handler().Handle(errors.New(errs[0]))
|
|
|
|
Handle(errors.New(errs[1]))
|
|
|
|
s.Assert().Equal(errs, s.errLogger.Got())
|
2020-05-30 00:34:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *HandlerTestSuite) TestNoDropsOnDelegate() {
|
2020-06-09 21:07:23 +02:00
|
|
|
// max time to wait for goroutine to Handle an error.
|
|
|
|
pause := 10 * time.Millisecond
|
|
|
|
|
2020-05-30 00:34:53 +02:00
|
|
|
var sent int
|
|
|
|
err := errors.New("")
|
|
|
|
stop := make(chan struct{})
|
|
|
|
beat := make(chan struct{})
|
|
|
|
done := make(chan struct{})
|
|
|
|
|
2020-06-09 21:07:23 +02:00
|
|
|
// Wait for a error to be submitted from the following goroutine.
|
|
|
|
wait := func(d time.Duration) error {
|
|
|
|
timer := time.NewTimer(d)
|
|
|
|
select {
|
|
|
|
case <-timer.C:
|
|
|
|
// We are about to fail, stop the spawned goroutine.
|
|
|
|
stop <- struct{}{}
|
|
|
|
return fmt.Errorf("no errors sent in %v", d)
|
|
|
|
case <-beat:
|
2020-06-10 02:21:01 +02:00
|
|
|
// Allow the timer to be reclaimed by GC.
|
2020-06-09 21:07:23 +02:00
|
|
|
timer.Stop()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-30 00:34:53 +02:00
|
|
|
go func() {
|
2020-06-10 02:21:01 +02:00
|
|
|
// Slow down to speed up: do not overload the processor.
|
|
|
|
ticker := time.NewTicker(100 * time.Microsecond)
|
2020-05-30 00:34:53 +02:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-stop:
|
2020-06-10 02:21:01 +02:00
|
|
|
ticker.Stop()
|
2020-05-30 00:34:53 +02:00
|
|
|
done <- struct{}{}
|
|
|
|
return
|
2020-06-10 02:21:01 +02:00
|
|
|
case <-ticker.C:
|
2020-05-30 00:34:53 +02:00
|
|
|
sent++
|
|
|
|
Handle(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case beat <- struct{}{}:
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Wait for the spice to flow
|
2020-06-09 21:07:23 +02:00
|
|
|
s.Require().NoError(wait(pause), "starting error stream")
|
2020-05-30 00:34:53 +02:00
|
|
|
|
|
|
|
// Change to another Handler. We are testing this is loss-less.
|
2020-06-01 19:38:05 +02:00
|
|
|
newErrLogger := new(errLogger)
|
|
|
|
secondary := &handler{
|
|
|
|
l: log.New(newErrLogger, "", 0),
|
|
|
|
}
|
2020-05-30 00:34:53 +02:00
|
|
|
SetHandler(secondary)
|
2020-06-10 02:21:01 +02:00
|
|
|
s.Require().NoError(wait(pause), "switched to new Handler")
|
2020-05-30 00:34:53 +02:00
|
|
|
|
2020-06-09 21:07:23 +02:00
|
|
|
// Testing done, stop sending errors.
|
2020-05-30 00:34:53 +02:00
|
|
|
stop <- struct{}{}
|
|
|
|
// Ensure we do not lose any straglers.
|
|
|
|
<-done
|
|
|
|
|
2020-06-01 19:38:05 +02:00
|
|
|
got := append(s.errLogger.Got(), newErrLogger.Got()...)
|
|
|
|
s.Assert().Greater(len(got), 1, "at least 2 errors should have been sent")
|
|
|
|
s.Assert().Len(got, sent)
|
2020-05-30 00:34:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandlerTestSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(HandlerTestSuite))
|
|
|
|
}
|