From 2c56e6160d8f4e6bfdc073408002ac6c7aebd6d0 Mon Sep 17 00:00:00 2001 From: Jon Lamb Date: Thu, 4 Apr 2024 03:36:55 -0700 Subject: [PATCH] Add support for Deviant events, add robot framework tests --- .github/workflows/integration_tests.yml | 1 + src/event_record.rs | 68 +- test_system/.gitignore | 7 + test_system/Cargo.toml | 13 +- test_system/config/reflector-config.toml | 3 + test_system/config/workspace.toml | 2 +- test_system/memory.x | 1 - test_system/renode/RttReader.cs | 9 +- test_system/renode/commands.py | 26 + .../renode/robot_frameworkd_setup.resc | 41 + test_system/scripts/get_test_run_id.sh | 23 + test_system/scripts/run_robot_framework.sh | 7 + test_system/scripts/setup_modality.sh | 13 + test_system/{ => scripts}/view_expansion.sh | 6 + test_system/scripts/view_report.sh | 7 + test_system/{ => scripts}/view_rtt.sh | 6 + test_system/specs/tests.speqtr | 11 +- test_system/src/main.rs | 70 +- test_system/tests.robot | 98 ++ .../tools/mutator-server/.cargo/config | 2 + test_system/tools/mutator-server/.gitignore | 2 + test_system/tools/mutator-server/Cargo.lock | 1360 +++++++++++++++++ test_system/tools/mutator-server/Cargo.toml | 15 + test_system/tools/mutator-server/src/main.rs | 257 ++++ .../tools/mutator-server/src/mutator.rs | 100 ++ 25 files changed, 2127 insertions(+), 21 deletions(-) create mode 100644 test_system/renode/commands.py create mode 100644 test_system/renode/robot_frameworkd_setup.resc create mode 100755 test_system/scripts/get_test_run_id.sh create mode 100755 test_system/scripts/run_robot_framework.sh create mode 100755 test_system/scripts/setup_modality.sh rename test_system/{ => scripts}/view_expansion.sh (66%) create mode 100755 test_system/scripts/view_report.sh rename test_system/{ => scripts}/view_rtt.sh (66%) create mode 100644 test_system/tests.robot create mode 100644 test_system/tools/mutator-server/.cargo/config create mode 100644 test_system/tools/mutator-server/.gitignore create mode 100644 test_system/tools/mutator-server/Cargo.lock create mode 100644 test_system/tools/mutator-server/Cargo.toml create mode 100644 test_system/tools/mutator-server/src/main.rs create mode 100644 test_system/tools/mutator-server/src/mutator.rs diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 475ac00..7388b01 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -142,6 +142,7 @@ jobs: docker run \ --name reflector \ --network=host \ + -e MODALITY_RUN_ID="$GITHUB_RUN_NUMBER" \ -e RUST_LOG="modality_defmt=trace" \ -e INGEST_PROTOCOL_PARENT_URL="modality-ingest://127.0.0.1" \ -e MUTATION_PROTOCOL_PARENT_URL="modality-mutation://127.0.0.1" \ diff --git a/src/event_record.rs b/src/event_record.rs index fccb3d0..3c920a6 100644 --- a/src/event_record.rs +++ b/src/event_record.rs @@ -1,9 +1,10 @@ use crate::Error; use defmt_decoder::{Arg, Frame, Location}; use defmt_parser::{Fragment, ParserMode}; +use modality_api::Uuid; use modality_api::{AttrVal, BigInt, Nanoseconds, TimelineId}; use std::collections::BTreeMap; -use tracing::warn; +use tracing::{debug, warn}; pub type EventAttributes = BTreeMap; @@ -174,6 +175,8 @@ impl EventRecord { formatted_string.clone().into(), ); + let mut deviant_event = None; + for (frag_idx, frag) in fragments.iter().enumerate() { match frag { Fragment::Literal(l) => { @@ -181,7 +184,9 @@ impl EventRecord { // Look for :: convention if frag_idx == 0 { if let Some((n, rem)) = s.split_once("::") { - name = n.trim().to_owned().into(); + let ev_name = n.trim(); + deviant_event = DeviantEventKind::from_event_name(ev_name); + name = ev_name.to_owned().into(); s = rem; } } @@ -219,7 +224,10 @@ impl EventRecord { // SAFETY: decoder/frame already checks args and params let arg = &f.args()[p.index]; match arg_to_attr_val(arg) { - None => { + Some(val) => { + attributes.insert(Self::attr_key(&key), val); + } + None if deviant_event.is_none() => { warn!( formatted_string, attr_key = key, @@ -227,8 +235,29 @@ impl EventRecord { "Unsupported arg type" ); } - Some(val) => { - attributes.insert(Self::attr_key(&key), val); + None => { + // We have a deviant event, special case handle the UUID slices + match key.as_ref() { + "mutator.id" | "mutation.id" => { + if let Arg::Slice(uuid_bytes) = arg { + if let Ok(uuid) = Uuid::try_from(uuid_bytes.clone()) { + debug!(attr_key = key, attr_val = %uuid, "Found Deviant attribute"); + attributes.insert( + Self::attr_key(&key), + uuid_to_integer_attr_val(&uuid), + ); + } else { + warn!(attr_key = key, "Invalid UUID bytes"); + } + } else { + warn!( + attr_key = key, + "Unsupported argument type for Deviant event" + ); + } + } + _ => (), + } } } } @@ -375,6 +404,35 @@ fn ts_from_arg(arg: &Arg<'_>) -> Option { }) } +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +pub enum DeviantEventKind { + MutatorAnnounced, + MutatorRetired, + MutationCmdCommunicated, + MutationClearCommunicated, + MutationTriggered, + MutationInjected, +} + +impl DeviantEventKind { + fn from_event_name(event_name: &str) -> Option { + use DeviantEventKind::*; + Some(match event_name { + "modality.mutator.announced" => MutatorAnnounced, + "modality.mutator.retired" => MutatorRetired, + "modality.mutation.command_communicated" => MutationCmdCommunicated, + "modality.mutation.clear_communicated" => MutationClearCommunicated, + "modality.mutation.triggered" => MutationTriggered, + "modality.mutation.injected" => MutationInjected, + _ => return None, + }) + } +} + +fn uuid_to_integer_attr_val(u: &Uuid) -> AttrVal { + i128::from_le_bytes(*u.as_bytes()).into() +} + #[cfg(test)] mod test { use super::*; diff --git a/test_system/.gitignore b/test_system/.gitignore index 265b7f5..f9c95c9 100644 --- a/test_system/.gitignore +++ b/test_system/.gitignore @@ -1,2 +1,9 @@ /target .gdb_history +log.html +logs/ +report.html +robot_output.xml +snapshots/ +results-tests.robot.xml +.runids diff --git a/test_system/Cargo.toml b/test_system/Cargo.toml index c2451fc..9c31b04 100644 --- a/test_system/Cargo.toml +++ b/test_system/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" authors = ["Jon Lamb"] build = "build.rs" +exclude = ["tools/mutator-server"] [[bin]] name = "atsamd-rtic-firmware" @@ -40,7 +41,7 @@ defmt = { git = "https://github.com/knurling-rs/defmt.git", rev = "4db33ca5df8d7 [profile.release] codegen-units = 1 debug = 2 -lto = true +lto = false [package.metadata.renode] name = 'atsamd-rtic' @@ -50,6 +51,7 @@ machine-name = 'atsamd' using-sysbus = true init-commands = [ 'include @renode/RttReader.cs', + 'include @renode/commands.py', ] platform-descriptions = [ 'renode/atsamd51g19a.repl', @@ -77,7 +79,14 @@ pre-start-commands = [ 'logLevel -1 RttReader', 'RttReader Start', ] -start = 'emulation RunFor "00:00:20"' +# Includes the Deviant staged mutation related +#'write_staged_mutation "88b565a8-455b-4993-9779-9f6d4004d6d5" "d135b4b9-64c9-4d0d-b2bb-621e37ca29f7"', +reset = ''' + sysbus LoadELF $bin + clear_deviant_noint_vars +''' +start = 'emulation RunFor "00:00:15"' post-start-commands = [ + 'RttReader Stop', 'quit' ] diff --git a/test_system/config/reflector-config.toml b/test_system/config/reflector-config.toml index 08ad122..a8d7358 100644 --- a/test_system/config/reflector-config.toml +++ b/test_system/config/reflector-config.toml @@ -7,6 +7,9 @@ additional-timeline-attributes = [ "ci_commit='${GITHUB_SHA-local}'", "ci_git_commit='${GIT_COMMIT-local}'", ] +override-timeline-attributes = [ + "run_id='${MODALITY_RUN_ID-1}'", +] [plugins.ingest.importers.defmt] additional-timeline-attributes = [ diff --git a/test_system/config/workspace.toml b/test_system/config/workspace.toml index efaee41..584dd7e 100644 --- a/test_system/config/workspace.toml +++ b/test_system/config/workspace.toml @@ -1,5 +1,5 @@ [[segmentation-rule]] name = "by-run-id" attributes = ["run_id"] -segment-name-template = "Run {timeline.run_id}" +segment-name-template = "{timeline.run_id}" causally-partition-segments = true diff --git a/test_system/memory.x b/test_system/memory.x index 4ecd4ec..dd1c7b3 100644 --- a/test_system/memory.x +++ b/test_system/memory.x @@ -5,4 +5,3 @@ MEMORY RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K } _stack_start = ORIGIN(RAM) + LENGTH(RAM); - diff --git a/test_system/renode/RttReader.cs b/test_system/renode/RttReader.cs index 0330dca..5d03070 100644 --- a/test_system/renode/RttReader.cs +++ b/test_system/renode/RttReader.cs @@ -60,7 +60,12 @@ public void Start() { this.NoisyLog("Starting RTT reading"); pollTimer.Enabled = true; } - + + public void Stop() { + this.NoisyLog("Stopping RTT reading"); + pollTimer.Enabled = false; + } + private void TimerLimitReachedCallback() { if(controlBlockAddress == 0) @@ -135,7 +140,7 @@ private void readRttBuffer() { break; } - + uint addr = chBufferPtr + read; machine.SystemBus.ReadBytes((ulong) addr, (int) count, buffer, (int) total); diff --git a/test_system/renode/commands.py b/test_system/renode/commands.py new file mode 100644 index 0000000..8694628 --- /dev/null +++ b/test_system/renode/commands.py @@ -0,0 +1,26 @@ +from Antmicro import Renode +import uuid + +def mc_clear_deviant_noint_vars(): + sysbus = self.Machine["sysbus"] + var_mutation_staged_addr = sysbus.GetSymbolAddress("DEVIANT_MUTATION_STAGED") + sysbus.WriteDoubleWord(var_mutation_staged_addr, 0) + +def mc_write_staged_mutation(mutator_uuid_str, mutation_uuid_str): + print("Writing staged mutation, mutator_id = %s, mutation_id = %s" % (mutator_uuid_str, mutation_uuid_str)) + mutator_uuid = uuid.UUID(mutator_uuid_str) + mutation_uuid = uuid.UUID(mutation_uuid_str) + + sysbus = self.Machine["sysbus"] + var_mutation_staged_addr = sysbus.GetSymbolAddress("DEVIANT_MUTATION_STAGED") + var_mutator_id_addr = sysbus.GetSymbolAddress("DEVIANT_MUTATOR_ID"); + var_mutation_id_addr = sysbus.GetSymbolAddress("DEVIANT_MUTATION_ID"); + + for offset, b in enumerate(mutator_uuid.bytes): + val = int(b.encode('hex'), 16) + sysbus.WriteByte(var_mutator_id_addr + offset, val) + for offset, b in enumerate(mutation_uuid.bytes): + val = int(b.encode('hex'), 16) + sysbus.WriteByte(var_mutation_id_addr + offset, val) + + sysbus.WriteDoubleWord(var_mutation_staged_addr, 1) diff --git a/test_system/renode/robot_frameworkd_setup.resc b/test_system/renode/robot_frameworkd_setup.resc new file mode 100644 index 0000000..d56813a --- /dev/null +++ b/test_system/renode/robot_frameworkd_setup.resc @@ -0,0 +1,41 @@ +:name: atsamd-rtic +:description: Runs the example firmware in Renode + +using sysbus + +mach create "atsamd" + +include @renode/RttReader.cs +include @renode/commands.py + +$bin = @target/thumbv7em-none-eabihf/release/atsamd-rtic-firmware + +machine LoadPlatformDescription @renode/atsamd51g19a.repl +machine LoadPlatformDescriptionFromString +""" +sercom0: UART.SAMD5_UART @ sysbus 0x40003000 + ->nvic@48 +""" + +sysbus.nvic Frequency 10000000000 +emulation CreateUARTHub "uarthub" +connector Connect sercom0 uarthub +connector Connect sercom3 uarthub +machine CreateRttReader +RttReader CreateFileBackend @/tmp/rtt_log.bin true +logLevel 3 sercom0 +logLevel 3 sercom3 +logLevel 3 sysbus +logLevel 3 nvic +logLevel 3 dwt +logLevel -1 RttReader +RttReader Start + +macro reset +""" + sysbus LoadELF $bin +""" + +runMacro $reset + +clear_deviant_noint_vars diff --git a/test_system/scripts/get_test_run_id.sh b/test_system/scripts/get_test_run_id.sh new file mode 100755 index 0000000..8e9beda --- /dev/null +++ b/test_system/scripts/get_test_run_id.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -euo pipefail + +dir=".runids" +test_name="$1" +runid_file="$dir/$test_name" + +mkdir -p "$dir" + +runid=0 + +if [ -f "$runid_file" ]; then + runid=$(cat "$runid_file") +fi + +runid=$((runid+1)) + +echo "$runid" > "$runid_file" + +echo "$runid" + +exit 0 diff --git a/test_system/scripts/run_robot_framework.sh b/test_system/scripts/run_robot_framework.sh new file mode 100755 index 0000000..9057bfc --- /dev/null +++ b/test_system/scripts/run_robot_framework.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +renode-test --kill-stale-renode-instances tests.robot + +exit 0 diff --git a/test_system/scripts/setup_modality.sh b/test_system/scripts/setup_modality.sh new file mode 100755 index 0000000..300461e --- /dev/null +++ b/test_system/scripts/setup_modality.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -euo pipefail + +modality user create --use admin + +modality workspace create --use ci-tests config/workspace.toml + +modality segment use --latest + +conform spec create --file specs/tests.speqtr tests + +exit 0 diff --git a/test_system/view_expansion.sh b/test_system/scripts/view_expansion.sh similarity index 66% rename from test_system/view_expansion.sh rename to test_system/scripts/view_expansion.sh index 48b58e9..fa32586 100755 --- a/test_system/view_expansion.sh +++ b/test_system/scripts/view_expansion.sh @@ -1 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + rustfmt --emit stdout target/rtic-expansion.rs | vim +':setlocal buftype=nofile filetype=rust' - + +exit 0 diff --git a/test_system/scripts/view_report.sh b/test_system/scripts/view_report.sh new file mode 100755 index 0000000..805abe4 --- /dev/null +++ b/test_system/scripts/view_report.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +firefox $PWD/report.html + +exit 0 diff --git a/test_system/view_rtt.sh b/test_system/scripts/view_rtt.sh similarity index 66% rename from test_system/view_rtt.sh rename to test_system/scripts/view_rtt.sh index 0ad69b2..5953ad4 100755 --- a/test_system/view_rtt.sh +++ b/test_system/scripts/view_rtt.sh @@ -1 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + cat /tmp/rtt_log.bin | defmt-print -e target/thumbv7em-none-eabihf/release/atsamd-rtic-firmware + +exit 0 diff --git a/test_system/specs/tests.speqtr b/test_system/specs/tests.speqtr index 4023502..cf0e193 100644 --- a/test_system/specs/tests.speqtr +++ b/test_system/specs/tests.speqtr @@ -4,11 +4,11 @@ # @rtos_mode = "rtic1" behavior "Basic Checks" prohibited case "Start event comes first" - AUXON_TRACE_START@init <- *@* + AUXON_TRACE_START @ init <- *@* end nominal case "Start event checks" - AUXON_TRACE_START@init (exists(_.version) AND exists(_.task) AND _.level = "trace") aggregate count() = 1 + AUXON_TRACE_START @ init (exists(_.version) AND exists(_.task) AND _.level = "trace") aggregate count() = 1 end end @@ -40,13 +40,16 @@ behavior "Context Switching" -> AUXON_TASK_EXIT @ blinky # back on the ISR -> AUXON_CONTEXT_RETURN @ FREQM + end + recovery case "Mutation causes panic" + init -> panic @ consumer (_.msg = "*Message corruption!") end end -behavior "System Shutdown" +behavior "Nominal System Shutdown" nominal case "System panics when done" - panic @ consumer (_.level = "error") aggregate count() = 1 + panic @ consumer (_.level = "error" AND _.msg = "*data == 6") aggregate count() = 1 end end diff --git a/test_system/src/main.rs b/test_system/src/main.rs index c464995..dab6075 100644 --- a/test_system/src/main.rs +++ b/test_system/src/main.rs @@ -18,7 +18,8 @@ mod app { IoSet3, Sercom0, Sercom3, }, }; - use defmt::{debug, info, warn}; + use core::mem::MaybeUninit; + use defmt::{debug, info, trace, warn}; use dwt_systick_monotonic::{DwtSystick, ExtU64}; type Uart0Pads = uart::Pads, Pin>; @@ -37,8 +38,27 @@ mod app { struct Local { uart0: Uart0, uart3: Uart3, + staged_mutation: Option<(DeviantUuid, DeviantUuid)>, } + /// Mutator/Mutation UUID byte array + type DeviantUuid = [u8; 16]; + + /// Deviant staged-mutation related. + /// These get initialized by renode on startup based on whether + /// or not a mutation is staged. + #[link_section = ".uninit.deviant0"] + #[no_mangle] + static mut DEVIANT_MUTATION_STAGED: MaybeUninit = MaybeUninit::uninit(); + + #[link_section = ".uninit.deviant1"] + #[no_mangle] + static mut DEVIANT_MUTATOR_ID: MaybeUninit = MaybeUninit::uninit(); + + #[link_section = ".uninit.deviant2"] + #[no_mangle] + static mut DEVIANT_MUTATION_ID: MaybeUninit = MaybeUninit::uninit(); + #[init] fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) { defmt::timestamp!("{=u64:us}", monotonics::now().ticks()); @@ -90,9 +110,37 @@ mod app { crate::built_info::GIT_COMMIT_HASH.unwrap_or("NA"), ); + // Handle staged deviant mutation, if one exists + let mutation_staged = unsafe { DEVIANT_MUTATION_STAGED.assume_init() }; + let staged_mutation = if mutation_staged != 0 { + let mutator_id = unsafe { DEVIANT_MUTATOR_ID.assume_init() }; + let mutation_id = unsafe { DEVIANT_MUTATION_ID.assume_init() }; + + // Write down announcement and communication in the log + trace!( + "modality.mutator.announced::mutator.id={=[u8; 16]}", + mutator_id + ); + trace!("modality.mutation.command_communicated::mutation.success={=bool},mutator.id={=[u8; 16]},mutation.id={=[u8; 16]}", + true, + mutator_id, + mutation_id); + Some((mutator_id, mutation_id)) + } else { + None + }; + blinky::spawn().unwrap(); - (Shared {}, Local { uart0, uart3 }, init::Monotonics(mono)) + ( + Shared {}, + Local { + uart0, + uart3, + staged_mutation, + }, + init::Monotonics(mono), + ) } #[idle] @@ -129,12 +177,20 @@ mod app { data: u16, } - #[task(local = [data: u16 = 0])] + #[task(local = [data: u16 = 0, staged_mutation])] fn producer(ctx: producer::Context) { *ctx.local.data += 1; - let msg = IpcMessage { + let mut msg = IpcMessage { data: *ctx.local.data, }; + if let Some((mutator_id, mutation_id)) = ctx.local.staged_mutation.take() { + // Write down the injection in the log + trace!("modality.mutation.injected::mutation.success={=bool},mutator.id={=[u8; 16]},mutation.id={=[u8; 16]}", + true, + mutator_id, + mutation_id); + msg.data = u16::MAX; + } info!("send_data::data={=u16}", msg.data); consumer::spawn(msg).ok(); } @@ -143,8 +199,10 @@ mod app { fn consumer(_ctx: consumer::Context, msg: IpcMessage) { info!("recv_data::data={=u16}", msg.data); - if msg.data == 6 { - panic!("data == 6"); + match msg.data { + u16::MAX => panic!("Message corruption!"), + 6 => panic!("data == 6"), + _ => (), } } } diff --git a/test_system/tests.robot b/test_system/tests.robot new file mode 100644 index 0000000..d64d657 --- /dev/null +++ b/test_system/tests.robot @@ -0,0 +1,98 @@ +*** Settings *** +Documentation Integration test suite +Default Tags test_system +Library Process + +# These are the defaults provided by renode, automatically set if not supplied +Suite Setup Test System Suite Setup +Suite Teardown Test System Suite Teardown +Test Setup Test System Test Setup +Test Teardown Test Teardown +Resource ${RENODEKEYWORDS} + +*** Variables *** +${MUTATOR_SERVER} ${CURDIR}/tools/mutator-server/target/x86_64-unknown-linux-gnu/release/mutator-server +${MUTATOR_SERVER_PORT} 9785 +${RUN_ID_SCRIPT} ${CURDIR}/scripts/get_test_run_id.sh +${RESC} ${CURDIR}/renode/robot_frameworkd_setup.resc +${FW_ELF} ${CURDIR}/target/thumbv7em-none-eabihf/release/atsamd-rtic-firmware +${RTT_LOG} /tmp/rtt_log.bin +${REFLECTOR_CONFIG} ${CURDIR}/config/reflector-config.toml +${SPEC_NAME} tests + +*** Keywords *** +Test System Suite Setup + Setup + Build System + +Test System Suite Teardown + Terminate All Processes + Teardown + +Test System Test Setup + Test Setup + Prepare Machine + +Run Command + [Arguments] ${cmd_and_args} + ${result} = Run Process ${cmd_and_args} shell=true + IF ${result.rc} != 0 + Log To Console ${result.stdout} console=yes + Log To Console ${result.stderr} console=yes + END + Should Be Equal As Integers ${result.rc} 0 + RETURN ${result} + +Build System + Build Firmware + Build Mutator Server + +Build Firmware + Run Command cargo build --release + +Build Mutator Server + Run Command cd tools/mutator-server && cargo build --release + +Prepare Machine + Execute Command path add @${CURDIR} + Execute Script ${RESC} + +Start Mutator Server + ${process} Start Process ${MUTATOR_SERVER} alias=mutator-server + Sleep 1s + +Create Mutation + Run Command deviant mutation create + ${result} Run Command netcat -W 1 127.0.0.1 ${MUTATOR_SERVER_PORT} + ${deviant_ids} Evaluate json.loads("""${result.stdout}""") json + Set Test Variable ${MUTATOR_ID} ${deviant_ids['mutator_id']} + Set Test Variable ${MUTATION_ID} ${deviant_ids['mutation_id']} + +Import Data + ${runid} Run Command ${RUN_ID_SCRIPT} "${TEST NAME}" + Set environment variable MODALITY_RUN_ID "${TEST NAME}::${runid.stdout}" + Run Command modality-reflector import --config ${REFLECTOR_CONFIG} defmt --elf-file ${FW_ELF} ${RTT_LOG} + Run Command modality workspace sync-indices + +Evaluate Specs + Run Command conform spec eval --name ${SPEC_NAME} + +*** Test Cases *** +Nominal System Execution + [Documentation] Boots the system and runs for a period of time + [Tags] firmware + + Execute Command emulation RunFor "00:00:12" + Import Data + Evaluate Specs + +Mutated System Execution + [Documentation] Boots the system with a mutation and runs for a period of time + [Tags] firmware deviant mutation + + Start Mutator Server + Create Mutation + Execute Command write_staged_mutation "${MUTATOR_ID}" "${MUTATION_ID}" + Execute Command emulation RunFor "00:00:15" + Import Data + Evaluate Specs diff --git a/test_system/tools/mutator-server/.cargo/config b/test_system/tools/mutator-server/.cargo/config new file mode 100644 index 0000000..2f05654 --- /dev/null +++ b/test_system/tools/mutator-server/.cargo/config @@ -0,0 +1,2 @@ +[build] +target = "x86_64-unknown-linux-gnu" diff --git a/test_system/tools/mutator-server/.gitignore b/test_system/tools/mutator-server/.gitignore new file mode 100644 index 0000000..265b7f5 --- /dev/null +++ b/test_system/tools/mutator-server/.gitignore @@ -0,0 +1,2 @@ +/target +.gdb_history diff --git a/test_system/tools/mutator-server/Cargo.lock b/test_system/tools/mutator-server/Cargo.lock new file mode 100644 index 0000000..922f664 --- /dev/null +++ b/test_system/tools/mutator-server/Cargo.lock @@ -0,0 +1,1360 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-trait" +version = "0.1.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "auxon-sdk" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db9dc06fbd8a1c73f082294a23e1f00b2cc1aecade7886e2f8da929926afb677" +dependencies = [ + "async-trait", + "clap", + "dirs", + "exitcode", + "futures", + "hex", + "lazy_static", + "minicbor", + "minicbor-io", + "native-tls", + "nix", + "ordered-float", + "regex", + "serde", + "thiserror", + "tokio", + "tokio-native-tls", + "tokio-util", + "toml", + "tracing", + "tracing-subscriber", + "url", + "uuid", +] + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "exitcode" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" + +[[package]] +name = "fastrand" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minicbor" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "124d887cb82f0b1469bdac3d1b65764a381eed1a54fdab0070e5772b13114521" +dependencies = [ + "minicbor-derive", +] + +[[package]] +name = "minicbor-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f79d5d3fb4f93c77ef7b97065fb65efe6abe670795ad8bc5be9c0e12005290" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "minicbor-io" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a8666e08077a8adb373956102bfd80910d9ed842c32cfe97f96cf9f8a1277e" +dependencies = [ + "futures-core", + "futures-io", + "futures-util", + "minicbor", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "mutator-server" +version = "0.1.0" +dependencies = [ + "auxon-sdk", + "clap", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber", + "url", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-float" +version = "3.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" +dependencies = [ + "num-traits", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "security-framework" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom", + "serde", + "sha1_smol", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" diff --git a/test_system/tools/mutator-server/Cargo.toml b/test_system/tools/mutator-server/Cargo.toml new file mode 100644 index 0000000..978529f --- /dev/null +++ b/test_system/tools/mutator-server/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "mutator-server" +version = "0.1.0" +edition = "2021" + +[dependencies] +auxon-sdk = { version = "1.2", features = ["modality", "deviant"] } +clap = { version = "4.3", features = ["derive"] } +tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync", "time", "io-util", "net", "fs", "signal", "process"] } +thiserror = "1.0.43" +url = { version = "2.1", features = ["serde"] } +tracing-subscriber = "0.3" +tracing = "0.1" +serde = { version = "1.0", features=["derive"] } +serde_json = { version = "1.0" } diff --git a/test_system/tools/mutator-server/src/main.rs b/test_system/tools/mutator-server/src/main.rs new file mode 100644 index 0000000..8b69759 --- /dev/null +++ b/test_system/tools/mutator-server/src/main.rs @@ -0,0 +1,257 @@ +use crate::mutator::{ + failure_mutator_descriptor, BasicMutator, MutatorActuator, MutatorActuatorDescriptor, +}; +use auxon_sdk::{ + auth_token::AuthToken, + mutation_plane::{ + protocol::{LeafwardsMessage, RootwardsMessage, MUTATION_PROTOCOL_VERSION}, + types::{AttrKv, AttrKvs, ParticipantId}, + }, + mutation_plane_client::parent_connection::MutationParentConnection, +}; +use clap::Parser; +use std::env; +use tokio::{io::AsyncWriteExt, net::TcpListener, sync::mpsc}; +use url::Url; + +mod mutator; + +#[derive(Parser, Debug, Clone)] +#[command(version)] +struct Opts { + /// Address to bind to + #[arg(long, default_value = "127.0.0.1:9785")] + addr: String, +} + +const MUTATION_PROTOCOL_PARENT_URL_ENV_VAR: &str = "MUTATION_PROTOCOL_PARENT_URL"; +const MUTATION_PROTOCOL_PARENT_URL_DEFAULT: &str = "modality-mutation://127.0.0.1:14192"; + +#[tokio::main] +async fn main() -> Result<(), Box> { + match do_main().await { + Ok(()) => Ok(()), + Err(e) => { + tracing::error!("{}", e); + Err(e) + } + } +} + +#[derive(Debug, Clone, serde::Serialize)] +struct DeviantIds { + mutator_id: String, + mutation_id: String, +} + +async fn do_main() -> Result<(), Box> { + tracing_subscriber::fmt::init(); + let opts = Opts::parse(); + + let mut_plane_pid = ParticipantId::allocate(); + let mut_url = mutation_proto_parent_url().expect("Mutation protocol parent URL"); + let auth_token = AuthToken::load().expect("Auth token for mutation client"); + let allow_insecure_tls = true; + tracing::info!(url = %mut_url, "Connection to mutation plane"); + let mut mut_plane_conn = + MutationParentConnection::connect(&mut_url, allow_insecure_tls).await?; + mut_plane_conn + .write_msg(&RootwardsMessage::ChildAuthAttempt { + child_participant_id: mut_plane_pid, + version: MUTATION_PROTOCOL_VERSION, + token: auth_token.as_ref().to_vec(), + }) + .await?; + + let auth_outcome = mut_plane_conn.read_msg().await?; + match auth_outcome { + LeafwardsMessage::ChildAuthOutcome { + child_participant_id, + version: _, + ok, + message, + } => { + if child_participant_id == mut_plane_pid { + if !ok { + return Err(format!("Mutation plane authorization failed. {message:?}").into()); + } + } else { + return Err( + "Mutation plane auth outcome received for a different participant" + .to_string() + .into(), + ); + } + } + resp => { + return Err(format!("Mutation plane unexpected auth response. Got {resp:?}").into()) + } + } + + let (tx, mut rx) = mpsc::channel(32); + + let tcp_task_join_handle = tokio::spawn(async move { + tracing::info!(addr = opts.addr, "Listening"); + let listener = TcpListener::bind(opts.addr).await.unwrap(); + loop { + let (mut socket, client_addr) = listener.accept().await.unwrap(); + tracing::info!(client = %client_addr, "Client connected"); + let ids = match rx.recv().await { + Some(msg) => msg, + None => return, + }; + let msg = serde_json::to_string(&ids).unwrap(); + socket.write_all(msg.as_bytes()).await.unwrap(); + } + }); + + let mut_plane_task_join_handle = tokio::spawn(async move { + let mut server = MutatorServer::new(mut_plane_pid, mut_plane_conn, tx); + server.run().await; + }); + + tokio::select! { + _ = tokio::signal::ctrl_c() => { + tracing::info!("User signaled shutdown"); + } + _ = mut_plane_task_join_handle => { + tracing::warn!("Mutator server returned unexpectedly"); + } + _ = tcp_task_join_handle => { + tracing::warn!("TCP server returned unexpectedly"); + } + }; + + Ok(()) +} + +struct MutatorServer { + mut_plane_pid: ParticipantId, + mut_plane_conn: MutationParentConnection, + mutator: BasicMutator, + sender: mpsc::Sender, +} + +impl MutatorServer { + pub fn new( + mut_plane_pid: ParticipantId, + mut_plane_conn: MutationParentConnection, + sender: mpsc::Sender, + ) -> Self { + let mutator = BasicMutator::new(failure_mutator_descriptor()); + Self { + mut_plane_pid, + mut_plane_conn, + mutator, + sender, + } + } + + pub async fn register_mutator(&mut self) { + let announcement = mutator_announcement(self.mut_plane_pid, &self.mutator); + self.mut_plane_conn.write_msg(&announcement).await.unwrap(); + } + + pub async fn run(&mut self) { + self.register_mutator().await; + loop { + let msg = self.mut_plane_conn.read_msg().await.unwrap(); + self.handle_msg(msg).await; + if let Some(mutation_id) = self.mutator.active_mutation() { + let ids = DeviantIds { + mutator_id: self.mutator.mutator_id().to_string(), + mutation_id: mutation_id.to_string(), + }; + self.sender.send(ids).await.unwrap(); + self.mutator.reset(); + } + } + } + + async fn handle_msg(&mut self, msg: LeafwardsMessage) { + match msg { + LeafwardsMessage::RequestForMutatorAnnouncements {} => { + tracing::info!("Announcing mutator"); + let announcement = mutator_announcement(self.mut_plane_pid, &self.mutator); + self.mut_plane_conn.write_msg(&announcement).await.unwrap(); + } + LeafwardsMessage::NewMutation { + mutator_id, + mutation_id, + maybe_trigger_mask: _, + params, + } => { + if mutator_id == self.mutator.mutator_id() { + let params = params + .0 + .into_iter() + .map(|kv| (kv.key.into(), kv.value)) + .collect(); + tracing::info!(mutator_id = %mutator_id, mutation_id = %mutation_id, "Injecting mutation"); + self.mutator.inject(mutation_id, params); + } else { + tracing::warn!(mutator_id = %mutator_id, "Failed to handle new mutation, mutator not hosted by this client"); + } + } + LeafwardsMessage::ClearSingleMutation { + mutator_id, + mutation_id, + reset_if_active: _, + } => { + tracing::info!(mutator_id = %mutator_id, mutation_id = %mutation_id, "Ignoring request to clear mutation"); + } + LeafwardsMessage::ClearMutationsForMutator { + mutator_id, + reset_if_active: _, + } => { + tracing::info!(mutator_id = %mutator_id, "Ignoring request to clear mutations"); + } + LeafwardsMessage::ClearMutations {} => { + tracing::info!("Ignoring request to clear all mutations"); + } + msg => tracing::warn!( + message = msg.name(), + "Ignoring mutation plane leafwards message" + ), + } + } +} + +fn mutator_announcement( + participant_id: ParticipantId, + m: &M, +) -> RootwardsMessage { + let mutator_attrs = m + .get_description_attributes() + .map(|(k, value)| AttrKv { + key: k.to_string(), + value, + }) + .collect(); + RootwardsMessage::MutatorAnnouncement { + participant_id, + mutator_id: m.mutator_id(), + mutator_attrs: AttrKvs(mutator_attrs), + } +} + +#[derive(Debug, thiserror::Error)] +enum MutationProtocolUrlError { + #[error( + "The MUTATION_PROTOCOL_PARENT_URL environment variable contained a non-UTF-8-compatible string" + )] + EnvVarSpecifiedMutationProtoParentUrlNonUtf8, + + #[error("Mutation protocol parent URL error")] + MutationProtoParentUrl(#[from] url::ParseError), +} + +fn mutation_proto_parent_url() -> Result { + match env::var(MUTATION_PROTOCOL_PARENT_URL_ENV_VAR) { + Ok(val) => Ok(Url::parse(&val)?), + Err(env::VarError::NotUnicode(_)) => { + Err(MutationProtocolUrlError::EnvVarSpecifiedMutationProtoParentUrlNonUtf8) + } + Err(env::VarError::NotPresent) => Ok(Url::parse(MUTATION_PROTOCOL_PARENT_URL_DEFAULT)?), + } +} diff --git a/test_system/tools/mutator-server/src/mutator.rs b/test_system/tools/mutator-server/src/mutator.rs new file mode 100644 index 0000000..e9c1dc9 --- /dev/null +++ b/test_system/tools/mutator-server/src/mutator.rs @@ -0,0 +1,100 @@ +use auxon_sdk::{ + api::{AttrKey, AttrType, AttrVal}, + mutation_plane::types::{MutationId, MutatorId}, + mutator_protocol::descriptor::{owned::*, MutatorDescriptor}, +}; +use std::collections::{BTreeMap, HashMap}; + +pub type MutatorParams = BTreeMap; + +/// This is a specialized/infallible version of SyncMutatorActuator +pub trait MutatorActuator { + fn mutator_id(&self) -> MutatorId; + + fn inject(&mut self, mutation_id: MutationId, params: BTreeMap); + + fn reset(&mut self); +} + +pub trait MutatorActuatorDescriptor: MutatorActuator + MutatorDescriptor { + fn as_dyn(&mut self) -> &mut dyn MutatorActuatorDescriptor; +} + +#[derive(Debug)] +pub struct BasicMutator { + mutator_id: MutatorId, + descriptor: OwnedMutatorDescriptor, + active_mutation: Option, +} + +impl BasicMutator { + pub fn new(descriptor: OwnedMutatorDescriptor) -> Self { + Self { + mutator_id: MutatorId::allocate(), + descriptor, + active_mutation: None, + } + } + + #[allow(dead_code)] + pub fn is_active(&self) -> bool { + self.active_mutation.is_some() + } + + pub fn active_mutation(&self) -> Option { + self.active_mutation + } +} + +impl MutatorActuatorDescriptor for BasicMutator { + fn as_dyn(&mut self) -> &mut dyn MutatorActuatorDescriptor { + self + } +} + +impl MutatorDescriptor for BasicMutator { + fn get_description_attributes(&self) -> Box + '_> { + self.descriptor.clone().into_description_attributes() + } +} + +impl MutatorActuator for BasicMutator { + fn mutator_id(&self) -> MutatorId { + self.mutator_id + } + + fn inject(&mut self, mutation_id: MutationId, params: MutatorParams) { + assert!(params.len() == 1, "BasicMutator expects 1 parameter"); + self.active_mutation = Some(mutation_id); + } + + fn reset(&mut self) { + self.active_mutation = None; + } +} + +pub fn failure_mutator_descriptor() -> OwnedMutatorDescriptor { + OwnedMutatorDescriptor { + name: "Producer message corruption".to_owned().into(), + description: "Corrupt a message in the producer task".to_owned().into(), + layer: MutatorLayer::Operational.into(), + group: "system".to_owned().into(), + operation: MutatorOperation::Corrupt.into(), + statefulness: MutatorStatefulness::Permanent.into(), + organization_custom_metadata: OrganizationCustomMetadata::new( + "system".to_string(), + HashMap::from([ + ("id".to_string(), 1_i64.into()), + ("name".to_string(), "rv234".into()), + ("component_name".to_string(), "power-gateway".into()), + ]), + ), + params: vec![ + OwnedMutatorParamDescriptor::new(AttrType::Integer, "payload".to_owned()) + .unwrap() + .with_description("Corrupt payload") + .with_value_min(32) + .with_value_max(128), + ], + } +}