# Behavior scenarios (BDD)

Generated by grpc-dc codegen — do not edit.
Every scenario below is an executable example: the same table is stamped
as data into each language's `bdd_scenarios` file and interpreted by its
`TestBdd` suite against a loopback client and server, so this document
cannot drift from the behavior the tests enforce.

Given an Echo service (the reference implementation in each language's
examples) connected to a client over a loopback DataChannel:

## 1. A unary call echoes the message

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Unary with message "hello"
- **Then** the response is "echo: hello" with index 0

## 2. A unary call accepts an empty message

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Unary with message ""
- **Then** the response is "echo: " with index 0

## 3. The service rejects the message "fail"

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Unary with message "fail"
- **Then** the call fails with status code 3

## 4. Server streaming produces the requested number of responses

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ServerStream with message "tick" and count 3
- **Then** the responses are 3 copies of "tick" with indexes 0..2

## 5. Server streaming with count zero produces no responses

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ServerStream with message "zero" and count 0
- **Then** no responses are produced

## 6. Client streaming joins all messages into one response

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ClientStream with messages "a", "b", "c"
- **Then** the response is "a+b+c" with index 3

## 7. Client streaming accepts a single message

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ClientStream with messages "solo"
- **Then** the response is "solo" with index 1

## 8. Client streaming with no messages produces an empty response

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ClientStream with messages 
- **Then** the response is "" with index 0

## 9. Bidi streaming echoes each message in order

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Bidi with messages "x", "y"
- **Then** the responses echo "x", "y" in order with increasing indexes

## 10. Bidi streaming accepts a single message

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Bidi with messages "one"
- **Then** the responses echo "one" in order with increasing indexes

## 11. Call metadata reaches the service implementation

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Unary with message "hello" and metadata x-echo: "meta"
- **Then** the response is "echo: hello [meta]" with index 0

## 12. Response trailing metadata reaches the client

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Unary with message "hello" and metadata x-echo-trailer: "meta"; the service returns that marker in the x-echo-trailer response trailer
- **Then** the response is "echo: hello" with index 0

## 13. Unknown methods are rejected as UNIMPLEMENTED

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls the unknown method "/echo.Echo/Nope" with message "hello"
- **Then** the call fails with status code 12

## 14. Server streaming rejects the message "fail"

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ServerStream with message "fail" and count 3
- **Then** the call fails with status code 3

## 15. Bidi streaming rejects the message "fail"

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Bidi with messages "fail"
- **Then** the call fails with status code 3

## 16. A unary delayed past the client deadline fails

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls Unary with message "slow", which the service delays by 600 ms, under a shorter client deadline
- **Then** the call fails with status code 4

## 17. Cancelling a server stream terminates it

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ServerStream with message "tick" and count 5, reads one response, then cancels the call
- **Then** the stream terminates after the cancellation instead of delivering the remaining responses

## 18. Breaking a server stream stops the server

- **Given** the Echo service over a loopback DataChannel
- **When** the client calls ServerStream with message "tick" and count 100, reads one response, then abandons the stream without cancelling
- **Then** the server stops producing responses after the break instead of streaming all of them into the void

## Schema scenarios (protoc examples)

The same treatment for message schemas: golden bytes produced by
protoc itself over `webapp/testdata/kitchen.proto` and
`webapp/testdata/features.proto`, generated by grpc-dc codegen.
Each language decodes them with its generated message classes and
re-encodes; the result must be byte-identical.

### S1. Kitchen sink (every scalar, nested, maps, packed, oneof) round-trips protoc's bytes

- **Given** protoc's encoded `kitchen` bytes (224 bytes)
- **When** the generated classes decode and re-encode them
- **Then** the output is byte-identical to the expected 224 bytes

### S2. An empty Kitchen message encodes to zero bytes

- **Given** protoc's encoded `kitchen` bytes (0 bytes)
- **When** the generated classes decode and re-encode them
- **Then** the output is byte-identical to the expected 0 bytes

### S3. Three-level nesting with a nested enum and enum map round-trips protoc's bytes

- **Given** protoc's encoded `outer` bytes (37 bytes)
- **When** the generated classes decode and re-encode them
- **Then** the output is byte-identical to the expected 37 bytes

### S4. With both oneof variants on the wire, only the later (code) survives re-encoding

- **Given** protoc's encoded `kitchen` bytes (7 bytes)
- **When** the generated classes decode and re-encode them
- **Then** the output is byte-identical to the expected 3 bytes

### S5. An unknown field is captured on decode and re-emitted verbatim

- **Given** protoc's encoded `kitchen` bytes (6 bytes)
- **When** the generated classes decode and re-encode them
- **Then** the output is byte-identical to the expected 6 bytes

Run them per language with `make test-<lang>` (suite `TestBdd`), or all
of them with `make test`. In a real browser, `browser-test/bdd.test.mjs`
runs the same table in Chromium and Firefox against the Node WebRTC
stack, and `browser-test/bdd_wasm.test.mjs` pins every Wasm client to
the same generated table: every Wasm client — the native runtimes
(Rust, Dart, Zig, Lua, C++, Swift, Kotlin) and all six facades (Go,
Zig, C++, Swift, Kotlin, Scala.js) — also executes the failure,
metadata, unknown-method, cancellation, and deadline scenarios
inside the Wasm module itself.
