# Distributed Tracing Cross Agent Tests

The `distributed_tracing.json` file included here is our local copy of the
Better Better CAT CAT [tests](https://source.datanerd.us/agents/cross_agent_tests/pull/96/files).

The tests in json format and is a list of dictionaries, each dictionary
representing one test.

## Required fields

Each test will include these fields:

+ `test_name`: A string representing the test name.
+ `comment`: String; optional field. Describes the test.
+ `inbound_payloads`: List representing distributed trace payloads as described
  in the spec. AcceptDistributedTracePayload should be called with each payload
  in turn.
+ `account_id` String. The account_id to use for this test.
+ `transport_type` String. If the transport_type is 'HTTP', payloads will be
  generated via a request to a dummy WSGI server. Otherwise, they'll be
  generated manually.
+ `major_version`: Integer. The expected major version of the payload.
+ `minor_version`: Integer. The expected minor version of the payload.
+ `trusted_account_key`: String. The earliest ancestor trusted account id.
+ `force_sampled_true`: Boolean. Currently does nothing.
+ `expected_metrics`: List. Each list item itself is also a list of length two.
  The first item in the list is a metric name (unscoped). The second item is
  the expected number of occurrences of that metric. When a `null` is
  encountered, then the metric is expected to be absent.
+ `web_transaction`: Boolean. Whether the test should be run
  as a web transaction (as opposed to a background task).
+ `raises_exception`: Boolean, defaults to false. Whether the test should raise
  and record an exception (thus creating error traces, error events, etc).
+ `span_events_enabled`: Boolean. Whether span events are expected to be
  enabled for this test. (that is to say, whether span events are generated and
  validated or not)
+ `outbound_payloads`: List. For each item in the list, an outgoing request
  should be made during the distributed trace transaction. The list item itself
  is a dict, with the key, value pairs that should be asserted. Note that
  keys prepended with "d." are in the `data` portion of the outgoing payload.
+ `intrinsics`: Dictionary. Has a specific format, as described below.

## "Intrinsics" field attributes

+ `target_events`: List of strings. Each string represents an event type that
  will be generated by this test. Each string will also appear as a field in
  this `intrinsics` dict, with the same format as `common`.

+ `common`: A dict representing common attributes for all generated event
  types. The key/value pairs in `common` should be unioned with the values for
  each specific event type. Both `common` and the specific events will each
  have three subfields: `expected`, `unexpected`, and `exact`. The first two
  list of fields that should and should not, respectably, be present in the
  are event's attributes. `exact`, on the other hand, is a dict with key/value
  pairs describing what each attribute's exact value should be.

### Trace Context test details

The Trace Context test cases in `trace_context.json` are meant to be used to verify the
creation and forwarding of W3C Trace Context headers within the agent and the attributes
and metrics that get created during that process.

Each test case should correspond to a simulated inbound header or creation of a header in
the agent under test. Here's what the various fields in each test case mean:

| Name | Meaning |
| ---- | ------- |
| `name` | A human-meaningful name for the test case. |
| `trusted_account_key` | The account ids the agent can trust. |
| `account_id` | The account id the agent would receive on connect. |
| `web_transaction` | Whether the transaction that's tested is a web transaction or not. |
| `raises_exception` | Whether to simulate an exception happening within the transaction or not, resulting in a transaction error event. |
| `force_sampled_true` | Whether to force a transaction to be sampled or not. |
| `transport_type` | The transport type for the inbound request. |
| `inbound_headers` | The headers you should mock coming into the agent. |
| `outbound_payloads` | The exact/expected/unexpected values for outbound headers. |
| `intrinsics` | The exact/expected/unexpected attributes for events. |
| `expected_metrics` | The expected metrics and associated counts as a result of the test. |

The `outbound_payloads` and `intrinsics` field can have nested values, for example:
```javascript
...
    "intrinsics": {
       "target_events": ["Transaction", "Span"],
       "common":{
         "exact": {
           "traceId": "da8bc8cc6d062849b0efcf3c169afb5a"
         },
         "expected": ["guid"],
         "unexpected": ["grandparentId"]
       },
       "Transaction": {
         "exact": {
           "parent.type": "App",
           "parent.app": "2827902",
           "parent.account": "33",
           "parent.transportType": "HTTP",
           "parentId": "e8b91a159289ff74",
           "parentSpanId": "7d3efb1b173fecfa"
         },
         "expected": ["parent.transportDuration"]
       },
       "Span": {
         "exact": {
           "parentId": "7d3efb1b173fecfa",
           "trustedParentId": "7d3efb1b173fecfa",
           "tracingVendors": ""
         },
         "expected": ["transactionId"],
         "unexpected": ["parent.transportDuration", "parent.type", "parent.app", "parent.account", "parent.transportType"]
       }
     },
    ...
```

`target_events` is paired with the `common` block. So anything in the common block should be checked for any event type in the
`target_events` list. So for instance, this test should check that both the Transaction and Span events
have a `guid`, both have `da8bc8cc6d062849b0efcf3c169afb5a` as the `traceId`, and both don't have a `grandparentId` attribute.
The `Transaction` block means anything in there should only apply to the transaction object. Same for the `Span` block.

The same idea goes for the `outbound_payloads` block but will apply specifically for the outbound `traceparent` header and `tracestate` header.
