Task: Write round-trip tests for instrument parse dispatch

Table of Contents

This page documents a task in the Fix rfl complexity failure (Windows + macOS CI) story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

Validate the new instrument parse dispatch with round-trip tests that exercise the full server → client JSON path. Tests must compile and pass on Linux, Windows (MSVC), and macOS (Clang) — their compilation on MSVC/Clang is itself evidence that AddTagsToVariants has been successfully eliminated from the client parse path.

2. Status

Field Value
State DONE
Parent story Fix rfl complexity failure (Windows + macOS CI)
Now Nothing.
Waiting on Nothing.
Next N/A.
Last touched 2026-05-31

3. Acceptance

  • At least one test per instrument family: bond, credit, commodity, scripted, composite, FX (at least 2 leaf types: forward + one option), rates/swap (at least 2 leaf types: FRA + vanilla swap), equity (at least 2 leaf types: option + forward).
  • Each test serializes a fully-populated response struct using rfl::json::write<rfl::AddTagsToVariants> (matching server behaviour), then calls the new client parse function, and asserts:
    • trade_export_item.instrument holds the expected std::variant alternative.
    • Key instrument fields round-trip correctly (instrument_id, a family-specific field).
    • trade_export_item.trade.classification.product_type matches.
  • A test for an unknown (product_type, trade_type) combination asserts the instrument is std::monostate and that a warn log was emitted.
  • A test for a malformed instrument JSON asserts the call returns std::nullopt and that an error log was emitted.
  • All tests compile with MSVC (no C1202) and Clang (no fold-expression error).

4. Plan

(Transient.)

4.1. Test structure

One test fixture (or test file) per family is sufficient. Tests live in the ores.qt.api test target alongside existing tests.

Pattern per test:

// 1. Build a response the way the server does
messaging::get_trade_instrument_response resp{
    .success = true,
    .trade   = make_test_trade(product_type::fx, "FxForward"),
    .instrument = fx_instrument_variant{make_fx_forward()}
};

// 2. Serialize as the server does
const auto json = rfl::json::write<rfl::AddTagsToVariants>(resp);

// 3. Run client parse
auto result = parse_trade_instrument(json);  // the new function under test

// 4. Assert
ASSERT_TRUE(result.has_value());
auto* fx_fwd = std::get_if<fx_instrument_variant>(&result->instrument);
ASSERT_NE(fx_fwd, nullptr);
auto* fwd = std::get_if<fx_forward_instrument>(fx_fwd);
ASSERT_NE(fwd, nullptr);
EXPECT_EQ(fwd->currency_pair, "EURUSD");

4.2. Leaf types to cover

Family Leaf types to test
Bond bond_instrument
Credit credit_instrument
Commodity commodity_instrument
Scripted scripted_instrument
Composite composite_instrument_data (with legs)
FX fx_forward_instrument, fx_vanilla_option_instrument
Rates fra_instrument, vanilla_swap_instrument (with legs)
Equity equity_option_instrument, equity_forward_instrument

5. Notes

6. PRs

PR Title
941 [ores.qt.api] Task 3: extract parse_trade_instrument + tests

7. Review

# Comment summary File Decision Notes
1 READ_FLAT/READ_LEGS identical; unhygienic parse_trade_instrument.cpp Applied Replaced both macros with try_parse<T>() template (8c9cad6b); thread resolved

8. Result

Emacs 29.3 (Org mode 9.6.15)