Skip to content
Go back

On DST

DRAFT
Published: May 10, 2025
Punta Cana, Dominican Republic

Let’s start with a new mental model, one called deterministic simulation testing (DST) which was largely defined by FoundationDB which inspired Antithesis

According to Antithesis driven testing:

There are 5 different kinds of asserts currently available:

  1. AssertAlways: assert that a given condition is true every time the assertion is encountered and that it is encountered at least once.
  2. AssertAlwaysOrUnreachable: assert that a given condition is true every time the assertion is encountered or that the assertion is never encountered.
  3. AssertSometimes: assert that a given condition is true in at least one timeline. This property is so powerful there is an entire doc about it.
  4. AssertReachable: this line of code must be encountered in at least one timeline.
  5. AssertUnreachable: this line of code is never encountered in any timeline.

According to Assertion functionality (Fallback SDK):

  1. Always: asserts that a given condition is true every time the assertion is encountered and that it is encountered at least once
  2. AlwaysOrUnreachable: asserts that some condition is true every time it is encountered
  3. Sometimes: asserts that a given state is encountered at some point across the entire testing session
  4. Reachable: asserts that a given line of code is encountered at some point across the entire testing session
  5. Unreachable: asserts that a given line of code is never encountered across the entire testing session

To get a better understanding of their assertion schema, here is their complete JSON schema below:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$id": "https://antithesis.com/assertions.schema.json",
  "title": "Antithesis Assertions",
  "description": "This describes the details of an Antithesis assertion",
  "type": "object",
  "properties": {
    "antithesis_assert": {
      "description": "Asserts a specific condition value and reachability",
      "type": "object",
      "properties": {
        "id": {
          "description": "A unique identifier for an assertion",
          "type": "string"
        },
        "message": {
          "description": "Description of the assertion",
          "type": "string"
        },
        "condition": {
          "description": "Evaluation of execution state and location",
          "type": "boolean"
        },
        "display_type": {
          "description": "User-supplied name of the assertion type, for use in reports.",
          "type": "string"
        },
        "hit": {
          "description": "Indicates the assertion was evaluated",
          "type": "boolean"
        },
        "must_hit": {
          "description": "True if the assertion is expected to be evaluated at least once to consider it to be passed",
          "type": "boolean"
        },
        "assert_type": {
          "description": "Type of assertion that was established",
          "type": "string",
          "enum": [ 
            "always",
            "sometimes",
            "reachability"
          ]
        },
        "location": {
          "description": "Describes physical and logical source code location",
          "type": "object",
          "properties": {
            "file": {
              "description": "Filename containing the assertion",
              "type": "string"
            },
            "function": {
              "description": "Function or method containing the assertion",
              "type": "string"
            },
            "class": {
              "description": "Class or package for the code containing the assertion",
              "type": "string"
            },
            "begin_line": {
              "description": "Line number for the assertion",
              "type": "number"
            },
            "begin_column": {
              "description": "Column number for the assertion",
              "type": "number"
            }
          }
        },
        "details": {
          "description": "User-provided JSON, for display in reports as additional details. If no additional details are desired, set as null.",
          "type": "object",
          "patternProperties": {
            "^.*$": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "boolean"
                },
                {
                  "type": "object"
                },
                {
                  "type": "array"
                },
                {
                  "type": "null"
                }
              ]
            }
          },
          "additionalProperties": false
        }
      }
    }
  }
}
(This example is complete, it can be run "as is")

Wait but why?

According to Carl Sverre’s Antithesis driven testing:

A testing pattern that can give me confidence that I won’t be woken up at 3 AM for a production outage or discover I’ve silently been losing data

What are the best DST programming languages?

  1. Swift (Successor to C++)
  2. Zig (Successor to C)

Let’s look at Swift first

Swift: Successor to C++?

Konrad Malawski at FoundationDB, which was acquired by Apple, gave an interesting talk called Swift as C++ Successor in FoundationDB

FoundationDB’s Existing DST

FDB heavily relies on a powerful simulation testing (aka DST) runtime that can run millions of tests, inject failures, reorder messages, and inject delays

Crucially, this system allows for the exact reproduction of any issue found, which is vital for debugging complex distributed systems

This was originally made possible by a custom C++ dialect called ‘Flow,’ which had hooks to allow the simulation runtime to control execution. Flow code is source-generated into C++ with state machines representing jobs submitted to an event loop.

Swift’s Integration Challenge

When adopting Swift, a key requirement was to preserve this invaluable DST capability. The goal was to allow Swift code to be tested within the same deterministic simulation framework.

How Swift Achieved Integration

Swift’s modern concurrency model (async/await, tasks, jobs) is designed with extensibility in mind. Malawski states, ‘Swift is actually quite similar to that [Flow’s job submission model] because we have tasks and jobs which… we have a hook for that we have overridden’.

Instead of Swift tasks running on Swift’s default concurrency pool, the hook was used to redirect them. Swift tasks and jobs are wrapped into a type that FDB’s existing event loop already understands.

When the FDB event loop (either the simulation one or the production one) picks up one of these Swift-originated jobs, it then calls ‘Swift run on the job’. This means the FDB simulation runtime can apply its usual deterministic controls (delays, reordering, etc.) to the execution of Swift code.

Malawski notes, ‘the integration here was fairly easy surprisingly’, highlighting Swift’s flexibility. The talk description also mentions: ‘Swift’s flexible concurrency and distributed actor model enabled an incremental side-by-side approach by having Swift concurrency seamlessly execute on the existing scheduling infrastructure.’

Benefits

FDB can now write new components in Swift, gaining its memory safety, concurrency safety, and improved ergonomics.

Crucially, they can do this without sacrificing their battle-tested deterministic simulation testing capabilities. Swift code benefits from the same rigorous testing as the legacy C++/Flow code.

Takeaways for Swift Developers?

Swift’s modern and extensible concurrency system allowed it to seamlessly integrate with FoundationDB’s pre-existing and highly specialized deterministic simulation testing runtime. This demonstrates Swift’s capability to work well within such environments, particularly when a mechanism exists to control the scheduling and execution of its concurrent tasks.

Whenever you’re about to use C++, you should think again and use Swift