go.dedis.ch/onet/v3@v3.2.11-0.20210930124529-e36530bca7ef/tracing/trace_test.go (about)

     1  package tracing
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  	"testing"
     9  
    10  	"go.dedis.ch/onet/v3/log"
    11  
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestNewStackEntry(t *testing.T) {
    16  	for i, test := range []struct {
    17  		method string
    18  		file   string
    19  		se     stackEntry
    20  		err    bool
    21  	}{
    22  		{"runtime/debug.Stack(0x11953ba, 0x1089998, 0xad8eee637bfa)",
    23  			"/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/stack." +
    24  				"go:24 +0xab",
    25  			stackEntry{
    26  				24, "/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/",
    27  				"stack.go",
    28  				"runtime/debug", "Stack",
    29  				"(0x11953ba, 0x1089998, 0xad8eee637bfa)", "", false,
    30  			}, false,
    31  		}, {"go.dedis.ch/onet/v3/log.Stack(...)",
    32  			"/home/foo/onet/log/testutil.go:105",
    33  			stackEntry{
    34  				105, "/home/foo/onet/log/",
    35  				"testutil.go",
    36  				"go.dedis.ch/onet/v3/log", "Stack",
    37  				"(...)", "", false,
    38  			}, false,
    39  		}, {"go.dedis.ch/onet/v3/honeycomb.TestNewTrace(0xc0001b2200)",
    40  			"/home/foo/onet/honeycomb/trace_test.go:19",
    41  			stackEntry{
    42  				line: 19, path: "/home/foo/onet" +
    43  					"/honeycomb/", file: "trace_test.go",
    44  				pkgPath: "go.dedis.ch/onet/v3/honeycomb", method: "TestNewTrace",
    45  				params: "(0xc0001b2200)",
    46  			}, false,
    47  		}, {"testing.tRunner",
    48  			"/usr/local/Cellar/go/1.13.3/libexec/src/testing/testing.go:909 +0x19a",
    49  			stackEntry{
    50  				line: 909, path: "/usr/local/Cellar/go/1.13.3/libexec/src/testing/",
    51  				file:    "testing.go",
    52  				pkgPath: "testing", method: "tRunner", params: "",
    53  			}, false,
    54  		}, {"created by testing.(*T).Run",
    55  			"/usr/local/Cellar/go/1.13.3/libexec/src/testing/testing.go:960 +0x652",
    56  			stackEntry{
    57  				line: 960, path: "/usr/local/Cellar/go/1.13.3/libexec/src/testing/",
    58  				file:    "testing.go",
    59  				pkgPath: "testing.(*T)", method: "Run",
    60  				params: "", createdBy: true,
    61  			}, false,
    62  		},
    63  		{"created by testing.(*T).Run",
    64  			"/usr/local/Cellar/go/1.13.3/libexec/src/testing/testing.go:960 +0x652",
    65  			stackEntry{
    66  				line: 960, path: "/usr/local/Cellar/go/1.13.3/libexec/src/testing/",
    67  				file:    "testing.go",
    68  				pkgPath: "testing.(*T)", method: "Run", params: "",
    69  				createdBy: true,
    70  			}, false,
    71  		},
    72  		{"created by testing.(*T).Run",
    73  			"/usr/local/Cellar/go/1.13.3/libexec/src/testing/testing.go",
    74  			stackEntry{createdBy: true}, true,
    75  		},
    76  		{"created by testing",
    77  			"/usr/local/Cellar/go/1.13.3/libexec/src/testing/testing.go:960 +0x652",
    78  			stackEntry{createdBy: true}, true,
    79  		},
    80  		{
    81  			"go.dedis.ch/onet/v3/honeycomb.(*oneStr).more.(*another).one(" +
    82  				"0x58fe970, 0xc0001f0410, 0x14)",
    83  			"/home/foo/onet/honeycomb/stack_test.go:32 +0x34",
    84  			stackEntry{32, "/home/foo/onet/honeycomb/", "stack_test.go",
    85  				"go.dedis.ch/onet/v3/honeycomb.(*oneStr).more.(*another)",
    86  				"one", "(0x58fe970, 0xc0001f0410, 0x14)", "", false,
    87  			}, false,
    88  		},
    89  	} {
    90  		se, err := newStackEntry(test.method, test.file, "")
    91  		if test.err {
    92  			require.Error(t, err)
    93  		} else {
    94  			require.NoError(t, err)
    95  			require.Equal(t, test.se, se, fmt.Sprint("Failed for: ", i))
    96  		}
    97  	}
    98  }
    99  
   100  func TestParseLogs(t *testing.T) {
   101  	for _, test := range []struct {
   102  		logs string
   103  		ses  []stackEntry
   104  	}{
   105  		{
   106  			`runtime/debug.Stack(0x11953ba, 0x1009c10, 0xc00004ff18)
   107  			/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/stack.go:24 +0xab
   108  			go.dedis.ch/onet/v3/log.Stack(...)
   109  			/home/foo//onet/log/testutil.go:105`,
   110  			[]stackEntry{
   111  				{line: 105, path: "/home/foo//onet/log/",
   112  					file:    "testutil.go",
   113  					pkgPath: "go.dedis.ch/onet/v3/log", method: "Stack", params: "(...)"},
   114  				{line: 24, path: "/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/",
   115  					file:    "stack.go",
   116  					pkgPath: "runtime/debug", method: "Stack",
   117  					params: "(0x11953ba, 0x1009c10, 0xc00004ff18)"},
   118  			},
   119  		},
   120  		{
   121  			`runtime/debug.Stack(0x11953ba, 0x1009c10, 0xc00004ff18)
   122  			/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/stack.go:24 +0xab
   123  			/home/foo//onet/log/testutil.go:105`,
   124  			[]stackEntry{
   125  				{line: 24, path: "/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/",
   126  					file:    "stack.go",
   127  					pkgPath: "runtime/debug", method: "Stack",
   128  					params: "(0x11953ba, 0x1009c10, 0xc00004ff18)"},
   129  			},
   130  		},
   131  		{
   132  			`runtime/debug.Stack(0x11953ba, 0x1009c10, 0xc00004ff18)
   133  			/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/stack.go`,
   134  			nil,
   135  		},
   136  	} {
   137  		ses := parseLogs("goroutine t [test]\n"+test.logs, map[string]string{})
   138  		for s := range test.ses {
   139  			test.ses[s].traceID = "go_t"
   140  		}
   141  		require.Equal(t, test.ses, ses, fmt.Sprintf("logs: %s\nses: %+v",
   142  			test.logs, test.ses))
   143  	}
   144  }
   145  
   146  func simpleSe(path ...string) (ses []stackEntry) {
   147  	for _, p := range path {
   148  		ses = append(ses, stackEntry{method: p})
   149  	}
   150  	return
   151  }
   152  
   153  func TestNewStacked(t *testing.T) {
   154  	ctx, hcTr := newSimulTrace(context.TODO(), "")
   155  	tr, _ := newTraceWrapper(ctx, hcTr, simpleSe("root"))
   156  	stack1 := simpleSe("root", "one")
   157  	stack12 := simpleSe("root", "one", "two")
   158  	stack2 := simpleSe("root", "two")
   159  	stack23 := simpleSe("root", "two", "three")
   160  	stack234 := simpleSe("root", "two", "three", "four")
   161  	tr.stackToSpan(stack1).log(1, "one-1")
   162  	tr.stackToSpan(stack12).log(1, "one/two-1")
   163  	tr.stackToSpan(stack12).log(1, "one/two-2")
   164  	tr.stackToSpan(stack1).log(1, "one-2")
   165  	tr.stackToSpan(stack2).log(1, "two-1")
   166  	tr.stackToSpan(stack23).log(1, "two/three-1")
   167  	tr.stackToSpan(stack2).log(1, "two-2")
   168  	tr.stackToSpan(stack23).log(1, "two/three-2")
   169  	tr.stackToSpan(stack234).log(1, "two/three-2/four")
   170  	tr.stackToSpan(stack2).log(1, "two-3")
   171  	tr.send()
   172  	testSentTrace(t, tr,
   173  		`log.Lvl:1;log.Msg:"one-1";method:"one"`,
   174  		`log.Lvl:1;log.Msg:"one/two-1";method:"two"`,
   175  		`log.Lvl:1;log.Msg:"one/two-2";method:"two"`,
   176  		`method:"two"`,
   177  		`log.Lvl:1;log.Msg:"one-2";method:"one"`,
   178  		`log.Lvl:1;log.Msg:"two-1";method:"two"`,
   179  		`log.Lvl:1;log.Msg:"two/three-1";method:"three"`,
   180  		`method:"three"`,
   181  		`log.Lvl:1;log.Msg:"two-2";method:"two"`,
   182  		`log.Lvl:1;log.Msg:"two/three-2";method:"three"`,
   183  		`log.Lvl:1;log.Msg:"two/three-2/four";method:"four"`,
   184  		`method:"four"`,
   185  		`method:"three"`,
   186  		`log.Lvl:1;log.Msg:"two-3";method:"two"`,
   187  		`method:"two"`, `method:"root"`)
   188  }
   189  
   190  func TestTraceWrapper_Add(t *testing.T) {
   191  	skv := &storeKVs{}
   192  	for _, test := range []struct {
   193  		val interface{}
   194  		kv  map[string]string
   195  	}{
   196  		{1, map[string]string{"base": "1"}},
   197  		{ab{`"AA"`, 2},
   198  			map[string]string{"base.A": `"AA"`, "base.B": "2"}},
   199  		{struct {
   200  			C ab
   201  			D int
   202  		}{ab{"E", 3}, 2},
   203  			map[string]string{
   204  				"base.C.A": `"E"`,
   205  				"base.C.B": "3",
   206  				"base.D":   "2"}},
   207  		{struct{ D cab }{
   208  			cab{ab{"CAB", 3}}},
   209  			map[string]string{
   210  				"base.D.C.A": `"CAB"`,
   211  				"base.D.C.B": "3"}},
   212  	} {
   213  		skv.kvs = map[string]string{}
   214  		structToFields(skv.AddField, "base", test.val)
   215  		require.Equal(t, test.kv, skv.kvs)
   216  	}
   217  }
   218  
   219  type ab struct {
   220  	A string
   221  	B int
   222  }
   223  
   224  type cab struct {
   225  	C ab
   226  }
   227  
   228  func TestMerge(t *testing.T) {
   229  	for _, tms := range testMergeStack[1:] {
   230  		ctx, hcTr := newSimulTrace(context.TODO(), "")
   231  		ses := parseLogs(tms[1], map[string]string{})
   232  		known, _ := newTraceWrapper(ctx, hcTr, ses)
   233  		sesNew := known.findGoroutine(parseLogs(tms[0], map[string]string{}))
   234  		require.NotNil(t, sesNew)
   235  		require.NotEqual(t, 0, len(sesNew))
   236  		require.Equal(t, ses[0].traceID, sesNew[0].traceID)
   237  	}
   238  }
   239  
   240  var testMergeStack = [][]string{{`goroutine 2 [running]:
   241  go.dedis.ch/onet/v3/tracing.tg()
   242  /home/foo//onet/tracing/logger_test.go:116 +0x44
   243  created by go.dedis.ch/onet/v3/tracing.TestGor
   244  /home/foo//onet/tracing/logger_test.go:108 +0x68
   245  `, `goroutine 1 [runnable]:
   246  sync.(*WaitGroup).Wait(0xc0001ce070)
   247  /usr/local/Cellar/go/1.13.3/libexec/src/sync/waitgroup.go:103 +0x148
   248  go.dedis.ch/onet/v3/tracing.tg()
   249  /home/foo//onet/tracing/logger_test.go:136 +0x183
   250  created by go.dedis.ch/onet/v3/tracing.TestGor
   251  /home/foo//onet/tracing/logger_test.go:107 +0x50
   252  `},
   253  	{
   254  		`goroutine 2 [running]:
   255  runtime/debug.Stack(0x3, 0x3, 0xc00042dfb8)
   256  	/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/stack.go:24 +0xab
   257  go.dedis.ch/onet/v3/log.Stack(...)
   258  	/home/foo//onet/log/testutil.go:105
   259  go.dedis.ch/onet/v3/tracing.subgo(0xc000388410)
   260  	/home/foo//onet/tracing/logger_test.go:85 +0x87
   261  created by go.dedis.ch/onet/v3/tracing.goroutines
   262  	/home/foo//onet/tracing/logger_test.go:78 +0x209`,
   263  		`goroutine 1 [running]:
   264  runtime/debug.Stack(0x2, 0x3, 0xc0000c7f80)
   265  	/usr/local/Cellar/go/1.13.3/libexec/src/runtime/debug/stack.go:24 +0xab
   266  go.dedis.ch/onet/v3/log.Stack(...)
   267  	/home/foo//onet/log/testutil.go:105
   268  go.dedis.ch/onet/v3/tracing.goroutines(0x0)
   269  	/home/foo//onet/tracing/logger_test.go:74 +0xc7
   270  go.dedis.ch/onet/v3/tracing.TestGoroutines.func1(0xc0001e8620, 0x0)
   271  	/home/foo//onet/tracing/logger_test.go:56 +0x39
   272  created by go.dedis.ch/onet/v3/tracing.TestGoroutines
   273  	/home/foo//onet/tracing/logger_test.go:55 +0x1eb`,
   274  	}}
   275  
   276  func TestTraceID(t *testing.T) {
   277  	sc, tr := newSimulLogger()
   278  	defer log.UnregisterLogger(tr.loggerID)
   279  	if testing.Verbose() {
   280  		tr.PrintSingleSpans = 10
   281  		tr.Debug = true
   282  	}
   283  	tr.AddEntryPoints("go.dedis.ch/onet/v3/tracing.setTraceID")
   284  	tr.AddDoneMsgs("done trace")
   285  	syncTrace[0] = make(chan bool, 2)
   286  	syncTrace[1] = make(chan bool, 2)
   287  	setTraceID(0, "get")
   288  	setTraceID(1, "set")
   289  
   290  	setTraceID(0, "set")
   291  	setTraceID(1, "get")
   292  
   293  	setTraceID(0, "done")
   294  	setTraceID(1, "done")
   295  	sc.Wg.Wait()
   296  	sc.waitAndPrint()
   297  	require.Equal(t, 2, len(sc.Traces))
   298  }
   299  
   300  // used to make sure that the 'done' comes _after_ the get and set method
   301  var syncTrace [2]chan bool
   302  
   303  func setTraceID(id int, cmd string) {
   304  	log.TraceID([]byte{byte(id)})
   305  	log.Lvl2("adding traceID")
   306  	go traceCmd(id, cmd)
   307  }
   308  
   309  func traceCmd(id int, cmd string) {
   310  	log.TraceID([]byte{byte(id)})
   311  	log.Lvl2("cmd:", cmd)
   312  	if cmd == "done" {
   313  		<-syncTrace[id]
   314  		<-syncTrace[id]
   315  		log.Lvl2("done trace")
   316  	} else {
   317  		syncTrace[id] <- true
   318  	}
   319  }
   320  
   321  type storeKVs struct {
   322  	kvs map[string]string
   323  }
   324  
   325  func (s *storeKVs) AddField(key string, val interface{}) {
   326  	s.kvs[key] = valToJSON(val)
   327  }
   328  
   329  func testSentTrace(t *testing.T, tr *traceWrapper, exp ...string) {
   330  	testSent(t, tr.hcTrace.(*simulTrace).sent, exp...)
   331  }
   332  
   333  func testSent(t *testing.T, sent []map[string]string, exp ...string) {
   334  	var sentStr []string
   335  	for _, cl := range sent {
   336  		var keys []string
   337  		for k := range cl {
   338  			keys = append(keys, k)
   339  		}
   340  		sort.Strings(keys)
   341  		var s []string
   342  		for _, k := range keys {
   343  			s = append(s, fmt.Sprintf("%s:%s", k, strings.TrimSpace(cl[k])))
   344  		}
   345  		sentStr = append(sentStr, strings.Join(s, ";"))
   346  	}
   347  	sentNice := strings.Join(sentStr, "\n")
   348  	require.Equal(t, len(exp), len(sent), sentNice)
   349  	require.Equal(t, exp, sentStr, sentNice)
   350  }