go.undefinedlabs.com/scopeagent@v0.4.2/instrumentation/testing/logger.go (about)

     1  package testing
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  	_ "unsafe"
     8  
     9  	"github.com/opentracing/opentracing-go/log"
    10  	"github.com/undefinedlabs/go-mpatch"
    11  
    12  	"go.undefinedlabs.com/scopeagent/instrumentation"
    13  	"go.undefinedlabs.com/scopeagent/tags"
    14  )
    15  
    16  var (
    17  	patchLock sync.Mutex
    18  
    19  	errorPatch  *mpatch.Patch
    20  	errorfPatch *mpatch.Patch
    21  	fatalPatch  *mpatch.Patch
    22  	fatalfPatch *mpatch.Patch
    23  	logPatch    *mpatch.Patch
    24  	logfPatch   *mpatch.Patch
    25  	skipPatch   *mpatch.Patch
    26  	skipfPatch  *mpatch.Patch
    27  )
    28  
    29  //go:linkname llog testing.(*common).log
    30  func llog(t *testing.T, s string)
    31  
    32  //go:linkname lError testing.(*common).Error
    33  func lError(t *testing.T, args ...interface{})
    34  
    35  //go:linkname lErrorf testing.(*common).Errorf
    36  func lErrorf(t *testing.T, format string, args ...interface{})
    37  
    38  //go:linkname lFatal testing.(*common).Fatal
    39  func lFatal(t *testing.T, args ...interface{})
    40  
    41  //go:linkname lFatalf testing.(*common).Fatalf
    42  func lFatalf(t *testing.T, format string, args ...interface{})
    43  
    44  //go:linkname lLog testing.(*common).Log
    45  func lLog(t *testing.T, args ...interface{})
    46  
    47  //go:linkname lLogf testing.(*common).Logf
    48  func lLogf(t *testing.T, format string, args ...interface{})
    49  
    50  //go:linkname lSkip testing.(*common).Skip
    51  func lSkip(t *testing.T, args ...interface{})
    52  
    53  //go:linkname lSkipf testing.(*common).Skipf
    54  func lSkipf(t *testing.T, format string, args ...interface{})
    55  
    56  func PatchTestingLogger() {
    57  	patchError()
    58  	patchErrorf()
    59  	patchFatal()
    60  	patchFatalf()
    61  	patchLog()
    62  	patchLogf()
    63  	patchSkip()
    64  	patchSkipf()
    65  }
    66  
    67  func UnpatchTestingLogger() {
    68  	patchLock.Lock()
    69  	defer patchLock.Unlock()
    70  
    71  	if errorPatch != nil {
    72  		logOnError(errorPatch.Unpatch())
    73  	}
    74  	if errorfPatch != nil {
    75  		logOnError(errorfPatch.Unpatch())
    76  	}
    77  	if fatalPatch != nil {
    78  		logOnError(fatalPatch.Unpatch())
    79  	}
    80  	if fatalfPatch != nil {
    81  		logOnError(fatalfPatch.Unpatch())
    82  	}
    83  	if logPatch != nil {
    84  		logOnError(logPatch.Unpatch())
    85  	}
    86  	if logfPatch != nil {
    87  		logOnError(logfPatch.Unpatch())
    88  	}
    89  	if skipPatch != nil {
    90  		logOnError(skipPatch.Unpatch())
    91  	}
    92  	if skipfPatch != nil {
    93  		logOnError(skipfPatch.Unpatch())
    94  	}
    95  }
    96  
    97  func patchError() {
    98  	patchWithArgs(&errorPatch, lError, func(test *Test, args ...interface{}) {
    99  		test.t.Helper()
   100  		s := fmt.Sprintln(args...)
   101  		if test.span != nil {
   102  			test.span.LogFields(
   103  				log.String(tags.EventType, tags.LogEvent),
   104  				log.String(tags.EventMessage, s),
   105  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   106  				log.String(tags.LogEventLevel, tags.LogLevel_ERROR),
   107  				log.String("log.internal_level", "Error"),
   108  				log.String("log.logger", "testing"),
   109  			)
   110  		}
   111  		llog(test.t, s)
   112  		test.t.Fail()
   113  	})
   114  }
   115  
   116  func patchErrorf() {
   117  	patchWithFormatAndArgs(&errorfPatch, lErrorf, func(test *Test, format string, args ...interface{}) {
   118  		test.t.Helper()
   119  		s := fmt.Sprintf(format, args...)
   120  		if test.span != nil {
   121  			test.span.LogFields(
   122  				log.String(tags.EventType, tags.LogEvent),
   123  				log.String(tags.EventMessage, s),
   124  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   125  				log.String(tags.LogEventLevel, tags.LogLevel_ERROR),
   126  				log.String("log.internal_level", "Error"),
   127  				log.String("log.logger", "testing"),
   128  			)
   129  		}
   130  		llog(test.t, s)
   131  		test.t.Fail()
   132  	})
   133  }
   134  
   135  func patchFatal() {
   136  	patchWithArgs(&fatalPatch, lFatal, func(test *Test, args ...interface{}) {
   137  		test.t.Helper()
   138  		s := fmt.Sprintln(args...)
   139  		if test.span != nil {
   140  			test.span.LogFields(
   141  				log.String(tags.EventType, tags.EventTestFailure),
   142  				log.String(tags.EventMessage, s),
   143  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   144  				log.String("log.internal_level", "Fatal"),
   145  				log.String("log.logger", "testing"),
   146  			)
   147  		}
   148  		llog(test.t, s)
   149  		test.t.FailNow()
   150  	})
   151  }
   152  
   153  func patchFatalf() {
   154  	patchWithFormatAndArgs(&fatalfPatch, lFatalf, func(test *Test, format string, args ...interface{}) {
   155  		test.t.Helper()
   156  		s := fmt.Sprintf(format, args...)
   157  		if test.span != nil {
   158  			test.span.LogFields(
   159  				log.String(tags.EventType, tags.EventTestFailure),
   160  				log.String(tags.EventMessage, s),
   161  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   162  				log.String("log.internal_level", "Fatal"),
   163  				log.String("log.logger", "testing"),
   164  			)
   165  		}
   166  		llog(test.t, s)
   167  		test.t.FailNow()
   168  	})
   169  }
   170  
   171  func patchLog() {
   172  	patchWithArgs(&logPatch, lLog, func(test *Test, args ...interface{}) {
   173  		test.t.Helper()
   174  		s := fmt.Sprintln(args...)
   175  		if test.span != nil {
   176  			test.span.LogFields(
   177  				log.String(tags.EventType, tags.LogEvent),
   178  				log.String(tags.EventMessage, s),
   179  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   180  				log.String(tags.LogEventLevel, tags.LogLevel_INFO),
   181  				log.String("log.internal_level", "Log"),
   182  				log.String("log.logger", "testing"),
   183  			)
   184  		}
   185  		llog(test.t, s)
   186  	})
   187  }
   188  
   189  func patchLogf() {
   190  	patchWithFormatAndArgs(&logfPatch, lLogf, func(test *Test, format string, args ...interface{}) {
   191  		test.t.Helper()
   192  		s := fmt.Sprintf(format, args...)
   193  		if test.span != nil {
   194  			test.span.LogFields(
   195  				log.String(tags.EventType, tags.LogEvent),
   196  				log.String(tags.EventMessage, s),
   197  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   198  				log.String(tags.LogEventLevel, tags.LogLevel_INFO),
   199  				log.String("log.internal_level", "Log"),
   200  				log.String("log.logger", "testing"),
   201  			)
   202  		}
   203  		llog(test.t, s)
   204  	})
   205  }
   206  
   207  func patchSkip() {
   208  	patchWithArgs(&skipPatch, lSkip, func(test *Test, args ...interface{}) {
   209  		test.t.Helper()
   210  		s := fmt.Sprintln(args...)
   211  		if test.span != nil {
   212  			test.span.LogFields(
   213  				log.String(tags.EventType, tags.EventTestSkip),
   214  				log.String(tags.EventMessage, s),
   215  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   216  				log.String("log.internal_level", "Skip"),
   217  				log.String("log.logger", "testing"),
   218  			)
   219  		}
   220  		llog(test.t, s)
   221  		test.t.SkipNow()
   222  	})
   223  }
   224  
   225  func patchSkipf() {
   226  	patchWithFormatAndArgs(&skipfPatch, lSkipf, func(test *Test, format string, args ...interface{}) {
   227  		test.t.Helper()
   228  		s := fmt.Sprintf(format, args...)
   229  		if test.span != nil {
   230  			test.span.LogFields(
   231  				log.String(tags.EventType, tags.EventTestSkip),
   232  				log.String(tags.EventMessage, s),
   233  				log.String(tags.EventSource, getSourceFileAndNumber(2)),
   234  				log.String("log.internal_level", "Skip"),
   235  				log.String("log.logger", "testing"),
   236  			)
   237  		}
   238  		llog(test.t, s)
   239  		test.t.SkipNow()
   240  	})
   241  }
   242  
   243  func patchWithArgs(patchValue **mpatch.Patch, method interface{}, methodBody func(test *Test, args ...interface{})) {
   244  	lPatch, err := mpatch.PatchMethod(method, func(t *testing.T, args ...interface{}) {
   245  		if t == nil {
   246  			instrumentation.Logger().Println("testing.T is nil")
   247  			return
   248  		}
   249  		t.Helper()
   250  		test := GetTest(t)
   251  		if test == nil {
   252  			instrumentation.Logger().Printf("test struct for %v doesn't exist\n", t.Name())
   253  			return
   254  		}
   255  		methodBody(test, args...)
   256  	})
   257  	logOnError(err)
   258  	*patchValue = lPatch
   259  }
   260  
   261  func patchWithFormatAndArgs(patchValue **mpatch.Patch, method interface{}, methodBody func(test *Test, format string, args ...interface{})) {
   262  	lPatch, err := mpatch.PatchMethod(method, func(t *testing.T, format string, args ...interface{}) {
   263  		if t == nil {
   264  			instrumentation.Logger().Println("testing.T is nil")
   265  			return
   266  		}
   267  		t.Helper()
   268  		test := GetTest(t)
   269  		if test == nil {
   270  			instrumentation.Logger().Printf("test struct for %v doesn't exist\n", t.Name())
   271  			return
   272  		}
   273  		methodBody(test, format, args...)
   274  	})
   275  	logOnError(err)
   276  	*patchValue = lPatch
   277  }
   278  
   279  func logOnError(err error) {
   280  	if err != nil {
   281  		instrumentation.Logger().Println(err)
   282  	}
   283  }