# Fault Injection

The interesting bugs in printing code are not in the happy path. They are in what happens when the
paper runs out halfway through a receipt and the application reports success anyway.

Real hardware makes this awkward to stage: you have to physically open the cover, pull the roll, or
unplug the network at the right moment. Here it is an HTTP call, which means it can run on every
commit.

## Hardware faults

```bash
curl -sf -X PATCH "$VP_API/printers/$PRINTER_ID/operational-flags" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{"IsPaperOut": true}'
```

The flags available are `IsPaperOut`, `IsPaperNearEnd`, `IsCoverOpen`, `IsOffline` and `HasError`. Set
one, print, and assert on how your application reacts. Clear it by sending `false`.

What makes this more than a flag on a screen: **the printer answers status requests accordingly**. A
client that polls `DLE EOT n`, or reads Automatic Status Back, receives the status bytes a real printer
in that condition would send. If your application checks the printer before printing, this is what
exercises that code.

## Taking the listener down

The same endpoint sets `TargetState` to `Stopped` or `Started`. A stopped printer refuses connections
outright, which is how you test the reconnect path - a different failure from a printer that is
reachable but not ready.

## A slow printer

Real thermal printers have a small receive buffer and print slowly. A long receipt sent faster than the
printer prints it fills that buffer, and what happens next is exactly the case worth testing.

Enable buffer emulation on the printer, giving it a capacity and a drain rate. The buffer then fills as
bytes arrive and empties at the rate you set, and:

- a job that outruns the capacity is marked in the document with a **buffer overflow**, so a test can
  assert that the receipt did not survive intact;
- while the buffer holds data the printer reports itself **busy**, and reports **full** when it is at
  capacity, which is what a client polling the status sees;
- the buffered byte count is visible in the runtime status and on its live stream, so a test can watch
  it fill and drain.

## The cash drawer

```bash
curl -sf -X PATCH "$VP_API/printers/$PRINTER_ID/drawers" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{"Drawer1State": "Closed"}'
```

Drawer state is readable from the runtime status, and an ESC/POS pulse from your application opens the
emulated drawer - enough to assert that the till opens when it should, and stays shut when it should
not.

## A worked order

A test for "the paper runs out mid-receipt" usually looks like this:

1. Create the printer, print a normal receipt, assert it arrived.
2. Set `IsPaperOut`.
3. Print the next receipt.
4. Assert your application surfaced an alert, retried, or queued the order - whatever it is supposed to
   do - rather than reporting success.
5. Clear the flag and assert it recovers.

Step 4 is the one that finds real bugs.
