github.com/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrmicro/nrmicro_test.go (about)

     1  // Copyright 2020 New Relic Corporation. All rights reserved.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package nrmicro
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/micro/go-micro"
    14  	"github.com/micro/go-micro/broker"
    15  	bmemory "github.com/micro/go-micro/broker/memory"
    16  	"github.com/micro/go-micro/client"
    17  	"github.com/micro/go-micro/client/selector"
    18  	microerrors "github.com/micro/go-micro/errors"
    19  	"github.com/micro/go-micro/metadata"
    20  	rmemory "github.com/micro/go-micro/registry/memory"
    21  	"github.com/micro/go-micro/server"
    22  	newrelic "github.com/newrelic/go-agent"
    23  	proto "github.com/newrelic/go-agent/_integrations/nrmicro/example/proto"
    24  	"github.com/newrelic/go-agent/internal"
    25  	"github.com/newrelic/go-agent/internal/integrationsupport"
    26  )
    27  
    28  const (
    29  	missingHeaders  = "HEADERS NOT FOUND"
    30  	missingMetadata = "METADATA NOT FOUND"
    31  	serverName      = "testing"
    32  	topic           = "topic"
    33  )
    34  
    35  type TestRequest struct{}
    36  
    37  type TestResponse struct {
    38  	RequestHeaders string
    39  }
    40  
    41  func dtHeadersFound(hdr string) bool {
    42  	return hdr != "" && hdr != missingMetadata && hdr != missingHeaders
    43  }
    44  
    45  type TestHandler struct{}
    46  
    47  func (t *TestHandler) Method(ctx context.Context, req *TestRequest, rsp *TestResponse) error {
    48  	rsp.RequestHeaders = getDTRequestHeaderVal(ctx)
    49  	defer newrelic.StartSegment(newrelic.FromContext(ctx), "Method").End()
    50  	return nil
    51  }
    52  
    53  func (t *TestHandler) StreamingMethod(ctx context.Context, stream server.Stream) error {
    54  	if err := stream.Send(getDTRequestHeaderVal(ctx)); nil != err {
    55  		return err
    56  	}
    57  	return nil
    58  }
    59  
    60  type TestHandlerWithError struct{}
    61  
    62  func (t *TestHandlerWithError) Method(ctx context.Context, req *TestRequest, rsp *TestResponse) error {
    63  	rsp.RequestHeaders = getDTRequestHeaderVal(ctx)
    64  	return microerrors.Unauthorized("id", "format")
    65  }
    66  
    67  type TestHandlerWithNonMicroError struct{}
    68  
    69  func (t *TestHandlerWithNonMicroError) Method(ctx context.Context, req *TestRequest, rsp *TestResponse) error {
    70  	rsp.RequestHeaders = getDTRequestHeaderVal(ctx)
    71  	return errors.New("Non-Micro Error")
    72  }
    73  
    74  func getDTRequestHeaderVal(ctx context.Context) string {
    75  	if md, ok := metadata.FromContext(ctx); ok {
    76  		if dtHeader, ok := md[newrelic.DistributedTracePayloadHeader]; ok {
    77  			return dtHeader
    78  		}
    79  		return missingHeaders
    80  	}
    81  	return missingMetadata
    82  }
    83  
    84  func createTestApp() integrationsupport.ExpectApp {
    85  	return integrationsupport.NewTestApp(replyFn, cfgFn)
    86  }
    87  
    88  var replyFn = func(reply *internal.ConnectReply) {
    89  	reply.AdaptiveSampler = internal.SampleEverything{}
    90  	reply.AccountID = "123"
    91  	reply.TrustedAccountKey = "123"
    92  	reply.PrimaryAppID = "456"
    93  }
    94  
    95  var cfgFn = func(cfg *newrelic.Config) {
    96  	cfg.Enabled = false
    97  	cfg.DistributedTracer.Enabled = true
    98  	cfg.TransactionTracer.SegmentThreshold = 0
    99  	cfg.TransactionTracer.Threshold.IsApdexFailing = false
   100  	cfg.TransactionTracer.Threshold.Duration = 0
   101  	cfg.Attributes.Include = append(cfg.Attributes.Include,
   102  		newrelic.AttributeMessageRoutingKey,
   103  		newrelic.AttributeMessageQueueName,
   104  		newrelic.AttributeMessageExchangeType,
   105  		newrelic.AttributeMessageReplyTo,
   106  		newrelic.AttributeMessageCorrelationID,
   107  	)
   108  }
   109  
   110  func newTestWrappedClientAndServer(app newrelic.Application, wrapperOption client.Option, t *testing.T) (client.Client, server.Server) {
   111  	registry := rmemory.NewRegistry()
   112  	sel := selector.NewSelector(selector.Registry(registry))
   113  	c := client.NewClient(
   114  		client.Selector(sel),
   115  		wrapperOption,
   116  	)
   117  	s := server.NewServer(
   118  		server.Name(serverName),
   119  		server.Registry(registry),
   120  		server.WrapHandler(HandlerWrapper(app)),
   121  	)
   122  	s.Handle(s.NewHandler(new(TestHandler)))
   123  	s.Handle(s.NewHandler(new(TestHandlerWithError)))
   124  	s.Handle(s.NewHandler(new(TestHandlerWithNonMicroError)))
   125  
   126  	if err := s.Start(); nil != err {
   127  		t.Fatal(err)
   128  	}
   129  	return c, s
   130  }
   131  
   132  func TestClientCallWithNoTransaction(t *testing.T) {
   133  	c, s := newTestWrappedClientAndServer(createTestApp(), client.Wrap(ClientWrapper()), t)
   134  	defer s.Stop()
   135  	testClientCallWithNoTransaction(c, t)
   136  }
   137  
   138  func TestClientCallWrapperWithNoTransaction(t *testing.T) {
   139  	c, s := newTestWrappedClientAndServer(createTestApp(), client.WrapCall(CallWrapper()), t)
   140  	defer s.Stop()
   141  	testClientCallWithNoTransaction(c, t)
   142  }
   143  
   144  func testClientCallWithNoTransaction(c client.Client, t *testing.T) {
   145  
   146  	ctx := context.Background()
   147  	req := c.NewRequest(serverName, "TestHandler.Method", &TestRequest{}, client.WithContentType("application/json"))
   148  	rsp := TestResponse{}
   149  	if err := c.Call(ctx, req, &rsp); nil != err {
   150  		t.Fatal("Error calling test client:", err)
   151  	}
   152  	if rsp.RequestHeaders != missingHeaders {
   153  		t.Error("Header should not be here", rsp.RequestHeaders)
   154  	}
   155  }
   156  
   157  func TestClientCallWithTransaction(t *testing.T) {
   158  	c, s := newTestWrappedClientAndServer(createTestApp(), client.Wrap(ClientWrapper()), t)
   159  	defer s.Stop()
   160  	testClientCallWithTransaction(c, t)
   161  }
   162  
   163  func TestClientCallWrapperWithTransaction(t *testing.T) {
   164  	c, s := newTestWrappedClientAndServer(createTestApp(), client.WrapCall(CallWrapper()), t)
   165  	defer s.Stop()
   166  	testClientCallWithTransaction(c, t)
   167  }
   168  
   169  func testClientCallWithTransaction(c client.Client, t *testing.T) {
   170  
   171  	req := c.NewRequest(serverName, "TestHandler.Method", &TestRequest{}, client.WithContentType("application/json"))
   172  	rsp := TestResponse{}
   173  	app := createTestApp()
   174  	txn := app.StartTransaction("name", nil, nil)
   175  	ctx := newrelic.NewContext(context.Background(), txn)
   176  	if err := c.Call(ctx, req, &rsp); nil != err {
   177  		t.Fatal("Error calling test client:", err)
   178  	}
   179  	if !dtHeadersFound(rsp.RequestHeaders) {
   180  		t.Error("Incorrect header:", rsp.RequestHeaders)
   181  	}
   182  
   183  	txn.End()
   184  	app.ExpectMetrics(t, []internal.WantMetric{
   185  		{Name: "OtherTransaction/Go/name", Scope: "", Forced: true, Data: nil},
   186  		{Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil},
   187  		{Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   188  		{Name: "OtherTransactionTotalTime/Go/name", Scope: "", Forced: false, Data: nil},
   189  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   190  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil},
   191  		{Name: "External/all", Scope: "", Forced: true, Data: nil},
   192  		{Name: "External/allOther", Scope: "", Forced: true, Data: nil},
   193  		{Name: "External/testing/all", Scope: "", Forced: false, Data: nil},
   194  		{Name: "External/testing/Micro/TestHandler.Method", Scope: "OtherTransaction/Go/name", Forced: false, Data: nil},
   195  		{Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil},
   196  	})
   197  	app.ExpectSpanEvents(t, []internal.WantEvent{
   198  		{
   199  			Intrinsics: map[string]interface{}{
   200  				"category":      "generic",
   201  				"name":          "OtherTransaction/Go/name",
   202  				"nr.entryPoint": true,
   203  			},
   204  			UserAttributes:  map[string]interface{}{},
   205  			AgentAttributes: map[string]interface{}{},
   206  		},
   207  		{
   208  			Intrinsics: map[string]interface{}{
   209  				"category":  "http",
   210  				"component": "Micro",
   211  				"name":      "External/testing/Micro/TestHandler.Method",
   212  				"parentId":  internal.MatchAnything,
   213  				"span.kind": "client",
   214  			},
   215  			UserAttributes:  map[string]interface{}{},
   216  			AgentAttributes: map[string]interface{}{},
   217  		},
   218  	})
   219  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   220  		MetricName: "OtherTransaction/Go/name",
   221  		Root: internal.WantTraceSegment{
   222  			SegmentName: "ROOT",
   223  			Attributes:  map[string]interface{}{},
   224  			Children: []internal.WantTraceSegment{{
   225  				SegmentName: "OtherTransaction/Go/name",
   226  				Attributes:  map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything},
   227  				Children: []internal.WantTraceSegment{
   228  					{
   229  						SegmentName: "External/testing/Micro/TestHandler.Method",
   230  						Attributes:  map[string]interface{}{},
   231  					},
   232  				},
   233  			}},
   234  		},
   235  	}})
   236  }
   237  
   238  func TestClientCallMetadata(t *testing.T) {
   239  	c, s := newTestWrappedClientAndServer(createTestApp(), client.Wrap(ClientWrapper()), t)
   240  	defer s.Stop()
   241  	testClientCallMetadata(c, t)
   242  }
   243  
   244  func TestCallMetadata(t *testing.T) {
   245  	c, s := newTestWrappedClientAndServer(createTestApp(), client.WrapCall(CallWrapper()), t)
   246  	defer s.Stop()
   247  	testClientCallMetadata(c, t)
   248  }
   249  
   250  func testClientCallMetadata(c client.Client, t *testing.T) {
   251  	// test that context metadata is not changed by the newrelic wrapper
   252  	req := c.NewRequest(serverName, "TestHandler.Method", &TestRequest{}, client.WithContentType("application/json"))
   253  	rsp := TestResponse{}
   254  	app := createTestApp()
   255  	txn := app.StartTransaction("name", nil, nil)
   256  	ctx := newrelic.NewContext(context.Background(), txn)
   257  	md := metadata.Metadata{
   258  		"zip": "zap",
   259  	}
   260  	ctx = metadata.NewContext(ctx, md)
   261  	if err := c.Call(ctx, req, &rsp); nil != err {
   262  		t.Fatal("Error calling test client:", err)
   263  	}
   264  	if len(md) != 1 || md["zip"] != "zap" {
   265  		t.Error("metadata changed:", md)
   266  	}
   267  }
   268  
   269  func waitOrTimeout(t *testing.T, wg *sync.WaitGroup) {
   270  	ch := make(chan struct{})
   271  	go func() {
   272  		defer close(ch)
   273  		wg.Wait()
   274  	}()
   275  	select {
   276  	case <-ch:
   277  	case <-time.After(time.Second):
   278  		t.Fatal("timeout waiting for message")
   279  	}
   280  }
   281  
   282  func TestClientPublishWithNoTransaction(t *testing.T) {
   283  	c, _, b := newTestClientServerAndBroker(createTestApp(), t)
   284  
   285  	var wg sync.WaitGroup
   286  	if err := b.Connect(); nil != err {
   287  		t.Fatal("broker connect error:", err)
   288  	}
   289  	defer b.Disconnect()
   290  	if _, err := b.Subscribe(topic, func(e broker.Event) error {
   291  		defer wg.Done()
   292  		h := e.Message().Header
   293  		if _, ok := h[newrelic.DistributedTracePayloadHeader]; ok {
   294  			t.Error("Distributed tracing headers found", h)
   295  		}
   296  		return nil
   297  	}); nil != err {
   298  		t.Fatal("Failure to subscribe to broker:", err)
   299  	}
   300  
   301  	ctx := context.Background()
   302  	msg := c.NewMessage(topic, "hello world")
   303  	wg.Add(1)
   304  	if err := c.Publish(ctx, msg); nil != err {
   305  		t.Fatal("Error calling test client:", err)
   306  	}
   307  	waitOrTimeout(t, &wg)
   308  }
   309  
   310  func TestClientPublishWithTransaction(t *testing.T) {
   311  	c, _, b := newTestClientServerAndBroker(createTestApp(), t)
   312  
   313  	var wg sync.WaitGroup
   314  	if err := b.Connect(); nil != err {
   315  		t.Fatal("broker connect error:", err)
   316  	}
   317  	defer b.Disconnect()
   318  	if _, err := b.Subscribe(topic, func(e broker.Event) error {
   319  		defer wg.Done()
   320  		h := e.Message().Header
   321  		if _, ok := h[newrelic.DistributedTracePayloadHeader]; !ok {
   322  			t.Error("Distributed tracing headers not found", h)
   323  		}
   324  		return nil
   325  	}); nil != err {
   326  		t.Fatal("Failure to subscribe to broker:", err)
   327  	}
   328  
   329  	app := createTestApp()
   330  	txn := app.StartTransaction("name", nil, nil)
   331  	ctx := newrelic.NewContext(context.Background(), txn)
   332  	msg := c.NewMessage(topic, "hello world")
   333  	wg.Add(1)
   334  	if err := c.Publish(ctx, msg); nil != err {
   335  		t.Fatal("Error calling test client:", err)
   336  	}
   337  	waitOrTimeout(t, &wg)
   338  
   339  	txn.End()
   340  	app.ExpectMetrics(t, []internal.WantMetric{
   341  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   342  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil},
   343  		{Name: "MessageBroker/Micro/Topic/Produce/Named/topic", Scope: "", Forced: false, Data: nil},
   344  		{Name: "MessageBroker/Micro/Topic/Produce/Named/topic", Scope: "OtherTransaction/Go/name", Forced: false, Data: nil},
   345  		{Name: "OtherTransaction/Go/name", Scope: "", Forced: true, Data: nil},
   346  		{Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil},
   347  		{Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   348  		{Name: "OtherTransactionTotalTime/Go/name", Scope: "", Forced: false, Data: nil},
   349  		{Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil},
   350  	})
   351  	app.ExpectSpanEvents(t, []internal.WantEvent{
   352  		{
   353  			Intrinsics: map[string]interface{}{
   354  				"category":      "generic",
   355  				"name":          "OtherTransaction/Go/name",
   356  				"nr.entryPoint": true,
   357  			},
   358  			UserAttributes:  map[string]interface{}{},
   359  			AgentAttributes: map[string]interface{}{},
   360  		},
   361  		{
   362  			Intrinsics: map[string]interface{}{
   363  				"category": "generic",
   364  				"name":     "MessageBroker/Micro/Topic/Produce/Named/topic",
   365  				"parentId": internal.MatchAnything,
   366  			},
   367  			UserAttributes:  map[string]interface{}{},
   368  			AgentAttributes: map[string]interface{}{},
   369  		},
   370  	})
   371  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   372  		MetricName: "OtherTransaction/Go/name",
   373  		Root: internal.WantTraceSegment{
   374  			SegmentName: "ROOT",
   375  			Attributes:  map[string]interface{}{},
   376  			Children: []internal.WantTraceSegment{{
   377  				SegmentName: "OtherTransaction/Go/name",
   378  				Attributes:  map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything},
   379  				Children: []internal.WantTraceSegment{
   380  					{
   381  						SegmentName: "MessageBroker/Micro/Topic/Produce/Named/topic",
   382  						Attributes:  map[string]interface{}{},
   383  					},
   384  				},
   385  			}},
   386  		},
   387  	}})
   388  }
   389  
   390  func TestExtractHost(t *testing.T) {
   391  	testcases := []struct {
   392  		input  string
   393  		expect string
   394  	}{
   395  		{
   396  			input:  "192.168.0.10",
   397  			expect: "192.168.0.10",
   398  		},
   399  		{
   400  			input:  "192.168.0.10:1234",
   401  			expect: "192.168.0.10:1234",
   402  		},
   403  		{
   404  			input:  "unix:///path/to/file",
   405  			expect: "localhost",
   406  		},
   407  		{
   408  			input:  "nats://127.0.0.1:4222",
   409  			expect: "127.0.0.1:4222",
   410  		},
   411  		{
   412  			input:  "scheme://user:pass@host.com:5432/path?k=v#f",
   413  			expect: "host.com:5432",
   414  		},
   415  	}
   416  
   417  	for _, test := range testcases {
   418  		if actual := extractHost(test.input); actual != test.expect {
   419  			t.Errorf("incorrect host value extracted: actual=%s expected=%s", actual, test.expect)
   420  		}
   421  	}
   422  }
   423  
   424  func TestClientStreamWrapperWithNoTransaction(t *testing.T) {
   425  	c, s := newTestWrappedClientAndServer(createTestApp(), client.Wrap(ClientWrapper()), t)
   426  	defer s.Stop()
   427  
   428  	ctx := context.Background()
   429  	req := c.NewRequest(
   430  		serverName,
   431  		"TestHandler.StreamingMethod",
   432  		&TestRequest{},
   433  		client.WithContentType("application/json"),
   434  		client.StreamingRequest(),
   435  	)
   436  	stream, err := c.Stream(ctx, req)
   437  	defer stream.Close()
   438  	if nil != err {
   439  		t.Fatal("Error calling test client:", err)
   440  	}
   441  
   442  	var resp string
   443  	err = stream.Recv(&resp)
   444  	if nil != err {
   445  		t.Fatal(err)
   446  	}
   447  	if dtHeadersFound(resp) {
   448  		t.Error("dt headers found:", resp)
   449  	}
   450  
   451  	err = stream.Recv(&resp)
   452  	if nil == err {
   453  		t.Fatal("should have received EOF error from server")
   454  	}
   455  }
   456  
   457  func TestClientStreamWrapperWithTransaction(t *testing.T) {
   458  	c, s := newTestWrappedClientAndServer(createTestApp(), client.Wrap(ClientWrapper()), t)
   459  	defer s.Stop()
   460  
   461  	app := createTestApp()
   462  	txn := app.StartTransaction("name", nil, nil)
   463  	ctx := newrelic.NewContext(context.Background(), txn)
   464  	req := c.NewRequest(
   465  		serverName,
   466  		"TestHandler.StreamingMethod",
   467  		&TestRequest{},
   468  		client.WithContentType("application/json"),
   469  		client.StreamingRequest(),
   470  	)
   471  	stream, err := c.Stream(ctx, req)
   472  	defer stream.Close()
   473  	if nil != err {
   474  		t.Fatal("Error calling test client:", err)
   475  	}
   476  
   477  	var resp string
   478  	// second outgoing request to server, ensures we only create a single
   479  	// metric for the entire streaming cycle
   480  	if err := stream.Send(&resp); nil != err {
   481  		t.Fatal(err)
   482  	}
   483  
   484  	// receive the distributed trace headers from the server
   485  	if err := stream.Recv(&resp); nil != err {
   486  		t.Fatal(err)
   487  	}
   488  	if !dtHeadersFound(resp) {
   489  		t.Error("dt headers not found:", resp)
   490  	}
   491  
   492  	// exhaust the stream
   493  	if err := stream.Recv(&resp); nil == err {
   494  		t.Fatal("should have received EOF error from server")
   495  	}
   496  
   497  	txn.End()
   498  	app.ExpectMetrics(t, []internal.WantMetric{
   499  		{Name: "OtherTransaction/Go/name", Scope: "", Forced: true, Data: nil},
   500  		{Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil},
   501  		{Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   502  		{Name: "OtherTransactionTotalTime/Go/name", Scope: "", Forced: false, Data: nil},
   503  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   504  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil},
   505  		{Name: "External/all", Scope: "", Forced: true, Data: nil},
   506  		{Name: "External/allOther", Scope: "", Forced: true, Data: nil},
   507  		{Name: "External/testing/all", Scope: "", Forced: false, Data: nil},
   508  		{Name: "External/testing/Micro/TestHandler.StreamingMethod", Scope: "OtherTransaction/Go/name", Forced: false, Data: []float64{1}},
   509  		{Name: "Supportability/DistributedTrace/CreatePayload/Success", Scope: "", Forced: true, Data: nil},
   510  	})
   511  	app.ExpectSpanEvents(t, []internal.WantEvent{
   512  		{
   513  			Intrinsics: map[string]interface{}{
   514  				"category":      "generic",
   515  				"name":          "OtherTransaction/Go/name",
   516  				"nr.entryPoint": true,
   517  			},
   518  			UserAttributes:  map[string]interface{}{},
   519  			AgentAttributes: map[string]interface{}{},
   520  		},
   521  		{
   522  			Intrinsics: map[string]interface{}{
   523  				"category":  "http",
   524  				"component": "Micro",
   525  				"name":      "External/testing/Micro/TestHandler.StreamingMethod",
   526  				"parentId":  internal.MatchAnything,
   527  				"span.kind": "client",
   528  			},
   529  			UserAttributes:  map[string]interface{}{},
   530  			AgentAttributes: map[string]interface{}{},
   531  		},
   532  	})
   533  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   534  		MetricName: "OtherTransaction/Go/name",
   535  		Root: internal.WantTraceSegment{
   536  			SegmentName: "ROOT",
   537  			Attributes:  map[string]interface{}{},
   538  			Children: []internal.WantTraceSegment{{
   539  				SegmentName: "OtherTransaction/Go/name",
   540  				Attributes:  map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything},
   541  				Children: []internal.WantTraceSegment{
   542  					{
   543  						SegmentName: "External/testing/Micro/TestHandler.StreamingMethod",
   544  						Attributes:  map[string]interface{}{},
   545  					},
   546  				},
   547  			}},
   548  		},
   549  	}})
   550  }
   551  
   552  func TestServerWrapperWithNoApp(t *testing.T) {
   553  	c, s := newTestWrappedClientAndServer(nil, client.Wrap(ClientWrapper()), t)
   554  	defer s.Stop()
   555  	ctx := context.Background()
   556  	req := c.NewRequest(serverName, "TestHandler.Method", &TestRequest{}, client.WithContentType("application/json"))
   557  	rsp := TestResponse{}
   558  	if err := c.Call(ctx, req, &rsp); nil != err {
   559  		t.Fatal("Error calling test client:", err)
   560  	}
   561  	if rsp.RequestHeaders != missingHeaders {
   562  		t.Error("Header should not be here", rsp.RequestHeaders)
   563  	}
   564  }
   565  
   566  func TestServerWrapperWithApp(t *testing.T) {
   567  	app := createTestApp()
   568  	c, s := newTestWrappedClientAndServer(app, client.Wrap(ClientWrapper()), t)
   569  	defer s.Stop()
   570  	ctx := context.Background()
   571  	txn := app.StartTransaction("txn", nil, nil)
   572  	defer txn.End()
   573  	ctx = newrelic.NewContext(ctx, txn)
   574  	req := c.NewRequest(serverName, "TestHandler.Method", &TestRequest{}, client.WithContentType("application/json"))
   575  	rsp := TestResponse{}
   576  	if err := c.Call(ctx, req, &rsp); nil != err {
   577  		t.Fatal("Error calling test client:", err)
   578  	}
   579  	app.ExpectMetrics(t, []internal.WantMetric{
   580  		{Name: "DurationByCaller/App/123/456/HTTP/allWeb", Scope: "", Forced: false, Data: nil},
   581  		{Name: "TransportDuration/App/123/456/HTTP/allWeb", Scope: "", Forced: false, Data: nil},
   582  		{Name: "DurationByCaller/App/123/456/HTTP/all", Scope: "", Forced: false, Data: nil},
   583  		{Name: "TransportDuration/App/123/456/HTTP/all", Scope: "", Forced: false, Data: nil},
   584  		{Name: "Supportability/DistributedTrace/AcceptPayload/Success", Scope: "", Forced: true, Data: nil},
   585  		{Name: "Apdex", Scope: "", Forced: true, Data: nil},
   586  		{Name: "Apdex/Go/TestHandler.Method", Scope: "", Forced: false, Data: nil},
   587  		{Name: "HttpDispatcher", Scope: "", Forced: true, Data: nil},
   588  		{Name: "WebTransaction/Go/TestHandler.Method", Scope: "", Forced: true, Data: nil},
   589  		{Name: "WebTransaction", Scope: "", Forced: true, Data: nil},
   590  		{Name: "WebTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   591  		{Name: "WebTransactionTotalTime/Go/TestHandler.Method", Scope: "", Forced: false, Data: nil},
   592  		{Name: "Custom/Method", Scope: "", Forced: false, Data: nil},
   593  		{Name: "Custom/Method", Scope: "WebTransaction/Go/TestHandler.Method", Forced: false, Data: nil},
   594  	})
   595  	app.ExpectSpanEvents(t, []internal.WantEvent{
   596  		{
   597  			Intrinsics: map[string]interface{}{
   598  				"category":      "generic",
   599  				"name":          "WebTransaction/Go/TestHandler.Method",
   600  				"nr.entryPoint": true,
   601  				"parentId":      internal.MatchAnything,
   602  			},
   603  			UserAttributes:  map[string]interface{}{},
   604  			AgentAttributes: map[string]interface{}{},
   605  		},
   606  		{
   607  			Intrinsics: map[string]interface{}{
   608  				"category": "generic",
   609  				"name":     "Custom/Method",
   610  				"parentId": internal.MatchAnything,
   611  			},
   612  			UserAttributes:  map[string]interface{}{},
   613  			AgentAttributes: map[string]interface{}{},
   614  		},
   615  	})
   616  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   617  		MetricName: "WebTransaction/Go/TestHandler.Method",
   618  		Root: internal.WantTraceSegment{
   619  			SegmentName: "ROOT",
   620  			Attributes:  map[string]interface{}{},
   621  			Children: []internal.WantTraceSegment{{
   622  				SegmentName: "WebTransaction/Go/TestHandler.Method",
   623  				Attributes:  map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything},
   624  				Children: []internal.WantTraceSegment{
   625  					{
   626  						SegmentName: "Custom/Method",
   627  						Attributes:  map[string]interface{}{},
   628  					},
   629  				},
   630  			}},
   631  		},
   632  	}})
   633  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   634  		Intrinsics: map[string]interface{}{
   635  			"name":                     "WebTransaction/Go/TestHandler.Method",
   636  			"guid":                     internal.MatchAnything,
   637  			"priority":                 internal.MatchAnything,
   638  			"sampled":                  internal.MatchAnything,
   639  			"traceId":                  internal.MatchAnything,
   640  			"nr.apdexPerfZone":         "S",
   641  			"parent.account":           123,
   642  			"parent.transportType":     "HTTP",
   643  			"parent.app":               456,
   644  			"parentId":                 internal.MatchAnything,
   645  			"parent.type":              "App",
   646  			"parent.transportDuration": internal.MatchAnything,
   647  			"parentSpanId":             internal.MatchAnything,
   648  		},
   649  		UserAttributes: map[string]interface{}{},
   650  		AgentAttributes: map[string]interface{}{
   651  			"request.method":                "TestHandler.Method",
   652  			"request.uri":                   "micro://testing/TestHandler.Method",
   653  			"request.headers.accept":        "application/json",
   654  			"request.headers.contentType":   "application/json",
   655  			"request.headers.contentLength": 3,
   656  			"httpResponseCode":              "200",
   657  		},
   658  	}})
   659  }
   660  
   661  func TestServerWrapperWithAppReturnsError(t *testing.T) {
   662  	app := createTestApp()
   663  	c, s := newTestWrappedClientAndServer(app, client.Wrap(ClientWrapper()), t)
   664  	defer s.Stop()
   665  	ctx := context.Background()
   666  	req := c.NewRequest(serverName, "TestHandlerWithError.Method", &TestRequest{}, client.WithContentType("application/json"))
   667  	rsp := TestResponse{}
   668  	if err := c.Call(ctx, req, &rsp); nil == err {
   669  		t.Fatal("Expected an error but did not get one")
   670  	}
   671  	app.ExpectMetrics(t, []internal.WantMetric{
   672  		{Name: "Apdex/Go/TestHandlerWithError.Method", Scope: "", Forced: false, Data: nil},
   673  		{Name: "Errors/all", Scope: "", Forced: true, Data: nil},
   674  		{Name: "Errors/allWeb", Scope: "", Forced: true, Data: nil},
   675  		{Name: "Errors/WebTransaction/Go/TestHandlerWithError.Method", Scope: "", Forced: true, Data: nil},
   676  		{Name: "ErrorsByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   677  		{Name: "ErrorsByCaller/Unknown/Unknown/Unknown/Unknown/allWeb", Scope: "", Forced: false, Data: nil},
   678  		{Name: "WebTransaction/Go/TestHandlerWithError.Method", Scope: "", Forced: true, Data: nil},
   679  		{Name: "WebTransactionTotalTime/Go/TestHandlerWithError.Method", Scope: "", Forced: false, Data: nil},
   680  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   681  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allWeb", Scope: "", Forced: false, Data: nil},
   682  		{Name: "HttpDispatcher", Scope: "", Forced: true, Data: nil},
   683  		{Name: "WebTransaction", Scope: "", Forced: true, Data: nil},
   684  		{Name: "WebTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   685  		{Name: "Apdex", Scope: "", Forced: true, Data: nil},
   686  	})
   687  	app.ExpectSpanEvents(t, []internal.WantEvent{
   688  		{
   689  			Intrinsics: map[string]interface{}{
   690  				"category":      "generic",
   691  				"name":          "WebTransaction/Go/TestHandlerWithError.Method",
   692  				"nr.entryPoint": true,
   693  			},
   694  			UserAttributes:  map[string]interface{}{},
   695  			AgentAttributes: map[string]interface{}{},
   696  		},
   697  	})
   698  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   699  		MetricName: "WebTransaction/Go/TestHandlerWithError.Method",
   700  		Root: internal.WantTraceSegment{
   701  			SegmentName: "ROOT",
   702  			Attributes:  map[string]interface{}{},
   703  			Children: []internal.WantTraceSegment{{
   704  				SegmentName: "WebTransaction/Go/TestHandlerWithError.Method",
   705  				Attributes:  map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything},
   706  				Children:    []internal.WantTraceSegment{},
   707  			}},
   708  		},
   709  	}})
   710  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   711  		Intrinsics: map[string]interface{}{
   712  			"name":             "WebTransaction/Go/TestHandlerWithError.Method",
   713  			"guid":             internal.MatchAnything,
   714  			"priority":         internal.MatchAnything,
   715  			"sampled":          internal.MatchAnything,
   716  			"traceId":          internal.MatchAnything,
   717  			"nr.apdexPerfZone": internal.MatchAnything,
   718  		},
   719  		UserAttributes: map[string]interface{}{},
   720  		AgentAttributes: map[string]interface{}{
   721  			"request.method":                "TestHandlerWithError.Method",
   722  			"request.uri":                   "micro://testing/TestHandlerWithError.Method",
   723  			"request.headers.accept":        "application/json",
   724  			"request.headers.contentType":   "application/json",
   725  			"request.headers.contentLength": 3,
   726  			"httpResponseCode":              401,
   727  		},
   728  	}})
   729  	app.ExpectErrors(t, []internal.WantError{{
   730  		TxnName: "WebTransaction/Go/TestHandlerWithError.Method",
   731  		Msg:     "Unauthorized",
   732  		Klass:   "401",
   733  	}})
   734  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   735  		Intrinsics: map[string]interface{}{
   736  			"error.message":   "Unauthorized",
   737  			"error.class":     "401",
   738  			"transactionName": "WebTransaction/Go/TestHandlerWithError.Method",
   739  			"traceId":         internal.MatchAnything,
   740  			"priority":        internal.MatchAnything,
   741  			"guid":            internal.MatchAnything,
   742  			"sampled":         "true",
   743  		},
   744  	}})
   745  }
   746  
   747  func TestServerWrapperWithAppReturnsNonMicroError(t *testing.T) {
   748  	app := createTestApp()
   749  	c, s := newTestWrappedClientAndServer(app, client.Wrap(ClientWrapper()), t)
   750  	defer s.Stop()
   751  	ctx := context.Background()
   752  	req := c.NewRequest("testing", "TestHandlerWithNonMicroError.Method", &TestRequest{}, client.WithContentType("application/json"))
   753  	rsp := TestResponse{}
   754  	if err := c.Call(ctx, req, &rsp); nil == err {
   755  		t.Fatal("Expected an error but did not get one")
   756  	}
   757  	app.ExpectMetrics(t, []internal.WantMetric{
   758  		{Name: "Apdex/Go/TestHandlerWithNonMicroError.Method", Scope: "", Forced: false, Data: nil},
   759  		{Name: "Errors/all", Scope: "", Forced: true, Data: nil},
   760  		{Name: "Errors/allWeb", Scope: "", Forced: true, Data: nil},
   761  		{Name: "Errors/WebTransaction/Go/TestHandlerWithNonMicroError.Method", Scope: "", Forced: true, Data: nil},
   762  		{Name: "ErrorsByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   763  		{Name: "ErrorsByCaller/Unknown/Unknown/Unknown/Unknown/allWeb", Scope: "", Forced: false, Data: nil},
   764  		{Name: "WebTransaction/Go/TestHandlerWithNonMicroError.Method", Scope: "", Forced: true, Data: nil},
   765  		{Name: "WebTransactionTotalTime/Go/TestHandlerWithNonMicroError.Method", Scope: "", Forced: false, Data: nil},
   766  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   767  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allWeb", Scope: "", Forced: false, Data: nil},
   768  		{Name: "HttpDispatcher", Scope: "", Forced: true, Data: nil},
   769  		{Name: "WebTransaction", Scope: "", Forced: true, Data: nil},
   770  		{Name: "WebTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   771  		{Name: "Apdex", Scope: "", Forced: true, Data: nil},
   772  	})
   773  	app.ExpectTxnEvents(t, []internal.WantEvent{{
   774  		Intrinsics: map[string]interface{}{
   775  			"name":             "WebTransaction/Go/TestHandlerWithNonMicroError.Method",
   776  			"guid":             internal.MatchAnything,
   777  			"priority":         internal.MatchAnything,
   778  			"sampled":          internal.MatchAnything,
   779  			"traceId":          internal.MatchAnything,
   780  			"nr.apdexPerfZone": internal.MatchAnything,
   781  		},
   782  		UserAttributes: map[string]interface{}{},
   783  		AgentAttributes: map[string]interface{}{
   784  			"request.method":                "TestHandlerWithNonMicroError.Method",
   785  			"request.uri":                   "micro://testing/TestHandlerWithNonMicroError.Method",
   786  			"request.headers.accept":        "application/json",
   787  			"request.headers.contentType":   "application/json",
   788  			"request.headers.contentLength": 3,
   789  			"httpResponseCode":              500,
   790  		},
   791  	}})
   792  	app.ExpectErrors(t, []internal.WantError{{
   793  		TxnName: "WebTransaction/Go/TestHandlerWithNonMicroError.Method",
   794  		Msg:     "Internal Server Error",
   795  		Klass:   "500",
   796  	}})
   797  	app.ExpectErrorEvents(t, []internal.WantEvent{{
   798  		Intrinsics: map[string]interface{}{
   799  			"error.message":   "Internal Server Error",
   800  			"error.class":     "500",
   801  			"transactionName": "WebTransaction/Go/TestHandlerWithNonMicroError.Method",
   802  			"traceId":         internal.MatchAnything,
   803  			"priority":        internal.MatchAnything,
   804  			"guid":            internal.MatchAnything,
   805  			"sampled":         "true",
   806  		},
   807  	}})
   808  }
   809  
   810  func TestServerSubscribeNoApp(t *testing.T) {
   811  	c, s, b := newTestClientServerAndBroker(nil, t)
   812  	defer s.Stop()
   813  
   814  	var wg sync.WaitGroup
   815  	if err := b.Connect(); nil != err {
   816  		t.Fatal("broker connect error:", err)
   817  	}
   818  	defer b.Disconnect()
   819  	err := micro.RegisterSubscriber(topic, s, func(ctx context.Context, msg *proto.HelloRequest) error {
   820  		defer wg.Done()
   821  		return nil
   822  	})
   823  	if err != nil {
   824  		t.Fatal("error registering subscriber", err)
   825  	}
   826  	if err := s.Start(); nil != err {
   827  		t.Fatal(err)
   828  	}
   829  
   830  	ctx := context.Background()
   831  	msg := c.NewMessage(topic, &proto.HelloRequest{Name: "test"})
   832  	wg.Add(1)
   833  	if err := c.Publish(ctx, msg); nil != err {
   834  		t.Fatal("Error calling publish:", err)
   835  	}
   836  	waitOrTimeout(t, &wg)
   837  }
   838  
   839  func TestServerSubscribe(t *testing.T) {
   840  	app := createTestApp()
   841  	c, s, _ := newTestClientServerAndBroker(app, t)
   842  
   843  	var wg sync.WaitGroup
   844  	err := micro.RegisterSubscriber(topic, s, func(ctx context.Context, msg *proto.HelloRequest) error {
   845  		txn := newrelic.FromContext(ctx)
   846  		defer newrelic.StartSegment(txn, "segment").End()
   847  		defer wg.Done()
   848  		return nil
   849  	})
   850  	if err != nil {
   851  		t.Fatal("error registering subscriber", err)
   852  	}
   853  	if err := s.Start(); nil != err {
   854  		t.Fatal(err)
   855  	}
   856  
   857  	ctx := context.Background()
   858  	msg := c.NewMessage(topic, &proto.HelloRequest{Name: "test"})
   859  	wg.Add(1)
   860  	txn := app.StartTransaction("pub", nil, nil)
   861  	ctx = newrelic.NewContext(ctx, txn)
   862  	if err := c.Publish(ctx, msg); nil != err {
   863  		t.Fatal("Error calling publish:", err)
   864  	}
   865  	defer txn.End()
   866  	waitOrTimeout(t, &wg)
   867  	s.Stop()
   868  
   869  	app.ExpectMetrics(t, []internal.WantMetric{
   870  		{Name: "OtherTransaction/Go/Message/Micro/Topic/Named/topic", Scope: "", Forced: true, Data: nil},
   871  		{Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil},
   872  		{Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   873  		{Name: "OtherTransactionTotalTime/Go/Message/Micro/Topic/Named/topic", Scope: "", Forced: false, Data: nil},
   874  		{Name: "Custom/segment", Scope: "", Forced: false, Data: nil},
   875  		{Name: "Custom/segment", Scope: "OtherTransaction/Go/Message/Micro/Topic/Named/topic", Forced: false, Data: nil},
   876  		{Name: "TransportDuration/App/123/456/HTTP/allOther", Scope: "", Forced: false, Data: nil},
   877  		{Name: "Supportability/DistributedTrace/AcceptPayload/Success", Scope: "", Forced: true, Data: nil},
   878  		{Name: "DurationByCaller/App/123/456/HTTP/all", Scope: "", Forced: false, Data: nil},
   879  		{Name: "DurationByCaller/App/123/456/HTTP/allOther", Scope: "", Forced: false, Data: nil},
   880  		{Name: "TransportDuration/App/123/456/HTTP/all", Scope: "", Forced: false, Data: nil},
   881  	})
   882  	app.ExpectSpanEvents(t, []internal.WantEvent{
   883  		{
   884  			Intrinsics: map[string]interface{}{
   885  				"category":      "generic",
   886  				"name":          "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
   887  				"nr.entryPoint": true,
   888  				"parentId":      internal.MatchAnything,
   889  			},
   890  			UserAttributes:  map[string]interface{}{},
   891  			AgentAttributes: map[string]interface{}{},
   892  		},
   893  		{
   894  			Intrinsics: map[string]interface{}{
   895  				"category": "generic",
   896  				"name":     "Custom/segment",
   897  				"parentId": internal.MatchAnything,
   898  			},
   899  			UserAttributes:  map[string]interface{}{},
   900  			AgentAttributes: map[string]interface{}{},
   901  		},
   902  	})
   903  	app.ExpectTxnEvents(t, []internal.WantEvent{
   904  		{
   905  			Intrinsics: map[string]interface{}{
   906  				"guid":                     internal.MatchAnything,
   907  				"name":                     "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
   908  				"parent.account":           123,
   909  				"parent.app":               456,
   910  				"parent.transportDuration": internal.MatchAnything,
   911  				"parent.transportType":     "HTTP",
   912  				"parent.type":              "App",
   913  				"parentId":                 internal.MatchAnything,
   914  				"parentSpanId":             internal.MatchAnything,
   915  				"priority":                 internal.MatchAnything,
   916  				"sampled":                  internal.MatchAnything,
   917  				"traceId":                  internal.MatchAnything,
   918  			},
   919  			AgentAttributes: map[string]interface{}{
   920  				"message.routingKey": "topic",
   921  			},
   922  			UserAttributes: map[string]interface{}{},
   923  		},
   924  	})
   925  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   926  		MetricName: "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
   927  		Root: internal.WantTraceSegment{
   928  			SegmentName: "ROOT",
   929  			Attributes:  map[string]interface{}{},
   930  			Children: []internal.WantTraceSegment{{
   931  				SegmentName: "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
   932  				Attributes:  map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything},
   933  				Children: []internal.WantTraceSegment{{
   934  					SegmentName: "Custom/segment",
   935  					Attributes:  map[string]interface{}{},
   936  					Children:    []internal.WantTraceSegment{}},
   937  				},
   938  			}},
   939  		},
   940  	}})
   941  }
   942  
   943  func TestServerSubscribeWithError(t *testing.T) {
   944  	app := createTestApp()
   945  	c, s, _ := newTestClientServerAndBroker(app, t)
   946  
   947  	var wg sync.WaitGroup
   948  	err := micro.RegisterSubscriber(topic, s, func(ctx context.Context, msg *proto.HelloRequest) error {
   949  		defer wg.Done()
   950  		return errors.New("subscriber error")
   951  	})
   952  	if err != nil {
   953  		t.Fatal("error registering subscriber", err)
   954  	}
   955  	if err := s.Start(); nil != err {
   956  		t.Fatal(err)
   957  	}
   958  
   959  	ctx := context.Background()
   960  	msg := c.NewMessage(topic, &proto.HelloRequest{Name: "test"})
   961  	wg.Add(1)
   962  	if err := c.Publish(ctx, msg); nil == err {
   963  		t.Fatal("Expected error but didn't get one")
   964  	}
   965  	waitOrTimeout(t, &wg)
   966  	s.Stop()
   967  
   968  	app.ExpectMetrics(t, []internal.WantMetric{
   969  		{Name: "OtherTransaction/Go/Message/Micro/Topic/Named/topic", Scope: "", Forced: true, Data: nil},
   970  		{Name: "OtherTransaction/all", Scope: "", Forced: true, Data: nil},
   971  		{Name: "OtherTransactionTotalTime", Scope: "", Forced: true, Data: nil},
   972  		{Name: "OtherTransactionTotalTime/Go/Message/Micro/Topic/Named/topic", Scope: "", Forced: false, Data: nil},
   973  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   974  		{Name: "DurationByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil},
   975  		{Name: "Errors/all", Scope: "", Forced: true, Data: nil},
   976  		{Name: "Errors/allOther", Scope: "", Forced: true, Data: nil},
   977  		{Name: "ErrorsByCaller/Unknown/Unknown/Unknown/Unknown/all", Scope: "", Forced: false, Data: nil},
   978  		{Name: "ErrorsByCaller/Unknown/Unknown/Unknown/Unknown/allOther", Scope: "", Forced: false, Data: nil},
   979  		{Name: "Errors/OtherTransaction/Go/Message/Micro/Topic/Named/topic", Scope: "", Forced: true, Data: nil},
   980  	})
   981  	app.ExpectSpanEvents(t, []internal.WantEvent{
   982  		{
   983  			Intrinsics: map[string]interface{}{
   984  				"category":      "generic",
   985  				"name":          "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
   986  				"nr.entryPoint": true,
   987  			},
   988  			UserAttributes:  map[string]interface{}{},
   989  			AgentAttributes: map[string]interface{}{},
   990  		},
   991  	})
   992  	app.ExpectTxnTraces(t, []internal.WantTxnTrace{{
   993  		MetricName: "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
   994  		Root: internal.WantTraceSegment{
   995  			SegmentName: "ROOT",
   996  			Attributes:  map[string]interface{}{},
   997  			Children: []internal.WantTraceSegment{{
   998  				SegmentName: "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
   999  				Attributes:  map[string]interface{}{"exclusive_duration_millis": internal.MatchAnything},
  1000  				Children:    []internal.WantTraceSegment{},
  1001  			}},
  1002  		},
  1003  	}})
  1004  	app.ExpectErrors(t, []internal.WantError{{
  1005  		TxnName: "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
  1006  		Msg:     "subscriber error",
  1007  		Klass:   "*errors.errorString",
  1008  	}})
  1009  	app.ExpectErrorEvents(t, []internal.WantEvent{{
  1010  		Intrinsics: map[string]interface{}{
  1011  			"error.message":   "subscriber error",
  1012  			"error.class":     "*errors.errorString",
  1013  			"transactionName": "OtherTransaction/Go/Message/Micro/Topic/Named/topic",
  1014  			"traceId":         internal.MatchAnything,
  1015  			"priority":        internal.MatchAnything,
  1016  			"guid":            internal.MatchAnything,
  1017  			"sampled":         "true",
  1018  		},
  1019  	}})
  1020  }
  1021  
  1022  func newTestClientServerAndBroker(app newrelic.Application, t *testing.T) (client.Client, server.Server, broker.Broker) {
  1023  	b := bmemory.NewBroker()
  1024  	c := client.NewClient(
  1025  		client.Broker(b),
  1026  		client.Wrap(ClientWrapper()),
  1027  	)
  1028  	s := server.NewServer(
  1029  		server.Name(serverName),
  1030  		server.Broker(b),
  1031  		server.WrapSubscriber(SubscriberWrapper(app)),
  1032  	)
  1033  	return c, s, b
  1034  }