Test and Debug Utilities¶
The XCSoar test suite includes a collection of standalone utility programs
for debugging, testing, and interactive exploration of XCSoar components
without running the full application. Many of these utilities are prefixed
with Run* (e.g., RunTask, RunAnalysis, RunDeviceDriver), but
the suite also includes data conversion tools, device emulators, and other
development utilities.
Overview¶
Run* utilities are standalone programs that exercise specific XCSoar subsystems in isolation. They serve several purposes:
Debugging: Test individual components with real or simulated data
Development: Interactive tools for exploring component behavior
Testing: Verify functionality with flight data files
Device interaction: Communicate with hardware devices directly
These utilities are built as part of the XCSoar build system and are available in the output directory after compilation. The exact path depends on your build target:
Unix/Linux:
output/UNIX/bin/(default, and for flavors like WAYLAND, OPT, FUZZER)Windows:
output/PC/bin/(default, and for WIN64 flavor)macOS:
output/OSX64/bin/oroutput/MACOS/bin/(default)
Important: Many build “targets” are actually flavors that override the base
target. For example, TARGET=WAYLAND or TARGET=OPT both build to
output/UNIX/bin/ because they override the TARGET to UNIX internally. The
debug utilities are built for the base target (UNIX, PC, etc.), not for the
flavor name.
Note: In the examples below, output/UNIX/bin/ is used (typical for Linux
development). Replace UNIX with your actual base build target if different
(e.g., PC for Windows, OSX64 for macOS). To find your output directory,
check what was created in the output/ folder after building.
Building Run* Utilities¶
All Run* utilities are automatically built when you compile XCSoar. They are
defined in build/test.mk and compiled as part of the debug programs target.
To build all Run* utilities:
make DEBUG
To build a specific utility:
make output/UNIX/bin/RunTask
The utilities are built for the host platform (your development machine), not for embedded targets like Android or Kobo.
Common Patterns¶
Run* utilities follow several common patterns depending on their purpose:
Pattern 1: DebugReplay-Based Utilities¶
Many utilities use DebugReplay to process flight data files (IGC, NMEA).
This pattern is ideal for testing components that need to process historical
flight data.
Example: RunTask.cpp, RunWindComputer.cpp, RunContestAnalysis.cpp
Structure:
#include "system/Args.hpp"
#include "DebugReplay.hpp"
int main(int argc, char **argv)
{
Args args(argc, argv, "USAGE");
DebugReplay *replay = CreateDebugReplay(args);
if (replay == NULL)
return EXIT_FAILURE;
args.ExpectEnd();
while (replay->Next()) {
const MoreData &basic = replay->Basic();
const DerivedInfo &calculated = replay->Calculated();
// Process data here
}
delete replay;
return EXIT_SUCCESS;
}
Usage:
./output/UNIX/bin/RunTask task.xct test/data/01lz1hq1.igc
CreateDebugReplay() automatically detects the file format (IGC, NMEA) and
creates an appropriate replay object. It accepts:
IGC files:
file.igc(auto-detected by extension)IGC files with driver prefix:
IGC file.igc(driver name is ignored)NMEA files:
DRIVER file.nmea(driver name required for NMEA parsing)
If the file has a .igc extension, it is always parsed using the native IGC
replay, even if a driver name is specified before it.
Pattern 2: Main.hpp-Based GUI Utilities¶
Utilities that need a graphical interface use Main.hpp, which provides
boilerplate for window creation, event loops, and UI initialization.
Example: RunAnalysis.cpp, RunCanvas.cpp, RunMapWindow.cpp
Structure:
#define ENABLE_LOOK
#define ENABLE_DIALOG
#define ENABLE_CMDLINE
#define ENABLE_PROFILE
#define USAGE "DRIVER FILE"
#include "Main.hpp"
static void
Main(UI::Display &display)
{
// Create windows, dialogs, etc.
}
Available defines:
ENABLE_LOOK: Full Look system (fonts, colors, styles)ENABLE_DIALOG: Dialog system with DialogLookENABLE_CMDLINE: Command-line argument parsingENABLE_PROFILE: Profile/configuration file supportENABLE_MAIN_WINDOW: Main window with event loopENABLE_SCREEN: Screen initializationENABLE_BUTTON_LOOK: Button rendering support
Usage:
./output/UNIX/bin/RunAnalysis FLARM test/data/01lz1hq1.igc
Pattern 3: Simple Command-Line Utilities¶
Simple utilities that don’t need flight data or GUI can use direct command-line parsing.
Example: RunDeviceDriver.cpp, RunMD5.cpp, RunSHA256.cpp
Structure:
#include "system/Args.hpp"
int main(int argc, char **argv)
{
Args args(argc, argv, "USAGE");
// Parse arguments
args.ExpectEnd();
// Process input (stdin, files, etc.)
return EXIT_SUCCESS;
}
Usage:
echo "$GPRMC,..." | ./output/UNIX/bin/RunDeviceDriver FLARM
Pattern 4: Device Interaction Utilities¶
Utilities that interact with hardware devices use DebugPort and device
drivers directly.
Example: RunFlarmUtils.cpp, RunLX1600Utils.cpp, RunVegaSettings.cpp
Structure:
#include "test/src/DebugPort.hpp"
#include "Device/Driver.hpp"
int main(int argc, char **argv)
{
Args args(argc, argv, "PORT BAUD");
DebugPort debug_port(args);
args.ExpectEnd();
ScopeGlobalAsioThread global_asio_thread;
NullDataHandler handler;
auto port = debug_port.Open(*asio_thread, *global_cares_channel, handler);
ConsoleOperationEnvironment env;
if (!port->WaitConnected(env)) {
return EXIT_FAILURE;
}
// Interact with device
return EXIT_SUCCESS;
}
Usage:
./output/UNIX/bin/RunFlarmUtils /dev/ttyUSB0 57600
Using DebugReplay¶
DebugReplay is the primary mechanism for processing flight data in Run*
utilities. It provides:
Automatic format detection: IGC, NMEA, or device-specific formats
Incremental processing:
Next()advances through the flight dataComputed data:
Basic()returns processedMoreDataCalculated data:
Calculated()returnsDerivedInfoState management: Tracks previous states for calculations
Basic usage:
DebugReplay *replay = CreateDebugReplay(args);
if (replay == NULL)
return EXIT_FAILURE;
while (replay->Next()) {
const MoreData &basic = replay->Basic();
const DerivedInfo &calculated = replay->Calculated();
// Access GPS data
if (basic.location_available) {
GeoPoint location = basic.location;
// ...
}
// Access calculated values
if (calculated.estimated_wind_available) {
SpeedVector wind = calculated.estimated_wind;
// ...
}
}
delete replay;
Available data:
replay->Basic(): CurrentMoreData(GPS, sensors, etc.)replay->LastBasic(): PreviousMoreData(for calculations)replay->Calculated(): CurrentDerivedInfo(wind, task stats, etc.)replay->SetCalculated(): Mutable reference for updating calculationsreplay->SetFlyingComputer(): Access toFlyingComputerfor flight state
Setting QNH:
replay->SetQNH(AtmosphericPressure::Standard());
// Or from user input:
replay->SetQNH(AtmosphericPressure::HectoPascal(1013.25));
Common Utility Examples¶
RunTask¶
Tests task calculation with flight data.
Usage:
./output/UNIX/bin/RunTask task.xct test/data/01lz1hq1.igc
What it does:
Loads a task file (
.xct,.tsk,.cup)Replays flight data through the task
Reports task start, finish, and statistics
RunWindComputer¶
Tests wind estimation algorithms.
Usage:
./output/UNIX/bin/RunWindComputer FLARM test/data/01lz1hq1.igc
What it does:
Processes flight data through wind computer
Outputs wind estimates over time
Useful for debugging wind calculation algorithms
RunDeviceDriver¶
Tests device driver NMEA parsing.
Usage:
echo "$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A" | \
./output/UNIX/bin/RunDeviceDriver FLARM
What it does:
Parses NMEA sentences through device driver
Outputs parsed data fields
Useful for testing driver parsing logic
RunAnalysis¶
Opens the analysis dialog with flight data.
Usage:
./output/UNIX/bin/RunAnalysis FLARM test/data/01lz1hq1.igc
What it does:
Loads flight data
Opens the analysis dialog window
Allows interactive exploration of flight data
RunFlarmUtils¶
Interactive tool for configuring FLARM devices.
Usage:
./output/UNIX/bin/RunFlarmUtils /dev/ttyUSB0 57600
What it does:
Connects to FLARM device
Provides interactive menu for: - Changing pilot/co-pilot names - Setting competition ID/class - Configuring stealth mode - Adjusting range and baud rate
FeedNMEA¶
Feeds NMEA sentences from stdin to a serial port, TCP connection, or UDP socket. Useful for testing XCSoar with simulated GPS data, especially when running XCSoar under WINE or testing network-based device connections.
Usage:
Serial port:
cat test.nmea | ./output/UNIX/bin/FeedNMEA /dev/ttyUSB0 57600
# Or with a pseudo-TTY for WINE:
cat test.nmea | ./output/UNIX/bin/FeedNMEA /tmp/nmea 57600
TCP server (listener):
cat test.nmea | ./output/UNIX/bin/FeedNMEA tcp 4353
TCP client (connects to server):
cat test.nmea | ./output/UNIX/bin/FeedNMEA tcp_client 192.168.1.100 4353
UDP listener:
cat test.nmea | ./output/UNIX/bin/FeedNMEA udp 4353
What it does:
Reads NMEA sentences from stdin (one per line)
Writes them to the specified port (serial, TCP, or UDP)
Automatically sleeps for 1 second when timestamps change (for realistic timing)
Echoes received data to stdout (for bidirectional communication testing)
Port Types:
Serial ports:
/dev/ttyUSB0,/dev/ttyACM0,COM1(Windows), etc.TCP listener:
tcp <port>- Listens for incoming TCP connectionsTCP client:
tcp_client <ip_address> <port>- Connects to a TCP serverUDP listener:
udp <port>- Listens for UDP datagramsPseudo-TTY:
pty <path>- Creates a pseudo-terminal
TCP Server Mode:
TCP listener mode allows XCSoar (or other clients) to connect and receive NMEA data over the network:
# Terminal 1: Start FeedNMEA as TCP server
cat flight.nmea | ./output/UNIX/bin/FeedNMEA tcp 4353
# Terminal 2: XCSoar connects to localhost:4353 to receive NMEA data
# Configure XCSoar device port as "TCP Client" with host "localhost" and port 4353
TCP Client Mode:
TCP client mode connects to a remote server and sends NMEA data:
# Connect to remote NMEA server and feed data
cat flight.nmea | ./output/UNIX/bin/FeedNMEA tcp_client 192.168.1.100 4353
This is useful for: - Sending NMEA data to a remote XCSoar instance - Testing network-based device connections - Integrating with network GPS servers
WINE Integration:
FeedNMEA is particularly useful for testing XCSoar under WINE:
Create a pseudo-TTY:
./output/UNIX/bin/FeedNMEA /tmp/nmea 57600Symlink WINE COM port:
ln -s /tmp/nmea ~/.wine/dosdevices/com1Configure XCSoar to use COM1
Feed NMEA data:
cat flight.nmea | ./output/UNIX/bin/FeedNMEA /tmp/nmea 57600
Example:
# Convert IGC to NMEA and feed to serial port
./output/UNIX/bin/IGC2NMEA test/data/01lz1hq1.igc /tmp/flight.nmea
cat /tmp/flight.nmea | ./output/UNIX/bin/FeedNMEA /dev/ttyUSB0 57600
# Or feed to TCP server for network testing
cat /tmp/flight.nmea | ./output/UNIX/bin/FeedNMEA tcp 4353
EmulateDevice¶
Emulates device protocols to test XCSoar’s device communication without actual hardware. Supports Vega, FLARM, and ATR833 devices.
Usage:
./output/UNIX/bin/EmulateDevice FLARM /dev/ttyUSB0 57600
./output/UNIX/bin/EmulateDevice Vega /tmp/nmea 57600
./output/UNIX/bin/EmulateDevice ATR833 /dev/ttyUSB0 9600
What it does:
Creates a device emulator that responds to XCSoar commands
Implements device-specific protocols: - FLARM: Responds to configuration commands (PFLAC), sends traffic data - Vega: Emulates variometer with settings commands - ATR833: Emulates radio transponder with frequency commands
Runs until the port connection fails
Useful for testing device drivers without physical hardware
Supported Devices:
FLARM: FLARM collision avoidance systemVega: Vega variometerATR833: ATR833 radio transponder
Use Cases:
Testing device driver implementations
Debugging device communication protocols
Developing new device drivers
Automated testing of device interactions
Example Workflow:
# Terminal 1: Start device emulator
./output/UNIX/bin/EmulateDevice FLARM /tmp/flarm 57600
# Terminal 2: Connect XCSoar to /tmp/flarm and test FLARM features
# XCSoar will send commands, emulator will respond appropriately
Data Conversion Utilities¶
IGC2NMEA¶
Converts IGC flight files to NMEA format. Useful for testing device drivers or feeding NMEA data to other tools.
Usage:
./output/UNIX/bin/IGC2NMEA test/data/01lz1hq1.igc output.nmea
What it does:
Reads IGC file using DebugReplay
Generates NMEA sentences (GPRMC, GPGGA, PGRMZ)
Writes NMEA output to file
Useful for converting flight data to NMEA format for testing
Example:
# Convert IGC to NMEA, then feed to device
./output/UNIX/bin/IGC2NMEA flight.igc flight.nmea
cat flight.nmea | ./output/UNIX/bin/FeedNMEA /dev/ttyUSB0 57600
lxn2igc¶
Converts LX Navigation (LXN) binary files to IGC format.
Usage:
./output/UNIX/bin/lxn2igc flight.lxn > flight.igc
What it does:
Reads LX Navigation binary format (
.lxnfiles)Converts to standard IGC format
Outputs to stdout
Useful for converting old LX device recordings
Example:
./output/UNIX/bin/lxn2igc test/data/lxn_to_igc/18BF14K1.FIL > converted.igc
Flight Analysis Utilities¶
RunContestAnalysis¶
Analyzes flight data through all contest solvers and prints results.
Usage:
# IGC file (auto-detected by extension):
./output/UNIX/bin/RunContestAnalysis flight.igc
# NMEA file (driver name required):
./output/UNIX/bin/RunContestAnalysis FLARM flight.nmea
What it does:
Processes flight data through all contest solvers
Runs exhaustive solving for OLC Classic, FAI, Sprint, League, Plus, DMSt (quadrilateral, triangle, out-and-return, free), XContest, SIS-AT, WeGlide (distance, FAI, OR, free), and Charron
Prints distance, score, speed, and time for each contest type
Useful for comparing contest results across rule sets
Example output (abbreviated):
classic
# score 307.294
# distance 307.294 (km)
# speed 67.213 (kph)
# time 16459 (sec)
dmst
# quadrilateral
# score 276.402
# distance 276.402 (km)
...
# triangle
# score 276.853
# distance 197.752 (km)
...
AnalyseFlight¶
Analyzes flight data and outputs JSON with flight phases, takeoff/landing times, and contest results.
Usage:
# IGC file (auto-detected by extension):
./output/UNIX/bin/AnalyseFlight flight.igc
# NMEA file (driver name required):
./output/UNIX/bin/AnalyseFlight FLARM flight.nmea
# With options:
./output/UNIX/bin/AnalyseFlight --full-points=1024 flight.igc
What it does:
Processes flight data through flight phase detector
Detects takeoff, release, and landing events
Calculates contest results (OLC Plus, DMSt)
Outputs JSON with flight statistics
Useful for automated flight analysis
Output includes:
Takeoff/release/landing times and locations
Flight phases (circling, cruise, etc.)
Contest scores (OLC Plus: classic/triangle/plus; DMSt: quadrilateral/triangle/out-and-return/free)
Circling statistics
Note: Available on UNIX/PC platforms only (not Android).
Device and Port Utilities¶
EnumeratePorts¶
Lists all available serial/TTY ports on the system. Useful for debugging device connection issues.
Usage:
./output/UNIX/bin/EnumeratePorts
What it does:
Scans system for available TTY/serial ports
Lists port paths (e.g.,
/dev/ttyUSB0,/dev/ttyACM0)Helps identify which port a device is connected to
Example output:
/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyACM0
Note: Only available on POSIX systems (Linux, macOS, not Windows).
Monitoring Device Communication with socat¶
socat is a powerful command-line utility available in Debian/Ubuntu that can monitor bidirectional serial port traffic between XCSoar and devices. This is useful for debugging device communication protocols and seeing all NMEA sentences in both directions.
Installation:
sudo apt install socat
Basic Usage - Monitor Serial Port:
To monitor a serial port and see all traffic in both directions:
# Monitor /dev/ttyUSB0 at 57600 baud, showing both TX and RX
socat -x -v /dev/ttyUSB0,raw,echo=0,b57600 -
The flags:
- -x: Shows hex dump of all data
- -v: Verbose output with direction indicators (> for TX, < for
RX)
-: Outputs to stdout
Spying on XCSoar Device Communication:
To spy on communication between XCSoar and a device, create a virtual serial pair and route traffic through it:
# Terminal 1: Create virtual serial pair with logging
socat -x -v pty,raw,echo=0,link=/dev/ttyV0 pty,raw,echo=0,link=/dev/ttyV1
# Terminal 2: Connect device to one end (e.g., /dev/ttyV0)
# Terminal 3: Configure XCSoar to use /dev/ttyV1
# All traffic will be logged in Terminal 1
Alternative: Direct Port Monitoring:
If you can temporarily disconnect the device, monitor it directly:
# Connect device to /dev/ttyUSB0, monitor at 57600 baud
socat -x -v /dev/ttyUSB0,raw,echo=0,b57600 - | tee device_traffic.log
This will:
- Display all traffic in real-time with hex dumps
- Show direction indicators (> for data sent to device, < for data
received from device)
Save output to
device_traffic.logfile
What it does:
Monitors bidirectional serial port traffic
Shows both TX (transmitted) and RX (received) data
Displays data in both ASCII and hex format
Useful for debugging device communication issues
Helps understand device protocol behavior
Note: Requires Debian/Ubuntu package socat. The device port must be
available (not in use by XCSoar) when monitoring directly.
CAI302Tool¶
Interactive tool for CAI302 flight computer devices. Allows reading device information, waypoints, and flight data.
Usage:
./output/UNIX/bin/CAI302Tool /dev/ttyUSB0 9600
What it does:
Connects to CAI302 device
Reads device information (ID, firmware version)
Can read waypoints and flight data
Useful for debugging CAI302 device communication
Note: Requires CAI302 device connected via serial port.
Scripting Utilities¶
RunLua¶
Runs Lua scripts with XCSoar Lua bindings. Useful for testing Lua scripts or developing Lua-based features.
Usage:
./output/UNIX/bin/RunLua script.lua
What it does:
Initializes Lua state with XCSoar bindings
Loads and executes Lua script
Provides access to: - Geo functions (coordinate calculations) - HTTP functions (if HTTP support enabled) - Log functions - Custom
alert()function for output
Available bindings:
geo.*: Geographic calculationshttp.*: HTTP requests (if enabled)log.*: Logging functionsalert(): Print to stderr
Example script:
local point1 = geo.Point(52.0, 13.0)
local point2 = geo.Point(52.1, 13.1)
local distance = geo.Distance(point1, point2)
alert("Distance: " .. distance)
Note: Requires Lua support to be enabled in build (LUA=y).
Renderer Utilities¶
These utilities test and demonstrate various rendering components used in XCSoar’s UI. They provide interactive visual testing of renderers.
RunRenderOZ¶
Tests observation zone (OZ) rendering for different task zone types.
Usage:
./output/UNIX/bin/RunRenderOZ
What it does:
Displays a window with a list of observation zone types on the left
Renders the selected zone type on the right
Supports all OZ types: Line, Cylinder, Sector, FAI Sector, Keyhole, etc.
Interactive: click on zone type to see it rendered
Useful for testing OZ rendering and debugging zone shapes
Supported zone types:
Line, Cylinder, MAT Cylinder
Sector, FAI Sector, Annular Sector
DAeC Keyhole, BGA Fixed Course, BGA Enhanced Option
BGA Start, Symmetric Quadrant, Custom Keyhole
RunChartRenderer¶
Tests chart/graph rendering capabilities.
Usage:
./output/UNIX/bin/RunChartRenderer
What it does:
Displays a window with chart types on the left
Renders the selected chart on the right
Demonstrates line charts, grids, labels
Interactive: select chart type from list
Useful for testing chart rendering and data visualization
RunWindArrowRenderer¶
Tests wind arrow rendering with animated wind display.
Usage:
./output/UNIX/bin/RunWindArrowRenderer
What it does:
Displays animated wind arrow in center of window
Wind direction and speed change automatically
Demonstrates wind arrow rendering styles
Useful for testing wind visualization
RunHorizonRenderer¶
Tests artificial horizon rendering with animated attitude display.
Usage:
./output/UNIX/bin/RunHorizonRenderer
What it does:
Displays animated artificial horizon
Bank and pitch angles change automatically
Demonstrates horizon rendering with attitude indicators
Useful for testing attitude visualization
RunFinalGlideBarRenderer¶
Tests final glide bar rendering with animated altitude difference.
Usage:
./output/UNIX/bin/RunFinalGlideBarRenderer
What it does:
Displays final glide bar with altitude difference
Shows MC and MC0 solutions
Animated: altitude difference changes over time
Useful for testing final glide calculations and rendering
RunFAITriangleSectorRenderer¶
Tests FAI triangle sector rendering with interactive point dragging.
Usage:
./output/UNIX/bin/RunFAITriangleSectorRenderer
What it does:
Displays FAI triangle sector between two points
Interactive: drag points A and B to change sector
Shows sector boundary and area
Useful for testing FAI triangle calculations and rendering
RunFlightListRenderer¶
Tests flight list rendering from a flight log file.
Usage:
./output/UNIX/bin/RunFlightListRenderer flights.log
What it does:
Reads flight information from log file
Renders flight list in a window
Displays flight dates, times, and statistics
Useful for testing flight list UI rendering
Note: Requires a flight log file (flights.log) as argument.
Creating a New Run* Utility¶
To create a new Run* utility:
Create the source file in
test/src/RunYourUtility.cpp:
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The XCSoar Project
#include "system/Args.hpp"
#include "DebugReplay.hpp"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
Args args(argc, argv, "USAGE");
DebugReplay *replay = CreateDebugReplay(args);
if (replay == NULL)
return EXIT_FAILURE;
args.ExpectEnd();
// Your processing logic here
delete replay;
return EXIT_SUCCESS;
}
Add to build system in
build/test.mk:
Find the DEBUG_PROGRAM_NAMES list and add your utility:
DEBUG_PROGRAM_NAMES += \
RunYourUtility
Then add build rules:
RUN_YOUR_UTILITY_SOURCES = \
$(DEBUG_REPLAY_SOURCES) \
$(TEST_SRC_DIR)/RunYourUtility.cpp
RUN_YOUR_UTILITY_DEPENDS = $(DEBUG_REPLAY_DEPENDS) GEO MATH UTIL
$(eval $(call link-program,RunYourUtility,RUN_YOUR_UTILITY))
Build and test:
make output/UNIX/bin/RunYourUtility
./output/UNIX/bin/RunYourUtility FLARM test/data/01lz1hq1.igc
Dependencies¶
Common dependencies for Run* utilities:
DEBUG_REPLAY_SOURCES: For DebugReplay-based utilitiesDEBUG_REPLAY_DEPENDS: Standard dependencies (GEO, MATH, UTIL, etc.)TASK: For task-related utilitiesWAYPOINT: For waypoint-related utilitiesAIRSPACE: For airspace-related utilitiesLOOK: For GUI utilitiesDIALOG: For dialog-based utilities
Check existing utilities in build/test.mk for examples of dependency
patterns.
Additional Resources¶
test/src/DebugReplay.hpp: DebugReplay API documentationtest/src/Main.hpp: GUI utility boilerplatetest/src/DebugPort.hpp: Device port utilitiestest/data/: Sample flight data files for testingbuild/test.mk: Build system definitions for all utilities