Add tests for unix goroutines dumper

parent a79f3f53
Pipeline #31932284 passed with stages
in 72 minutes and 42 seconds
......@@ -15,7 +15,7 @@ const (
)
var (
configuration = NewConfig()
configuration = NewConfig(logrus.StandardLogger())
logFlags = []cli.Flag{
cli.BoolFlag{
......@@ -52,6 +52,7 @@ func formatNames() []string {
}
type Config struct {
logger *logrus.Logger
level logrus.Level
format logrus.Formatter
......@@ -120,8 +121,8 @@ func (l *Config) SetFormat(format string) error {
}
func (l *Config) ReloadConfiguration() {
logrus.SetFormatter(l.format)
logrus.SetLevel(l.level)
l.logger.SetFormatter(l.format)
l.logger.SetLevel(l.level)
if l.level == logrus.DebugLevel {
l.enableGoroutinesDump()
......@@ -137,7 +138,7 @@ func (l *Config) enableGoroutinesDump() {
l.goroutinesDumpStopCh = make(chan bool)
watchForGoroutinesDump(l.goroutinesDumpStopCh)
watchForGoroutinesDump(l.logger, l.goroutinesDumpStopCh)
}
func (l *Config) disableGoroutinesDump() {
......@@ -149,8 +150,9 @@ func (l *Config) disableGoroutinesDump() {
l.goroutinesDumpStopCh = nil
}
func NewConfig() *Config {
func NewConfig(logger *logrus.Logger) *Config {
return &Config{
logger: logger,
level: logrus.InfoLevel,
format: new(RunnerTextFormatter),
}
......@@ -165,7 +167,7 @@ func ConfigureLogging(app *cli.App) {
appBefore := app.Before
app.Before = func(cliCtx *cli.Context) error {
logrus.SetOutput(os.Stderr)
Configuration().logger.SetOutput(os.Stderr)
err := Configuration().handleCliCtx(cliCtx)
if err != nil {
......
......@@ -4,6 +4,7 @@ import (
"testing"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
......@@ -11,9 +12,9 @@ import (
"gitlab.com/gitlab-org/gitlab-runner/helpers"
)
func prepareFakeConfiguration() func() {
func prepareFakeConfiguration(logger *logrus.Logger) func() {
oldConfiguration := configuration
configuration = NewConfig()
configuration = NewConfig(logger)
return func() {
configuration = oldConfiguration
......@@ -90,20 +91,22 @@ func TestHandleCliCtx(t *testing.T) {
},
}
for name, test := range tests {
for name, testCase := range tests {
t.Run(name, func(t *testing.T) {
defer prepareFakeConfiguration()()
logger, _ := test.NewNullLogger()
defer prepareFakeConfiguration(logger)()
defer helpers.MakeFatalToPanic()()
testFunc := func() {
testCommandRun(test.args...)
if test.expectedError == "" {
assert.Equal(t, test.expectedLevel, Configuration().level)
assert.Equal(t, test.expectedFormatter, Configuration().format)
assert.Equal(t, test.expectedLevelSetWithCli, Configuration().IsLevelSetWithCli())
assert.Equal(t, test.expectedFormatSetWithCli, Configuration().IsFormatSetWithCli())
if test.goroutinesDumpStopChExists {
testCommandRun(testCase.args...)
if testCase.expectedError == "" {
assert.Equal(t, testCase.expectedLevel, Configuration().level)
assert.Equal(t, testCase.expectedFormatter, Configuration().format)
assert.Equal(t, testCase.expectedLevelSetWithCli, Configuration().IsLevelSetWithCli())
assert.Equal(t, testCase.expectedFormatSetWithCli, Configuration().IsFormatSetWithCli())
if testCase.goroutinesDumpStopChExists {
assert.NotNil(t, Configuration().goroutinesDumpStopCh)
} else {
assert.Nil(t, Configuration().goroutinesDumpStopCh)
......@@ -111,7 +114,7 @@ func TestHandleCliCtx(t *testing.T) {
}
}
if test.expectedError != "" {
if testCase.expectedError != "" {
var message *logrus.Entry
var ok bool
......@@ -129,7 +132,7 @@ func TestHandleCliCtx(t *testing.T) {
require.NoError(t, err)
assert.Contains(t, panicMessage, "Error while setting up logging configuration")
assert.Contains(t, panicMessage, test.expectedError)
assert.Contains(t, panicMessage, testCase.expectedError)
} else {
assert.NotPanics(t, testFunc)
......@@ -139,7 +142,9 @@ func TestHandleCliCtx(t *testing.T) {
}
func TestGoroutinesDumpDisabling(t *testing.T) {
config := new(Config)
logger, _ := test.NewNullLogger()
config := NewConfig(logger)
config.level = logrus.DebugLevel
config.ReloadConfiguration()
config.ReloadConfiguration()
......
......@@ -11,20 +11,36 @@ import (
"github.com/sirupsen/logrus"
)
func watchForGoroutinesDump(stopCh chan bool) {
dumpStacks := make(chan os.Signal, 1)
func watchForGoroutinesDump(logger *logrus.Logger, stopCh chan bool) (chan bool, chan bool) {
dumpedCh := make(chan bool)
finishedCh := make(chan bool)
dumpStacksCh := make(chan os.Signal, 1)
// On USR1 dump stacks of all go routines
signal.Notify(dumpStacks, syscall.SIGUSR1)
for {
select {
case <-dumpStacks:
buf := make([]byte, 1<<20)
len := runtime.Stack(buf, true)
logrus.Printf("=== received SIGUSR1 ===\n*** goroutine dump...\n%s\n*** end\n", buf[0:len])
case <-stopCh:
return
signal.Notify(dumpStacksCh, syscall.SIGUSR1)
go func() {
for {
select {
case <-dumpStacksCh:
buf := make([]byte, 1<<20)
len := runtime.Stack(buf, true)
logger.Printf("=== received SIGUSR1 ===\n*** goroutine dump...\n%s\n*** end\n", buf[0:len])
nonBlockingSend(dumpedCh, true)
case <-stopCh:
close(finishedCh)
return
}
}
}()
return dumpedCh, finishedCh
}
func nonBlockingSend(ch chan bool, value bool) {
select {
case ch <- value:
default:
}
}
// +build darwin dragonfly freebsd linux netbsd openbsd
package log
import (
"os"
"syscall"
"testing"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestStackDumping(t *testing.T) {
logger, hook := test.NewNullLogger()
logger.SetFormatter(new(logrus.TextFormatter))
stopCh := make(chan bool)
dumpedCh, finishedCh := watchForGoroutinesDump(logger, stopCh)
require.NotNil(t, dumpedCh)
require.NotNil(t, finishedCh)
proc, err := os.FindProcess(os.Getpid())
require.NoError(t, err)
proc.Signal(syscall.SIGUSR1)
<-dumpedCh
logrusOutput, err := hook.LastEntry().String()
require.NoError(t, err)
assert.Contains(t, logrusOutput, "=== received SIGUSR1 ===")
assert.Contains(t, logrusOutput, "*** goroutine dump...")
close(stopCh)
<-finishedCh
}
package log
func watchForGoroutinesDump(stopCh chan bool) {
import (
"github.com/sirupsen/logrus"
)
func watchForGoroutinesDump(logger *logrus.Logger, stopCh chan bool) (chan bool, chan bool) {
return nil, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment