github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/pkg/log/configure_test.go (about)

     1  package log_test
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"os"
     7  	"sync"
     8  	"testing"
     9  
    10  	"github.com/kyma-incubator/compass/components/director/pkg/log"
    11  	"github.com/sirupsen/logrus"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  // TestMultipleGoroutinesDefaultLog validates that no race conditions occur when two go routines log using the default log
    16  func TestMultipleGoroutinesDefaultLog(t *testing.T) {
    17  	_, err := log.Configure(context.TODO(), log.DefaultConfig())
    18  	require.NoError(t, err)
    19  	wg := sync.WaitGroup{}
    20  	wg.Add(2)
    21  	go func() {
    22  		defer wg.Done()
    23  		log.D().Debug("message")
    24  	}()
    25  	go func() {
    26  		defer wg.Done()
    27  		log.D().Debug("message")
    28  	}()
    29  	wg.Wait()
    30  }
    31  
    32  // TestMultipleGoroutinesContextLog validates that no race conditions occur when two go routines log using the context log
    33  func TestMultipleGoroutinesContextLog(t *testing.T) {
    34  	ctx, err := log.Configure(context.TODO(), log.DefaultConfig())
    35  	require.NoError(t, err)
    36  	wg := sync.WaitGroup{}
    37  	wg.Add(2)
    38  	go func() {
    39  		defer wg.Done()
    40  		log.C(ctx).Debug("message")
    41  	}()
    42  	go func() {
    43  		defer wg.Done()
    44  		log.C(ctx).Debug("message")
    45  	}()
    46  	wg.Wait()
    47  }
    48  
    49  // TestMultipleGoroutinesMixedLog validates that no race conditions occur when two go routines log using both context and default log
    50  func TestMultipleGoroutinesMixedLog(t *testing.T) {
    51  	ctx, err := log.Configure(context.TODO(), log.DefaultConfig())
    52  	require.NoError(t, err)
    53  	wg := sync.WaitGroup{}
    54  	wg.Add(2)
    55  	go func() {
    56  		defer wg.Done()
    57  		log.C(ctx).Debug("message")
    58  	}()
    59  	go func() {
    60  		defer wg.Done()
    61  		log.D().Debug("message")
    62  	}()
    63  	wg.Wait()
    64  }
    65  
    66  func TestConfigureReturnsErrorWhenConfigIsInvalid(t *testing.T) {
    67  	var tests = []struct {
    68  		Msg            string
    69  		ConfigProvider func() *log.Config
    70  	}{
    71  		{
    72  			Msg: "Invalid log level",
    73  			ConfigProvider: func() *log.Config {
    74  				config := log.DefaultConfig()
    75  				config.Level = "invalid"
    76  				return config
    77  			},
    78  		},
    79  		{
    80  			Msg: "Missing Log Format",
    81  			ConfigProvider: func() *log.Config {
    82  				config := log.DefaultConfig()
    83  				config.Format = ""
    84  				return config
    85  			},
    86  		},
    87  		{
    88  			Msg: "Unsupported log format",
    89  			ConfigProvider: func() *log.Config {
    90  				config := log.DefaultConfig()
    91  				config.Format = "invalid"
    92  				return config
    93  			},
    94  		},
    95  		{
    96  			Msg: "Missing Output",
    97  			ConfigProvider: func() *log.Config {
    98  				config := log.DefaultConfig()
    99  				config.Output = ""
   100  				return config
   101  			},
   102  		},
   103  		{
   104  			Msg: "Unsupported output",
   105  			ConfigProvider: func() *log.Config {
   106  				config := log.DefaultConfig()
   107  				config.Output = "invalid"
   108  				return config
   109  			},
   110  		},
   111  		{
   112  			Msg: "Missing Bootstrap Correlation ID",
   113  			ConfigProvider: func() *log.Config {
   114  				config := log.DefaultConfig()
   115  				config.BootstrapCorrelationID = ""
   116  				return config
   117  			},
   118  		},
   119  	}
   120  
   121  	for _, test := range tests {
   122  		t.Run(test.Msg, func(t *testing.T) {
   123  			previousConfig := log.Configuration()
   124  			_, err := log.Configure(context.TODO(), test.ConfigProvider())
   125  			require.Error(t, err)
   126  			currentConfig := log.Configuration()
   127  			require.Equal(t, previousConfig, currentConfig)
   128  		})
   129  	}
   130  }
   131  
   132  func TestDefaultLoggerConfiguration(t *testing.T) {
   133  	config := log.DefaultConfig()
   134  	config.Level = "trace"
   135  	ctx, err := log.Configure(context.TODO(), config)
   136  	require.NoError(t, err)
   137  	require.Equal(t, log.C(ctx).Level, log.D().Level)
   138  }
   139  
   140  func TestConfigureFormat(t *testing.T) {
   141  	var tests = []struct {
   142  		Msg            string
   143  		ConfigProvider func() *log.Config
   144  		ExpectedOutput []string
   145  	}{
   146  		{
   147  			Msg: "text",
   148  			ConfigProvider: func() *log.Config {
   149  				config := log.DefaultConfig()
   150  				config.Format = "text"
   151  				return config
   152  			},
   153  			ExpectedOutput: []string{"msg=Test"},
   154  		},
   155  		{
   156  			Msg: "json",
   157  			ConfigProvider: func() *log.Config {
   158  				config := log.DefaultConfig()
   159  				config.Format = "json"
   160  				return config
   161  			},
   162  			ExpectedOutput: []string{"\"msg\":\"Test\""},
   163  		},
   164  	}
   165  
   166  	for _, test := range tests {
   167  		t.Run(test.Msg, func(t *testing.T) {
   168  			w := &bytes.Buffer{}
   169  			ctx, err := log.Configure(context.TODO(), test.ConfigProvider())
   170  			require.NoError(t, err)
   171  			entry := log.LoggerFromContext(ctx)
   172  			entry.Logger.SetOutput(w)
   173  			defer entry.Logger.SetOutput(os.Stderr) // return default output
   174  			entry.Info("Test")
   175  			for _, out := range test.ExpectedOutput {
   176  				require.Contains(t, w.String(), out)
   177  			}
   178  		})
   179  	}
   180  }
   181  
   182  func TestRegisterFormatterAddsItIfNotExists(t *testing.T) {
   183  	name := "formatter_name"
   184  	err := log.RegisterFormatter(name, &logrus.TextFormatter{})
   185  	require.NoError(t, err)
   186  
   187  	config := log.DefaultConfig()
   188  	config.Format = name
   189  	_, err = log.Configure(context.TODO(), config)
   190  	require.NoError(t, err)
   191  }
   192  
   193  func TestRegisterFormatterReturnsErrorForAlreadyExistingFormat(t *testing.T) {
   194  	name := "text"
   195  	err := log.RegisterFormatter(name, &logrus.TextFormatter{})
   196  	require.Error(t, err)
   197  }
   198  
   199  func TestConfigureWillReconfigureDefaultLoggerEvenIfEntryAlreadyExistsInTheContext(t *testing.T) {
   200  	config := log.DefaultConfig()
   201  	ctx, err := log.Configure(context.TODO(), config)
   202  	require.NoError(t, err)
   203  
   204  	config.Level = "trace"
   205  	ctx, err = log.Configure(ctx, config)
   206  	require.NoError(t, err)
   207  
   208  	require.Equal(t, log.C(ctx).Level, log.D().Level)
   209  }