Building and running¶
What it needs¶
- Rust 1.89 or newer.
- D-Bus development files, for the system keyring and notifications.
- pcsc-lite's development files on Linux and BSDs, for security keys (OpenPGP cards: a YubiKey):
pcsc-syslinks its client, found by pkg-config. Windows and macOS have theirs built in (WinSCard, the PCSC framework); Android needs none. To use a key, the smart card service must run:pcscdwith its CCID driver (Fedorapcsc-liteandpcsc-lite-ccid, thensudo systemctl enable --now pcscd.socket; Debian and Ubuntupcscd; Archpcscliteandccid). - For the window only: Qt 6.9 or newer (built and used with 6.11), with its development files: Qt Declarative (QML, Qt Quick, Controls, Layouts, Dialogs, Effects), Qt WebEngine with Qt WebChannel and Qt PDF, Qt Multimedia, Qt Positioning, Qt Location and Qt Image Formats. Sites keep their permissions with Qt WebEngine's permission API, long menus scroll as items of the window (both Qt 6.8), and each site's profile is made from a prototype (
WebEngineProfilePrototype, Qt 6.9). The command line builds without Qt.
| System | Packages |
|---|---|
| Fedora | dbus-devel, pcsc-lite-devel, qt6-qtbase-devel, qt6-qtdeclarative-devel, qt6-qtwebengine-devel, qt6-qtwebchannel-devel, qt6-qtpdf-devel, qt6-qtpositioning-devel, qt6-qtmultimedia, qt6-qtlocation, qt6-qtimageformats; to check attachments, clamav and clamav-update; to read paper letters, tesseract |
| Debian, Ubuntu, Arch | the D-Bus and pcsc-lite development files (Debian, Ubuntu: libpcsclite-dev; Arch: pcsclite), and Qt 6.9 or newer with the modules above and their QML modules; distributions name them differently (Debian: qt6-…-dev, qml6-module-…; Arch: qt6-…) |
The command line¶
cargo build and cargo test build the core, sync and the command line; the window is left out unless asked for, so machines without Qt can work on the rest.
Which build¶
Each build knows its version and the commit it was made from (sioul_core::build: VERSION, COMMIT, DESCRIBED, "0.0.3 (eff8661abcde)"), and says them: sioul --version; Settings ▸ Your folder and sharing ("This device: Sioul 0.0.3 (eff8661abcde)."); this device's entry among your devices, which the others show under its name; the first line of each batch of its records (database.md, "Devices", "The log"). crates/sioul-core/build.rs finds the commit:
git rev-parse --short=12 HEAD, with "-dirty" after it when tracked files hold changes not committed (git status --porcelain --untracked-files=no: files git does not track never count);- else the
.gitfolder read directly (HEAD, the branch it names, the packed references), for a build wheregitcannot run, or refuses a checkout another user owns (a container's); never "-dirty" then; - else
SIOUL_COMMITfrom the environment (letters, digits,-and.only), for a build from a copy without the repository's history; - else "unknown".
The workflows (.github/workflows/*.yml, actions/checkout, shallow) and the phone's build (~/Android/build.sh, android/CMakeLists.txt through Corrosion) build from the checkout itself, and find it the first way. The Flatpak copies the checkout as its source (type: dir), its .git among it unless skipped: the first or second way; SIOUL_COMMIT in the manifest's build-options would do where neither does (not needed so far, not checked inside flatpak-builder).
When it is looked at again: when the commit changes (HEAD, its branch, the packed references), when SIOUL_COMMIT changes, when a file of sioul-core changes. Not when another crate's file changes: watching the whole tree would build every crate again at each edit, and .git/index changes at each git status. So "-dirty" says the tree held changes when sioul-core was last built; a change made since, in another crate alone, does not add it. touch crates/sioul-core/build.rs before a build makes sure.
Sioul's own sign-in applications¶
Google and Microsoft sign people in on their own pages, with an application registered for Sioul, read at build time from the environment of cargo build (a release workflow's secrets, never the repository):
SIOUL_GOOGLE_CLIENT_IDandSIOUL_GOOGLE_CLIENT_SECRET, Google's (google.md); no workflow passes them yet.SIOUL_MICROSOFT_CLIENT_ID, Microsoft's: an id alone, no secret, since Microsoft refuses one from a program on your device (microsoft.md).release.ymlpasses it on the build steps of the Windows, macOS and AppImage packages, the Flatpak through its manifest'ssecret-env, andandroid.ymlon the APK's;build.yml's artefacts are built without it.
A build without them asks each person for a Google key, or a Microsoft application, of their own; the forms give the steps. Changing one of them builds sioul-sync again: Cargo watches what option_env! reads.
Windows and macOS¶
- Windows: Rust (rustup, MSVC), Qt 6.9 or newer from Qt's online installer (MSVC 2022 64-bit, with the modules above), with Qt's
binfolder inPATH; then the samecargo build --release -p sioul-app.windeployqt --release --qmldir crates\sioul-app\qml target\release\sioul-app.exegathers Qt beside the program, Qt's SVG plugins among it (iconengines\qsvgicon.dll,imageformats\qsvg.dll: Sioul's icons are SVG, and the packages' builds check that they are there), andpackaging\windows\sioul.issmakes an installer with Inno Setup. Attachments are checked by Microsoft Defender through AMSI. - macOS: see packaging/macos/README.md.
- Android, an experiment: see android.md.
- Checking both from Linux is done by the workflow
.github/workflows/build.yml: on each push tomainthat touches code it builds and tests Sioul on Linux, Windows and macOS with Qt 6.11 (below), and on Linux reads the code's comments with rustdoc, private items included, its warnings as errors (as the website's API reference does); started by hand (Actions, "Build on three systems", "Run workflow"), it also makes a Windows folder with Qt beside the program and a macOS.dmg.
The tests on GitHub¶
build.yml builds the window and the command line on Linux (Ubuntu 24.04), Windows (Server 2022) and macOS (15), checks and packs them, then runs the tests of sioul-core, sioul-sync and sioul-cli in one command, then the test of the bundled icons. A job stops at 150 minutes.
- One command, one set of features. Testing several crates in one command unifies their dev-dependencies' features: the command line's
no-keyringreachessioul-sync's own tests too. They never need the keyring, but for one: on Windows,microsoft::tests::windows_keeps_a_4_kb_tokenchecks the Credential Manager on purpose (Windows keeps 2,560 bytes an entry). It reaches it throughsecret::with_real_keyring, on its own thread and on Windows alone, whatever the features (run 39216227853 failed without it). On Linux and macOS no test reaches the keyring: it is the person's own. - Windows is the slowest. The sharing's simulations (
share_switch_tests.rs,share_switch_more_tests.rs,share_switch_third_tests.rsincrates/sioul-sync/src/) write each simulated device's files at every simulated minute and read the others', and they took fourteen to eighteen times as long on Windows as on Linux (on this laptop, whose disk is slow to flush, they spent three quarters of their time waiting for it). On 9 October 2026 the Windows job took 1 hour 34, 71 minutes of it forsioul-sync's tests; on 11 October (run 38155276278) they were still running after 97 minutes when the job reached its two-hour limit, against 521 seconds on Linux. On 13 October (run 38390114216, every seed, the limit raised to 300 minutes) they took 2 hours 50 on Windows, 33 minutes on macOS and 12 on Linux, and the Windows job 3 hours 13, all tests passing; its four widest sweeps took 77 to 135 minutes each there. - A few seeds, or every seed. Each simulation draws its devices' edits from a seed, over a range of seeds (
switch_more_tests::seeds). By default it runs the first three seeds of its range, and the seeds that once found a bug, which each test names (77 for T7 and T7b, 7 for S5b, 6, 7 and 9 for R11, 4 to 9 for R2 and R3): 231 runs.SIOUL_SWEEP=wideruns every seed the reviews ran, 1,532 runs. Linux's job sets it, so every push still runs the whole sweep; Windows, macOS and your own computer run the few unless asked. Before changing the sharing's format or how it merges, run the wide sweep by hand:SIOUL_SWEEP=wide cargo test --release -p sioul-sync. - Times, on the development laptop, four test threads as on GitHub's runners:
sioul-sync's tests took 51.6 minutes with every seed and 7.4 with the few; the simulations, 133 minutes of the threads' time, 21 with the few. Windows took 2.3 to 3.8 times as long as this laptop for the same tests, depending on the runner: some 17 to 28 minutes for them with the few, and 45 to 55 for the Windows job, until a run says otherwise. - The bundled icons (
cargo test --release -p sioul-app --test icons,crates/sioul-app/tests/icons.rs): every icon name the window gives is read by Qt from the bundled themes, light and dark, with no theme of the system's (offscreen, no platform theme, empty XDG folders); the set in use follows light, dark and light colours; and every bundled SVG must draw something. A name the bundle lacks shows nothing on Windows, macOS and phones, while a Linux desktop draws it from its own theme: this test fails instead, on each of the three systems. It runs after the other tests, whatever their outcome, and takes a second once built.
The window¶
To find it in the application menu:install -Dm755 target/release/sioul-app ~/.local/bin/sioul-app
install -Dm755 target/release/sioul ~/.local/bin/sioul
install -Dm644 data/com.aurelienpierre.Sioul.desktop ~/.local/share/applications/com.aurelienpierre.Sioul.desktop
install -Dm644 data/com.aurelienpierre.Sioul.metainfo.xml ~/.local/share/metainfo/com.aurelienpierre.Sioul.metainfo.xml
mkdir -p ~/.local/share/icons && cp -r data/icons/hicolor ~/.local/share/icons/
tools/install.sh (PREFIX sets where; ~/.local by default), which builds the command line, then the window, each alone, checks them, and installs them as above.
Build right before installing or packing. A test run (cargo test, any crate) builds with the tests' features, sioul-sync's no-keyring among them, and Cargo unifies them into every unit that run builds, the programs included: afterwards target/release/sioul and sioul-app are built for testing until the next cargo build --release, and keep no password (review of 19 October 2026, N1). No release build names a SIOUL_TEST_ hook; every path that ships a program checks it has none (tools/check-test-marks.sh): tools/install.sh, tools/final-pass.sh (which builds the programs after the tests), build.yml (the programs packed before any test step), release.yml (each system's build), the Flatpak's manifest and android.yml (Sioul's library in the APK). Cargo cannot keep a feature of the tests out of the programs a test run builds: the check is what holds.
Measuring the load¶
tools/measure-load.py <sioul-app pid> [<watcher pid>|0] [seconds] [out] samples Sioul every five seconds: its own process and every process under it (Qt WebEngine's zygotes, each site's renderers, its utility processes), CPU from /proc/<pid>/stat, memory as PSS (shared pages counted once), USS and RSS, threads, context switches and disk I/O; it writes a CSV and a JSON summary. On 6 October 2026 (8 cores, Linux, Qt 6.11, the release build of 5d80878):
- an invented profile, no site open (the demo profile, offscreen, five minutes): one process, CPU 0.2 % of one core on average (peak 3 %): Qt WebEngine starts with the first site opened, and each page of the window, each form and menu, with its first use. Its memory is below. On 4 October it was four processes and about 280 MB.
- daily use (a real mailbox, notes and tasks; three sites open in real time; three minutes, the window then closed): 8 processes, about 1.15 GB in all (
sioul-app0.39 GB, from 0.38 to 0.45; three renderers 0.7 GB; zygotes and the audio service 0.05 GB); CPU median 0.4 % of one core, mean 4 %, two samples above 20 % (up to 40 %);sioul-appread 3 MB and wrote 4 MB, closing included. On 4 October: about 1.9 GB (sioul-app0.7 GB, five renderers 1.1 GB), CPU median 5.5 %, mean 9.4 %, peaks to 76 %. - The reminder watcher (
sioul remind --watch): 10 MB, 0.16 % of one core. - A phone (Gigaset GS290, Android 12):
adb shell dumpsys meminfogives about 200 MB on the screen and 140 MB once put away (graphics given back, android.md); the window's log times each page's first opening (adb logcat | grep sioul-perf: 0.1 to 0.5 s). Not counted: GPU memory.
tools/measure-memory.py [--release] OUT [--sites N] says what the memory is made of. It starts the window as the runner does (below), on a demo profile, in a sandbox without the graphics card, with the step list "memory" (main.qml): a minute at rest on the Porch, every page and form as "pages" opens them, then the profile's sites shown one by one (--sites N: N local pages standing in for chats, kept open). At each moment it reads /proc: the window's process by kind of mapping (its heap, its other anonymous memory, the QML engine's JavaScript heap, Sioul's own program, each library), and the processes under it. tools/measure-memory.py --pid PID reads a Sioul already running the same way, from /proc alone. On 9 October 2026 (the release build; PSS of the window's process, then of the processes under it):
| No site | Three test sites kept open | |
|---|---|---|
| At rest, a minute on the Porch | 82 MB | 157 MB, and 221 MB under it |
| Every page and form opened | 190 MB | 265 MB, and 221 MB under it |
| The Sites page shown | 212 MB: Chromium not started | 297 MB, and 264 MB under it (each site shown) |
- Sioul's own program: 30 to 40 MB of it, its code and resources read from the disk; the kernel may drop them at any time and reads them again when they are used.
- The pages: about 110 MB once every page and form has been opened, QML's objects above all; each page is made at its first opening (10 to 50 ms here) and kept. In the sandbox, drawn in software, the window's pictures take some 18 MB of the process; on a desktop they are in the graphics card's memory.
- Sites: Chromium's browser side lives in the window's process, about 75 MB with three sites, whatever their number (its library's relocations 36 MB, its threads' memory), started with the first site's view, not with the page. Each test page takes about 60 MB in a process of its own, 75 once shown, and the three zygotes 32 MB; a real site 150 to 350 MB.
- What keeps it so: pages, forms and menus made at their first use; a setting's control made for its kind only (
SettingRow.qml: with every kind's controls hidden in each row, the Porch's settings panel alone took some 18 MB); English read only when the language in use lacks a message (i18n.rs: some 3 MB for each language read); glibc's thresholds held (steady_heapinlib.rs), so that memory freed goes back to the system rather than staying with the threads' heaps (15 to 20 MB); pictures read at the size they are drawn (a phone's photo of 12 megapixels in a conversation: 48 MB read whole); Chromium started with the first site's view, and Qt Multimedia, which lists the devices of calls, with the first call or the first look at that list (some 60 MB of graphics libraries in the sandbox). - Still to look at: in daily use, what the graphics driver holds in the window's process (Qt Quick and Chromium draw with the graphics card there), what the real mail and notes hold, and what real sites hold on Chromium's browser side:
tools/measure-memory.py --pidreads it on a running Sioul.
The icon¶
The drawings are in data/icons/: sioul.svg, sioul-small.svg (drawn for 32 pixels and under), sioul-symbolic.svg (one colour, the desktop's), and the quill alone for pages (sioul-mark.svg, sioul-mark-on-dark.svg). tools/make-icons.py (needs rsvg-convert) makes from them the icon theme folders a Linux desktop reads (data/icons/hicolor/, under the application's id, com.aurelienpierre.Sioul, as its desktop file, data/com.aurelienpierre.Sioul.desktop, and its AppStream file, data/com.aurelienpierre.Sioul.metainfo.xml, which software centres read), the Windows .ico and the macOS .icns in packaging/, and the website's favicon and logo; the window carries the PNGs (crates/sioul-app/app.qrc, cpp/appicon.cpp). Run it again after changing a drawing.
First steps¶
- Add your mail accounts, in the window (Accounts, the person at the bottom of the side bar) or from the terminal:
sioul account add you@example.orgSioul finds the server from the address (your provider's own settings, then Thunderbird's list of providers), says what it found, asks for the password, tests it, keeps it in your system keyring, and fetches the last 14 days. Gmail wants an app password (myaccount.google.com/apppasswords). - Web-only mailboxes, chats and other sites open in Sites (Ctrl+4), each logged in once in its own lasting profile (sites.md); from the terminal,
sioul account portal proton https://mail.proton.meadds one. - Keep the window open, or run
sioul watchin a terminal: each account's inbox stays open (IMAP IDLE), and the codes and links you ask sites for become quiet notifications within seconds. - Install an antivirus to have attachments checked before they open (without one, Sioul asks first):
sudo dnf install clamav clamav-update, thensudo freshclamfor its signatures andsudo systemctl enable --now clamav-freshclamto keep them current. - Choose your hours in Settings ▸ Hours: working hours, hours for your admin; every other time is leisure, meals and sleep come from the Health page (areas.md);
[[window]]in~/.config/sioul/config.tomlholds them (examples/config.toml). Without any, the Porch is always open.
Where things are¶
| What | Where |
|---|---|
| Configuration | ~/.config/sioul/config.toml |
| Senders you let in | ~/.config/sioul/known-senders.txt |
| Passwords | the system keyring, service sioul |
| Mail, one Maildir per account, a Maildir++ subfolder per folder | ~/.local/share/sioul/mail/<account>, …/<account>/.Sent |
| Drafts, with a copy of the message each answers | ~/.local/share/sioul/drafts/<draft>.toml, <draft>.eml |
| Where sync stopped, per folder | ~/.local/state/sioul/sync/<account>.toml |
| An account's folders, as last listed | ~/.local/state/sioul/sync/<account>.folders.toml |
| Where the Porch was closed | ~/.local/state/sioul/porch.toml |
Fetching never changes the server: folders are opened with EXAMINE and messages fetched with BODY.PEEK. Sioul writes to the server only when you act: opening a message in the window marks it read, as any client does; archiving, deleting, junking and moving happen ten seconds after you asked, so "Undo" can stop them; sending goes through your provider's SMTP server, and a copy is filed in Sent. What you do elsewhere (read on the phone, deleted in the webmail) comes back at each sync. Removing an account removes its password, not its mail.
Contacts and calendars live in ~/.local/share/sioul/contacts/<account>/<address book>/ and ~/.local/share/sioul/calendars/<account>/<calendar>/, one file per contact or event, readable by khal, khard, pimsync and vdirsyncer. From the terminal: sioul dav add you@example.org (the server is found from the address, or --url), sioul dav sync, sioul contacts [name], sioul contact --name … --email …, sioul agenda [--days 15], sioul event --title … --start 2026-10-05T09:00 [--end …] [--all-day] [--repeat weekly]. OpenPGP: sioul pgp list|make <address>|import <file>|export <fingerprint>|lookup <address>, and sioul mail send … --sign --encrypt.
From the terminal, the same without the ten seconds:
sioul mail folders <account>
sioul mail list <account> [folder]
sioul mail act <file> read|unread|flag|unflag|archive|trash|junk|not-junk|move --to <folder>
sioul mail send --account <account> --to <address> --subject <subject> --body <markdown> [--attach <file>]
sioul mail send --account <account> --reply <file> --body <markdown> # also --reply-all, --forward
Working on the window¶
- Qt's messages: Fedora's Qt sends them to the system journal;
QT_FORCE_STDERR_LOGGING=1brings them back to the terminal. - Images of each page: with
SIOUL_GRAB=<folder>, the window shows each page in turn (a message opened on the Porch included), saves it as<page>.pngand quits;SIOUL_GRAB_STEPSnames another step list. For a check, the runner sets them (below). - A demo, off the network:
SIOUL_DEMO=1keeps Sioul from fetching or sending anything by itself (mail, calendars, GitHub, weather, site icons, antivirus signatures, addresses on the map); it shows what is kept on the computer.tools/demo/make-demo.py --into <folder>writes an invented profile for it, andtools/demo/screenshots.shtakes the website's pictures from it. - Acting on mail in the window:
SIOUL_GRAB_STEPS=actionswithSIOUL_GRABarchives a message and undoes it, deletes another, writes and sends one, saving an image at each step. It writes to the server: only from the test build, against a test server (below). - Linting the QML:
tools/lint-qml.sh, aftercargo build -p sioul-app. - The window's buttons: on a computer, Sioul draws its own title bar, the window's buttons on the side and in the order the desktop uses, read once at start, off the window's thread (
src/desktop.rs,system_layout).SIOUL_BUTTON_LAYOUT, in GNOME's format (close,minimize,maximize:puts them on the left), comes first, to try a layout the desktop does not have. On KDE Plasma, kwinrc's[org.kde.kdecoration2]ButtonsOnLeftandButtonsOnRight, the strongest file first ($XDG_CONFIG_HOME, a Flatpak's$HOST_XDG_CONFIG_HOME,~/.config, each one'skdedefaults/, then$XDG_CONFIG_DIRS), else Plasma's defaults,MSandHIAX(I minimises, A maximises, X closes; the other letters are ignored). On Xfce,xfconf-query -c xfwm4 -p /general/button_layout. On GNOME, Unity, Budgie, Pantheon, Cinnamon and MATE,gsettings get <schema> button-layout, Cinnamon's and MATE's own schemas before GNOME's, and GNOME's own default, close alone on the right, when nothing answers. Elsewhere (sway, i3…), minimise, maximise and close on the right; on a Mac, close, minimise and maximise on the left; on Windows, on the right. In a Flatpak,gsettingsmay read the sandbox's settings rather than the desktop's (untried); the settings portal would read the desktop's. A right click on the bar does nothing: Qt 6.11 has no public call for the window manager's menu (X11's_GTK_SHOW_WINDOW_MENUwould work on KWin; Wayland needs Qt's private Wayland client).
Running the window for a check¶
tools/demo/run.sh [--release] OUT en|fr STEPS [phone] is the one way to start the window for a check, for a person as for an agent: never sioul-app on your own desktop session, nor on your own profile. Started there, a window under test reaches your desktop (the system tray, notifications, D-Bus names, do-not-disturb) and your mail and files. The runner:
- makes a demo profile, anew, in
OUT/profile(tools/demo/make-demo.py), on a weekday afternoon whatever the day (tools/demo/moment.py;RUN_HOUR=19for 19:xx instead), in English or French; - starts the window in a sandbox (bubblewrap; it refuses to run without): the real home out of reach, the profile as the home of a user "demo", the repository read-only; no network (a network namespace of its own, and
SIOUL_DEMO=1); no display (offscreen, software rendering); a D-Bus session and a runtime folder of its own, the session's own runtime folder hidden; the fonts oftools/demo/fonts.conf; 400 seconds at most. The debug build, or the release one with--release; - goes through the step list STEPS, its pictures in
OUT/shots/and the window's messages inOUT/shots/log;phonegives the window a phone's size and layout; - says what went wrong: it prints the log's lines from QML and its errors, and exits with 1 when the window crashed or was stopped, or a script error is in the log.
The step lists are grabber.steps in main.qml, each a series of steps a moment apart. Which a build allows is grab_steps in crates/sioul-app/src/backend.rs: "pages" (each page, the default) always; "demo", "phone" and "drag", pictures alone; on a demo profile only (SIOUL_DEMO=1, which the runner sets), the lists that act in the window: "taskform", "tiles", "review", "rail", "pauses", "blocks", "unsubscribe", "attention", "line", "share-panel", "share-send", "spam", "mail-search", "mail-filters", "security-key", "calls", "words", "movetask", "compose", "attachments" (a message's attachments unfolded in the Reader, a phone's words with phone, nothing opened), "bitwarden-wait" (the unlock dialog waiting for Bitwarden, then its answer: no account set, no server asked), "tray" (the window hidden as to the tray and brought back), "notes-shared" (a note changed on another device while the Notes page shows it: only read, then typed in, the typing kept and a newer version said), "reach" (the status line's button of what reaches you and its card, each state pressed and back to As usual; with phone, at 412 points, what passes the right edge said), "microsoft" (the mail form of a personal Microsoft address, as discovery finds it without the network, then a work one's, what its administrator does unfolded; nothing signed in), "projects-file" (with SIOUL_DEMO_OLD_PROJECTS=1: the projects' file under its first name, renamed from Settings, then a project's page and the form of a new one), "memory" (a minute at rest, then every page and form as "pages" opens them, no picture taken, then the profile's sites; tools/measure-memory.py reads /proc at each moment), and those of the sites ("site-open", "site-quit", "site-during", "site-share", "site-devices", "site-colour"), which tools/check-sites.py and tools/check-colour.py run in a sandbox of their own; every other list archives, sends or syncs, from the test build only, against the test servers below, on test folders, never your own. A list a build does not allow runs "pages". "compose" answers a message with a subject of more than sixty characters, two addresses to answer and a copy, which make-demo.py --compose adds (SIOUL_DEMO_COMPOSE=1 tools/demo/run.sh OUT fr compose phone), then writes a new message and deletes it; with phone, the writing window takes the phone's size too, and each of its pictures names what passes its right edge. tools/demo/screenshots.sh takes the website's pictures with "demo", in a sandbox of its own, on the runner's moment and fonts.
Before installing a release build, a maintainer starts each batch's release build once on a real desktop session, with a throwaway profile: the runner shows nothing of what the desktop itself draws (the system tray, the title bar's buttons where the desktop puts them, its notifications and its do-not-disturb).
The checks before a commit¶
- All at once:
tools/final-pass.sh [FOLDER], from the repository alone, each step's log in FOLDER (a new folder under~/.cache/sioul-final-pass/by default): the JVM checks; each crate's tests in release, one crate at a time, each on a D-Bus session of its own; the two programs in release, and no test hook in them; the messages (tools/check-messages.py); words from outside drawn as plain text (tools/check-plain-text.py, qt-quick.md), QML lint and the QML tests; rustdoc with warnings as errors, as the website's API reference. It stops before a build when less than 1.5 GB is free wheretarget/is (MIN_FREE_GBsets another floor), and exits with 1 when a step failed. It never starts the window: the runner does (above). - The QML tests:
tools/qml-test.sh [tst_name.qml…]runscrates/sioul-app/tests/qml/tst_*.qmlwith Qt 6's runner (Fedora'sqmltestrunner-qt6: a bareqmltestrunnerthere is Qt 5's), offscreen, each component on a stand-in for Sioul that records the calls it makes: the clock and the line at now in the day views, the timelines' drags by mouse and by touch, the costs' tiles and "How was it?", the Bitwarden login chooser and the unlock dialog waiting for Bitwarden's answer, the sounds' fades, the date picker's month arrows named, the status line's button of what reaches you and its card (each state, its lengths, a pause, every control named and nothing past its edge) and do-not-disturb's parts in What reaches you and This phone, a medicine's takes as rows with their time picker, a line's commands apart to copy, the phone's messages on a computer's Porch (Seen and its undo) with the phone's tab for them, the Texts page read again when the sharing brings texts, the conversation open, the draft and the place read back to kept (tst_texts.qml), what Android has not allowed Sioul yet on a phone, on the Porch with its buttons and Not now (tst_access.qml) and in the join's result (tst_join.qml), a ComboBox's list showing "&" as it is written (tst_plaincombobox.qml), an icon in its own colours read again from the other bundled set when its window turns dark or light, and only then (tst_icon.qml), the window light or dark from the setting, the system's colour scheme, its colours and high contrast, following each as it changes (tst_theme.qml), the tray's menu closing the work day or the whole day and a click on its message going to the window (tst_tray.qml), and words from outside holding a picture's tag shown in Sioul's buttons, menus, tooltips, lists and dialog titles, never fetched and never crashing (tst_plaintext.qml, against a stand-in web server,tools/qml-stand-in.py, which the runner starts on 127.0.0.1:18731 for a test that names it). Each test imports the window's QML folder by its relative path (import "../../qml"): no build is needed. - The phone's Java on a computer:
android/jvm-checks/run.sh(android.md). - A notification end to end:
tools/e2e/notifications/run.sh buttons|quit|elsewhere, the real window in the runner's sandbox against a stand-in notification server (A feature, end to end).
Testing against a local mail server¶
Writing to a server and sending are tested against GreenMail, never against real mailboxes. It accepts any login and makes the accounts as mail comes:
podman run -d --name sioul-greenmail -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled' \
-p 127.0.0.1:3993:3993 -p 127.0.0.1:3465:3465 -p 127.0.0.1:3025:3025 -p 127.0.0.1:3143:3143 docker.io/greenmail/standalone:2.1.8
SIOUL_TEST_INSECURE_TLS is set; SIOUL_TEST_PASSWORD stands in for the keyring. Never build Sioul for use with this feature.
cargo build -p sioul-cli -p sioul-app --features sioul-cli/insecure-test-tls,sioul-app/insecure-test-tls
export XDG_CONFIG_HOME=/some/test/folder/config XDG_DATA_HOME=/some/test/folder/data XDG_STATE_HOME=/some/test/folder/state
export SIOUL_TEST_INSECURE_TLS=1 SIOUL_TEST_PASSWORD=any
$XDG_CONFIG_HOME/sioul/config.toml: host = "localhost", port = 3993, security = "tls", smtp_host = "localhost", smtp_port = 3465, smtp_security = "tls". Mail goes in through port 3025 without TLS (Python's smtplib will do), and can be looked at on port 3143.
Contacts and calendars are tested against Radicale, in a Python virtual environment, without authentication:
python3 -m venv /some/test/folder/radicale && /some/test/folder/radicale/bin/pip install radicale
/some/test/folder/radicale/bin/radicale --server-hosts 127.0.0.1:5232 --auth-type none --storage-filesystem-folder /some/test/folder/radicale-data
MKCALENDAR and an address book with an extended MKCOL (curl will do), then sioul dav add you@example.org --url http://127.0.0.1:5232/. The test build allows plain HTTP to this computer only, and only with SIOUL_TEST_INSECURE_TLS. SIOUL_GRAB_STEPS=pim answers an invitation, writes a weekly event and changes a contact in the window.
Google Tasks and GitHub are tested against stand-ins of their APIs, in the test build only: tools/google-tasks-stand-in.py 39871 with SIOUL_TEST_GOOGLE_TASKS=http://127.0.0.1:39871 SIOUL_TEST_GOOGLE_TOKEN=test-token (cargo test -p sioul-sync --features insecure-test-tls -- --ignored stand_in), and tools/github-stand-in.py 39872 with SIOUL_TEST_GITHUB=http://127.0.0.1:39872 SIOUL_TEST_GITHUB_TOKEN=test-token and [github] enabled = true (SIOUL_GRAB_STEPS=github). Google's own servers, its sign-in and GitHub itself are not reached by any test. SIOUL_TEST_MICROSOFT_TOKEN stands in for Microsoft's access token in the test build, as SIOUL_TEST_GOOGLE_TOKEN does for Google's: an account written with auth = "microsoft" and a local server's host then reaches that server with it (in Sioul's own builds, Microsoft's token goes to Microsoft's servers alone, whatever the configuration says). Microsoft's sign-in, its token endpoint and its IMAP and SMTP answers are tested against stand-ins in the unit tests of microsoft.rs, sasl.rs and send.rs; Microsoft itself is reached by none.
OpenPGP is tested against GnuPG in a throwaway GNUPGHOME: sioul pgp make you@example.org makes Alice's key (the test build gives every key SIOUL_TEST_PASSWORD as passphrase and leaves the keyring alone), gpg --quick-generate-key makes Bob's; each imports the other's public key (sioul pgp import, sioul pgp export, gpg --import); sioul mail send --sign --encrypt goes to Bob, whose GnuPG must decrypt it and find a good signature; messages built with GnuPG come back to Alice, and SIOUL_GRAB_STEPS=pgp shows what the reader says of them.