From 77501a599787fb183ac616032e0241c4f9dd118f Mon Sep 17 00:00:00 2001 From: sjaffery Date: Thu, 23 Nov 2023 13:48:42 +0530 Subject: [PATCH] Revert "copying tsp-instrument from tsp-toolkit-kic-cli" This reverts commit 1acf97b4aa42e198ecdbf969312c8f9262dce9d3. --- Cargo.lock | 1489 -------------------- Cargo.toml | 27 - src/error.rs | 149 -- src/instrument/firmware.rs | 12 - src/instrument/info.rs | 178 --- src/instrument/language.rs | 63 - src/instrument/login.rs | 96 -- src/instrument/mod.rs | 66 - src/instrument/script.rs | 67 - src/interface/async_stream.rs | 170 --- src/interface/connection_addr.rs | 32 - src/interface/mod.rs | 31 - src/interface/usbtmc.rs | 174 --- src/lib.rs | 32 - src/model/ki2600.rs | 980 ------------- src/model/mod.rs | 27 - src/model/resources/flashUtil.tsp | 185 --- src/model/tti.rs | 970 ------------- src/model/versatest.rs | 994 ------------- src/test_util/mod.rs | 6 - src/test_util/simple_fake_binary_fw.chunk0 | Bin 1024 -> 0 bytes src/test_util/simple_fake_binary_fw.chunk1 | Bin 1024 -> 0 bytes src/test_util/simple_fake_binary_fw.chunk2 | Bin 1024 -> 0 bytes src/test_util/simple_fake_binary_fw.chunk3 | Bin 1024 -> 0 bytes src/test_util/simple_fake_binary_fw.test | Bin 4096 -> 0 bytes src/test_util/simple_fake_textual_fw.test | 11 - 26 files changed, 5759 deletions(-) delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 src/error.rs delete mode 100644 src/instrument/firmware.rs delete mode 100644 src/instrument/info.rs delete mode 100644 src/instrument/language.rs delete mode 100644 src/instrument/login.rs delete mode 100644 src/instrument/mod.rs delete mode 100644 src/instrument/script.rs delete mode 100644 src/interface/async_stream.rs delete mode 100644 src/interface/connection_addr.rs delete mode 100644 src/interface/mod.rs delete mode 100644 src/interface/usbtmc.rs delete mode 100644 src/lib.rs delete mode 100644 src/model/ki2600.rs delete mode 100644 src/model/mod.rs delete mode 100644 src/model/resources/flashUtil.tsp delete mode 100644 src/model/tti.rs delete mode 100644 src/model/versatest.rs delete mode 100644 src/test_util/mod.rs delete mode 100644 src/test_util/simple_fake_binary_fw.chunk0 delete mode 100644 src/test_util/simple_fake_binary_fw.chunk1 delete mode 100644 src/test_util/simple_fake_binary_fw.chunk2 delete mode 100644 src/test_util/simple_fake_binary_fw.chunk3 delete mode 100644 src/test_util/simple_fake_binary_fw.test delete mode 100644 src/test_util/simple_fake_textual_fw.test diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 837fdb8..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1489 +0,0 @@ -# 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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.21.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-targets", -] - -[[package]] -name = "colored" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" -dependencies = [ - "is-terminal", - "lazy_static", - "windows-sys", -] - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "difflib" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" - -[[package]] -name = "downcast" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -dependencies = [ - "num-traits", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[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 = "fragile" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" - -[[package]] -name = "futures-channel" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" - -[[package]] -name = "futures-sink" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" - -[[package]] -name = "futures-task" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" - -[[package]] -name = "futures-util" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "h2" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[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 = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "js-sys" -version = "0.3.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" -dependencies = [ - "wasm-bindgen", -] - -[[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.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" - -[[package]] -name = "libusb1-sys" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d0e2afce4245f2c9a418511e5af8718bcaf2fa408aefb259504d1a9cb25f27" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "mockall" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" -dependencies = [ - "cfg-if", - "downcast", - "fragile", - "lazy_static", - "mockall_derive", - "predicates", - "predicates-tree", -] - -[[package]] -name = "mockall_derive" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[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 = "normalize-line-endings" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "openssl" -version = "0.10.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" -dependencies = [ - "bitflags 2.4.1", - "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.39", -] - -[[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.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[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.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "predicates" -version = "2.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" -dependencies = [ - "difflib", - "float-cmp", - "itertools", - "normalize-line-endings", - "predicates-core", - "regex", -] - -[[package]] -name = "predicates-core" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" - -[[package]] -name = "predicates-tree" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" -dependencies = [ - "predicates-core", - "termtree", -] - -[[package]] -name = "proc-macro2" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "reqwest" -version = "0.11.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[package]] -name = "rpassword" -version = "7.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" -dependencies = [ - "libc", - "rtoolbox", - "windows-sys", -] - -[[package]] -name = "rtoolbox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "rusb" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fff149b6033f25e825cbb7b2c625a11ee8e6dac09264d49beb125e39aa97bf" -dependencies = [ - "libc", - "libusb1-sys", -] - -[[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.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "serde" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "serde_json" -version = "1.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys", -] - -[[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.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys", -] - -[[package]] -name = "termtree" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" - -[[package]] -name = "thiserror" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[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 = "tmc" -version = "0.1.1" -source = "git+https://github.com/esarver/rusb-usbtmc#0ed58c406a9ec7f1c48672a74531d8cd70957ac7" -dependencies = [ - "byteorder", - "rusb", - "thiserror", -] - -[[package]] -name = "tokio" -version = "1.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2 0.5.5", - "windows-sys", -] - -[[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-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[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.39", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "tsp-tookit-kic-lib" -version = "0.10.2" -dependencies = [ - "anyhow", - "bytes", - "chrono", - "colored", - "mockall", - "phf", - "reqwest", - "rpassword", - "rusb", - "serde", - "serde_json", - "thiserror", - "tmc", - "tracing", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[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.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -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", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.39", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" - -[[package]] -name = "web-sys" -version = "0.3.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[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-core" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[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_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[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_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[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_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys", -] diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 6678e13..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "tsp-tookit-kic-lib" -description = "A library specifically enabling communication to the Keithley product-line of instruments" -version = "0.10.2" -authors = ["Keithley Instruments, LLC"] -edition = "2021" -repository = "https://git.keithley.com/trebuchet/teaspoon/ki-comms" - -[dependencies] -bytes = "1.4.0" -phf = { version = "0.11.1", features = ["macros"] } -reqwest = "0.11" -rpassword = "7.2.0" -serde = { version = "1.0.152", features = ["derive"] } -serde_json = "1.0.93" -thiserror = "1.0.38" -tmc = { git = "https://github.com/esarver/rusb-usbtmc" } -tracing = { version = "0.1", features = ["async-await"] } -rusb = "0.9.1" -chrono = "0.4.30" -#oklib-rs = { git = "https://git.keithley.com/trebuchet/teaspoon/oklib-rs.git", branch = "main", optional = true } - -[dev-dependencies] -anyhow = "1.0.69" -bytes = "1" -colored = "2.0.0" -mockall = { version = "0.11.4", features = ["nightly"] } diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index b588c69..0000000 --- a/src/error.rs +++ /dev/null @@ -1,149 +0,0 @@ -//! All the errors that this crate can emit are defined in the -//! [`error::InstrumentError`] enum. - -use std::{num::ParseIntError, string::FromUtf8Error}; - -use thiserror::Error; - -use crate::instrument::info::ConnectionAddr; - -/// Define errors that originate from this crate -#[derive(Error, Debug)] -#[allow(clippy::module_name_repetitions)] -pub enum InstrumentError { - /// The `unparsable_string` was passed where an address was expected, but - /// it couldn't be parsed to a valid address. - #[error("unable to parse `{unparsable_string}`, expected an address")] - AddressParsingError { - ///The string that couldn't be parsed - unparsable_string: String, - }, - - /// The [`ConnectionAddr`] was not able to be converted to the desired device - /// interface type - #[error("unable to convert from `{from:?}` to {to}")] - ConnectionAddressConversionError { - /// The address information trying to be converted from - from: ConnectionAddr, - /// A string of name of the type trying to be converted to - to: String, - }, - - /// There was an error while trying to connect to the interface or instrument. - #[error("connection error occurred: {details}")] - ConnectionError { - // The details of the [`ConnectionError`] - details: String, - }, - - #[cfg(feature = "debugging")] - /// There was an error when performing a debugging action. - #[error("debug error occurred: {details}")] - DebugError { - /// The details of the [`DebugError`] - details: String, - }, - - #[cfg(feature = "debugging")] - /// The Debugger license was not accepted. - #[error("debug license was not valid: {reason}")] - DebugLicenseRejection { - /// The reason the license was rejected - reason: String, - }, - - /// There was an issue while disconnecting from an instrument. - #[error("unable to gracefully disconnect from instrument: {details}")] - DisconnectError { - /// More information about the disconnection error. - details: String, - }, - - /// A resource file was unable to be decrypted. - #[error("unable to decrypt resource: {source}")] - ResourceDecryptError { - ///**TODO:** Change this to the error that is produced when decryption fails - #[from] - source: FromUtf8Error, - }, - - /// An error that occurs while trying to retrieve information about an instrument - /// such as the serial number, model, manufacturer, etc. - #[error("instrument information retrieval error: {details}")] - InformationRetrievalError { - /// Any extra information about why the instrument information could not be - /// retrieved. - details: String, - }, - - /// An Error that originates from an instrument. This is generic for all instruments - /// and is therefore just a [`String`]. - #[error("{error}")] - InstrumentError { - /// The error string provided by the instrument. - error: String, - }, - - /// Converts a [`std::io::Error`] to a [`TeaspoonInterfaceError`] - #[error("IO error: {source}")] - IoError { - /// The [`std::io::Error`] from which this [`TeaspoonInterfaceError::IoError`] - /// was derived. - #[from] - source: std::io::Error, - }, - - /// The provided login details were either incorrect or the instrument is already - /// claimed and cannot be claimed again. - #[error("provided login details rejected or instrument already claimed")] - LoginRejected, - - #[error("{source}")] - ParseIntError { - #[from] - source: ParseIntError, - }, - - /// An error with communicating through rusb to the instrument - #[error("rusb error: {source}")] - RusbError { - #[from] - source: rusb::Error, - }, - - /// The TSP error that was received from the instrument was malformed. - #[error("unable to parse TSP error from instrument {error}")] - TspErrorParseError { - /// The text of the malformed error that was provided by the instrument - error: String, - }, - - /// Converts a [`tmc::TMCError`] to a [`TeaspoonInterfaceError`] - #[error("USBTMC error: {source}")] - TmcError { - /// The [`tmc::TMCError`] from which this [`TeaspoonInterfaceError::TmcError`] - /// was derived. - #[from] - source: tmc::TMCError, - }, - - /// The queried instrument returned an unknown model number - #[error("\"{model}\" is not a recognized model number")] - UnknownInstrumentModel { - /// The unknown model number - model: String, - }, - - /// The queried instrument returned an unknown language type - #[error("\"{lang} is not a recognized embedded instrument language\"")] - UnknownLanguage { - /// The unknown language type - lang: String, - }, - - /// An uncategorized error. - #[error("{0}")] - Other(String), -} - -pub(crate) type Result = std::result::Result; diff --git a/src/instrument/firmware.rs b/src/instrument/firmware.rs deleted file mode 100644 index 51d0a82..0000000 --- a/src/instrument/firmware.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::error::Result; - -/// The trait an instrument must implement in order to flash the firmware onto an -/// instrument. -pub trait Flash { - /// The method to flash a firmware image to an instrument. - /// - /// # Errors - /// An error can occur in the write to or reading from the instrument as well as in - /// reading the firmware image. - fn flash_firmware(&mut self, image: &[u8], firmware_info: Option) -> Result<()>; -} diff --git a/src/instrument/info.rs b/src/instrument/info.rs deleted file mode 100644 index ff4efba..0000000 --- a/src/instrument/info.rs +++ /dev/null @@ -1,178 +0,0 @@ -//! Define the trait and datatypes necessary to describe an instrument. - -use crate::{error::Result, usbtmc::UsbtmcAddr, InstrumentError}; -use std::{ - fmt::Display, - io::{Read, Write}, - net::SocketAddr, - time::Duration, -}; - -/// A generic connection address that covers all the different connection types. -/// Each device interface type will also have a [`TryFrom`] impl that converts from -/// this enum to itself. [`From`] is **not** implemented because the conversion could -/// fail. -#[non_exhaustive] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ConnectionAddr { - /// A LAN connection is created with a [`SocketAddr`], which includes an IpAddr and - /// a port for the connection. - Lan(SocketAddr), - - /// A USBTMC connection is created with a [`UsbtmcAddr`]. - Usbtmc(UsbtmcAddr), - //Add other device interface types here - Unknown, -} - -impl Display for ConnectionAddr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Lan(lan_info) => lan_info.to_string(), - Self::Usbtmc(usb_info) => usb_info.to_string(), - Self::Unknown => "".to_string(), - }; - write!(f, "{s}") - } -} - -/// The information about an instrument. -#[allow(clippy::module_name_repetitions)] -#[derive(serde::Serialize, Debug, Clone, PartialEq, Eq, Hash)] -pub struct InstrumentInfo { - /// The human-readable name of the vendor that makes the instrument - pub vendor: Option, - /// The model of the instrument - pub model: Option, - /// The serial number of the instrument - pub serial_number: Option, - /// The firmware revision of the instrument. - pub firmware_rev: Option, - /// The [`ConnectionAddr`] of the instrument. - #[serde(skip)] - pub address: Option, -} - -/// Get the [`InstrumentInfo`] from the given object that implements [`Read`] and -/// [`Write`]. -/// -/// # Errors -/// The following error classes can occur: -/// - Any [`std::io::Error`] that can occur with a [`Read`] or [`Write`] call -/// - Any error in converting the retrieved IDN string into [`InstrumentInfo`] -#[allow(clippy::module_name_repetitions)] -pub fn get_info(rw: &mut T) -> Result { - rw.write_all(b"*IDN?\n")?; - let mut info: Option = None; - for _ in 0..100 { - std::thread::sleep(Duration::from_millis(100)); - - let mut buf = vec![0u8; 100]; - let _ = rw.read(&mut buf)?; - let first_null = buf.iter().position(|&x| x == b'\0').unwrap_or(buf.len()); - let buf = &buf[..first_null]; - if let Ok(i) = buf.try_into() { - info = Some(i); - break; - } - } - info.ok_or(InstrumentError::InformationRetrievalError { - details: "unable to read instrument info".to_string(), - }) -} - -/// A trait to get the information from an instrument. -pub trait Info: Read + Write { - /// Get the information for the instrument. - /// - /// # Errors - /// [`TeaspoonInstrumentError::InformationRetrievalError`] if an instrument did not - /// return the requested information. - fn info(&mut self) -> Result { - get_info(self) - } -} - -impl TryFrom<&[u8]> for InstrumentInfo { - type Error = InstrumentError; - - fn try_from(idn: &[u8]) -> std::result::Result { - let parts: Vec<&[u8]> = idn - .split(|c| *c == b',' || *c == b'\n' || *c == b'\0') - .collect(); - - let (vendor, model, serial_number, firmware_rev) = match &parts[..] { - &[v, m, s, f, ..] => { - let fw_rev = String::from_utf8_lossy(f) - .to_string() - .trim_end_matches(|c| c == char::from(0)) - .trim() - .to_string(); - ( - Some(String::from_utf8_lossy(v).to_string()), - String::from_utf8_lossy(m) - .to_string() - .split("MODEL ") - .last() - .map(std::string::ToString::to_string), - Some(String::from_utf8_lossy(s).to_string()), - Some(fw_rev), - ) - } - _ => { - return Err(InstrumentError::InformationRetrievalError { - details: "unable to parse instrument information".to_string(), - }); - } - }; - - if model.is_none() { - return Err(InstrumentError::InformationRetrievalError { - details: "unable to parse model".to_string(), - }); - } - - Ok(Self { - vendor, - model, - serial_number, - firmware_rev, - address: None, - }) - } -} - -impl Display for InstrumentInfo { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let vendor = self.vendor.as_ref().map_or_else( - || String::from(""), - std::clone::Clone::clone, - ); - - let model: String = self - .model - .as_ref() - .map_or_else(|| String::from(""), std::clone::Clone::clone); - - let sn: String = self.serial_number.as_ref().map_or_else( - || String::from(""), - std::clone::Clone::clone, - ); - - let fw_rev = self.firmware_rev.as_ref().map_or_else( - || String::from(""), - std::clone::Clone::clone, - ); - - let addr = self - .address - .as_ref() - .map_or_else(|| ConnectionAddr::Unknown, std::clone::Clone::clone); - - if addr == ConnectionAddr::Unknown { - write!(f, "{vendor},MODEL {model},{sn},{fw_rev}") - } else { - write!(f, "{vendor},MODEL {model},{sn},{fw_rev},{addr}") - } - } -} diff --git a/src/instrument/language.rs b/src/instrument/language.rs deleted file mode 100644 index 1c2f735..0000000 --- a/src/instrument/language.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! All of the enums, traits, and impls for language management on an instrument. - -use std::{fmt::Display, str::FromStr}; - -use crate::InstrumentError; - -/// The languages that could be on an instrument. -#[allow(clippy::module_name_repetitions)] -#[derive(Debug, PartialEq, Eq)] -pub enum CmdLanguage { - /// The SCPI language - Scpi, - /// The TSP language - Tsp, -} - -impl FromStr for CmdLanguage { - type Err = InstrumentError; - - fn from_str(s: &str) -> Result { - let s = s.trim_matches(|c| c == char::from(0)).trim(); - match s { - "SCPI" => Ok(Self::Scpi), - "TSP" => Ok(Self::Tsp), - _ => Err(InstrumentError::UnknownLanguage { - lang: s.trim().to_string(), - }), - } - } -} - -impl Display for CmdLanguage { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Scpi => write!(f, "SCPI"), - Self::Tsp => write!(f, "TSP"), - } - } -} - -/// The functions to interface with an instrument and check or set the language. -/// -/// # Default -/// The default implementation of this trait assumes that the instrument only has the -/// TSP language, which is true for all instruments except TTI, as of the writing of -/// this comment) -pub trait Language { - /// Get the current language on the instrument. - /// - /// # Errors - /// [`InstrumentError`] is returned in the case of IO error, Unknown Language or other errors - fn get_language(&mut self) -> Result { - Ok(CmdLanguage::Tsp) - } - - /// Set the language on the instrument to the given language. - /// - /// # Errors - /// [`InstrumentError`] is returned in the case of IO error, Unknown Language or other errors - fn change_language(&mut self, _lang: CmdLanguage) -> Result<(), InstrumentError> { - Ok(()) - } -} diff --git a/src/instrument/login.rs b/src/instrument/login.rs deleted file mode 100644 index 771ecf9..0000000 --- a/src/instrument/login.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! The login functionality for an instrument. - -use crate::error::Result; - -/// The log-in state of an instrument. -#[derive(Debug, PartialEq, PartialOrd, Eq)] -pub enum State { - /// The instrument requires a login action for further communication. - Needed, - /// The instrument does _not_ require a login for further communication. Either the - /// instrument is not password protected OR the instrument is already unlocked for - /// this client. - NotNeeded, -} - -/// A trait that provides the expected functionality for logging into an instrument. -/// -/// This trait is required for a struct to be considered an instrument. -/// -/// Some instruments may not have the concept of logging in, for those instruments, -/// simply `impl Login` without any function definitions. -/// -/// # Examples -/// ## No Login Functionality Needed -/// ```no_run -/// use tsp_instrument::{instrument::{Login, State}, InstrumentError}; -/// -/// //This instrument does not have logins -/// struct ExampleInstrument { -/// //... -/// } -/// -/// impl Login for ExampleInstrument {} -/// ``` -/// -/// ## Login Functionality Needed -/// ```no_run -/// use tsp_instrument::{instrument::{Login, State}, InstrumentError}; -/// -/// struct Example { -/// logged_in: bool, -/// } -/// -/// impl Example { -/// fn enter_password(&mut self, token: &[u8]) -> Result<(), InstrumentError>{ -/// //... -/// self.logged_in = true; -/// Ok(()) -/// } -/// } -/// -/// impl Login for Example { -/// fn check_login(&mut self) -> Result { -/// if self.logged_in { -/// Ok(State::Needed) -/// } else { -/// Ok(State::NotNeeded) -/// } -/// } -/// -/// fn login(&mut self, token: &[u8]) -> Result<(), InstrumentError> -/// { -/// self.enter_password(token.as_ref()) -/// } -/// } -/// ``` -/// -pub trait Login { - /// Check the instrument to see if we need to login it. - /// - /// # Returns - /// - [`State::Needed`]: A login is necessary, therefore [`Login::login`] should be called. - /// - [`State::NotNeeded`]: A login is not necessary. Proceed with connection. - /// - /// # Default `impl` - /// The default implementation will always return [`State::NotNeeded`] and should - /// thus _not_ gate a connection to the instrument. - /// - /// # Errors - /// Returns an [`InstrumentError`] if any errors occurred. - fn check_login(&mut self) -> Result { - Ok(State::NotNeeded) - } - - /// Pass the given token to the instrument for it to authenticate. - /// - /// # Default `impl` - /// The default implementation will always return `Ok(())` and should therefore never - /// gate a connection to the instrument if called spuriously. - /// - /// # Errors - /// Returns an [`InstrumentError`] if any errors occurred. - fn login(&mut self, _token: &[u8]) -> Result<()> { - Ok(()) - } -} diff --git a/src/instrument/mod.rs b/src/instrument/mod.rs deleted file mode 100644 index b074696..0000000 --- a/src/instrument/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Trait definitions that need to be satisfied for any instrument. - -pub mod firmware; -pub mod info; -pub mod language; -pub mod login; -pub mod script; - -use std::{ - io::{Read, Write}, - time::Duration, -}; - -pub use firmware::Flash; -pub use info::Info; -pub use language::{CmdLanguage, Language}; -pub use login::{Login, State}; -pub use script::Script; - -use crate::interface::NonBlock; -use crate::{error::Result, InstrumentError}; - -/// A marker trait that defines the traits any [`Instrument`] needs to have. -pub trait Instrument: Flash + Info + Language + Login + Script + Read + Write + NonBlock {} - -/// Read from a 'rw' until we are sure we have cleared the output queue. -/// -/// # Errors -/// Whatever can errors can occur with [`std::io::Read`], [`std::io::Write`] or -/// [`tsp-instrument::interface::NonBlock`]. -pub fn clear_output_queue( - rw: &mut T, - max_attempts: usize, - delay_between_attempts: Duration, -) -> Result<()> { - let timestamp = chrono::Utc::now().to_string(); - - rw.write_all(format!("print(\"{timestamp}\")\n").as_bytes())?; - - rw.set_nonblocking(true)?; - - let mut accumulate = String::new(); - for _ in 0..max_attempts { - std::thread::sleep(delay_between_attempts); - let mut buf: Vec = vec![0u8; 512]; - match rw.read(&mut buf) { - Ok(_) => Ok(()), - Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { - std::thread::sleep(delay_between_attempts); - continue; - } - Err(e) => Err(e), - }?; - let first_null = buf.iter().position(|&x| x == b'\0').unwrap_or(buf.len()); - let buf = &buf[..first_null]; - if !buf.is_empty() { - accumulate = format!("{accumulate}{}", String::from_utf8_lossy(buf)); - } - if accumulate.contains(×tamp) { - return Ok(()); - } - } - Err(InstrumentError::Other( - "unable to clear instrument output queue".to_string(), - )) -} diff --git a/src/instrument/script.rs b/src/instrument/script.rs deleted file mode 100644 index 597f286..0000000 --- a/src/instrument/script.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! A trait that allows for the writing of a TSP script file to the instrument. - -use std::io::{BufRead, Write}; - -use bytes::Buf; - -use crate::error::Result; - -/// The [`Instrument`] can write a script to be executed. -pub trait Script -where - Self: Write, -{ - /// Write the given script to the instrument with the given name. - /// - /// # Parameters - /// - `name` - is the environment-compatible name of the script - /// - `script` - is the contents of the script - /// - `save_script` - `true` if the script should be saved to non-volatile memory - /// - `run_script` - `true` if the script should be run after load - /// - /// # Notes - /// - The script name will not be validated to ensure that it is compatible with the - /// scripting environment. - /// - The given script content will only be validated by the instrument, but not - /// the [`write_script`] function. - /// - /// # Errors - /// Returns an [`InstrumentError`] if any errors occurred. - fn write_script( - &mut self, - name: &[u8], - script: &[u8], - save_script: bool, - run_script: bool, - ) -> Result<()> { - let name = String::from_utf8_lossy(name).to_string(); - let script = script.reader(); //String::from_utf8_lossy(script.as_ref()).to_string(); - self.write_all(b"_orig_prompts = localnode.prompts localnode.prompts = 0\n")?; - self.flush()?; - self.write_all(format!("{name}=nil\n").as_bytes())?; - self.flush()?; - self.write_all(format!("loadscript {name}\n").as_bytes())?; - - for line in script.lines() { - self.write_all(format!("{}\n", line?).as_bytes())?; - } - - self.write_all(b"\nendscript\n")?; - self.flush()?; - - if save_script { - self.write_all(format!("{name}.save()\n").as_bytes())?; - self.flush()?; - } - - if run_script { - self.write_all(format!("{name}.run()\n").as_bytes())?; - self.flush()?; - } - - self.write_all(b"localnode.prompts = _orig_prompts _orig_prompts = nil\n")?; - self.flush()?; - - Ok(()) - } -} diff --git a/src/interface/async_stream.rs b/src/interface/async_stream.rs deleted file mode 100644 index e43122c..0000000 --- a/src/interface/async_stream.rs +++ /dev/null @@ -1,170 +0,0 @@ -use std::{ - io::{ErrorKind, Read, Write}, - rc::Rc, - sync::{ - mpsc::{self, Receiver, Sender, TryRecvError}, - Arc, - }, - thread::JoinHandle, - time::Duration, -}; - -use crate::error::{InstrumentError, Result}; - -use crate::interface::{Interface, NonBlock}; - -//create an Async version of the interface -pub struct AsyncStream { - join: JoinHandle>>, - write_to: Sender>, - read_from: Rc>>, - buffer: Vec, - nonblocking: bool, -} - -impl TryFrom> for AsyncStream { - type Error = InstrumentError; - - fn try_from( - mut socket: Arc, - ) -> std::result::Result { - let (write_to, read_into) = mpsc::channel(); - let (write_out, read_from) = mpsc::channel(); - let builder = - std::thread::Builder::new().name("Instrument Communication Thread".to_string()); - //TODO: Populate name with instrument information - - let join = builder.spawn(move || -> Result> { - Arc::get_mut(&mut socket).unwrap().set_nonblocking(true)?; - let read_into: Receiver> = read_into; - let write_out: Sender> = write_out; - - 'rw_loop: loop { - // see if the application has anything to send to the instrument. - std::thread::sleep(Duration::from_micros(1)); - match read_into.try_recv() { - // It does, so send it - Ok(msg) => match Arc::get_mut(&mut socket) - .unwrap() - // Do NOT add a newline here. It is added elsewhere. - .write_all(format!("{}", String::from_utf8_lossy(&msg)).as_bytes()) - { - Ok(()) => {} - Err(e) => { - // There was an Error sending to the instrument. - // clean up and get out. - return Err(e.into()); - } - }, - Err(e) => match e { - // The sender has disconnected, therefore we need to clean up - mpsc::TryRecvError::Disconnected => break 'rw_loop, - mpsc::TryRecvError::Empty => {} - }, - } - let buf = &mut [0u8; 512]; - if let Ok(size) = Arc::get_mut(&mut socket).unwrap().read(buf) { - let buf = &buf[..size]; - // This `send()` sends this to a receiver that will be activated next time a self.read() is called. - if size > 0 && write_out.send(buf.to_vec()).is_err() { - return Err(std::io::Error::new( - ErrorKind::ConnectionReset, - "attempted to send message from device, but client was closed" - .to_string(), - ) - .into()); - } - } - } - Ok(socket) - })?; - - Ok(Self { - join, - write_to, - read_from: Rc::new(read_from), - buffer: Vec::new(), - nonblocking: true, - }) - } -} - -impl Read for AsyncStream { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - // define an error since all of the returned errors are for the same reason. - let error: std::io::Error = std::io::Error::new( - ErrorKind::NotConnected, - "attempted to read asynchronously from socket, but it was not connected".to_string(), - ); - - let resp = if self.nonblocking { - match self.read_from.try_recv() { - Ok(resp) => resp, - Err(e) => match e { - TryRecvError::Empty => Vec::default(), - TryRecvError::Disconnected => { - return Err(error); - } - }, - } - } else { - if !self.buffer.is_empty() { - let read_size = self.buffer.take(buf.len() as u64).read(buf)?; - self.buffer = self.buffer[read_size..].into(); - return Ok(read_size); - } - match self.read_from.recv() { - Ok(resp) => resp, - Err(_) => { - return Err(error); - } - } - }; - - let _ = self.buffer.write(&resp); - let read_size = self.buffer.take(buf.len() as u64).read(buf)?; - self.buffer = self.buffer[read_size..].into(); - - Ok(read_size) - } -} - -impl Write for AsyncStream { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - let Ok(()) = self.write_to.send(Vec::from(buf)) else { - return Err(std::io::Error::new( - ErrorKind::NotConnected, - "attempted to write asynchronously to socket, but it was not connected".to_string(), - )); - }; - - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} - -impl NonBlock for AsyncStream { - fn set_nonblocking(&mut self, nonblocking: bool) -> Result<()> { - self.nonblocking = nonblocking; - Ok(()) - } -} - -impl TryFrom for Arc { - type Error = InstrumentError; - - fn try_from(async_stream: AsyncStream) -> std::result::Result { - drop(async_stream.write_to); - match async_stream.join.join() { - Ok(Ok(stream)) => Ok(stream), - _ => Err(InstrumentError::ConnectionError { - details: "unable to retrieve synchronous stream".to_string(), - }), - } - } -} - -impl Interface for AsyncStream {} diff --git a/src/interface/connection_addr.rs b/src/interface/connection_addr.rs deleted file mode 100644 index 31584bf..0000000 --- a/src/interface/connection_addr.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::fmt::Display; -use std::net::SocketAddr; - -use crate::interface::usbtmc::UsbtmcAddr; - -/// A generic connection address that covers all the different connection types. -/// Each device interface type will also have a [`TryFrom`] impl that converts from -/// this enum to itself. [`From`] is **not** implemented because the conversion could -/// fail. -#[non_exhaustive] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ConnectionAddr { - /// A LAN connection is created with a [`SocketAddr`], which includes an IpAddr and - /// a port for the connection. - Lan(SocketAddr), - - /// A USBTMC connection is created with a [`UsbtmcAddr`]. - Usbtmc(UsbtmcAddr), - //Add other device interface types here - Unknown, -} - -impl Display for ConnectionAddr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Lan(lan_info) => lan_info.to_string(), - Self::Usbtmc(usb_info) => usb_info.to_string(), - Self::Unknown => "".to_string(), - }; - write!(f, "{s}") - } -} diff --git a/src/interface/mod.rs b/src/interface/mod.rs deleted file mode 100644 index ccfe6fe..0000000 --- a/src/interface/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::{ - io::{Read, Write}, - net::TcpStream, -}; - -use crate::error::Result; - -pub mod async_stream; -pub mod connection_addr; -pub mod usbtmc; - -/// Defines a marker trait that we will implement on each device interface -pub trait Interface: NonBlock + Read + Write {} - -/// This device can be set to be non-blocking. This is a requirement of an Interface -pub trait NonBlock { - /// Set the interface not to block on reads to allow for polling. - /// - /// # Errors - /// There may be errors that occur from the associated physical interface - /// (e.g. LAN, USB). - fn set_nonblocking(&mut self, enable: bool) -> Result<()>; -} - -impl NonBlock for TcpStream { - fn set_nonblocking(&mut self, enable: bool) -> crate::error::Result<()> { - Ok(Self::set_nonblocking(self, enable)?) - } -} - -impl Interface for TcpStream {} diff --git a/src/interface/usbtmc.rs b/src/interface/usbtmc.rs deleted file mode 100644 index 2f74dc4..0000000 --- a/src/interface/usbtmc.rs +++ /dev/null @@ -1,174 +0,0 @@ -use std::{ - fmt::Display, - hash::Hash, - io::{ErrorKind, Read, Write}, - str::FromStr, - time::Duration, -}; - -use rusb::{Context, DeviceList}; -use tmc::InstrumentHandle; - -use crate::{error::Result, interface, interface::NonBlock, InstrumentError}; - -const KEITHLEY_VID: u16 = 0x05e6; - -/// An address representing how to connect to a USBTMC device. -#[allow(clippy::module_name_repetitions)] -#[derive(Debug, Clone)] -pub struct UsbtmcAddr { - pub device: rusb::Device, - pub model: String, - pub serial: String, -} - -impl Hash for UsbtmcAddr { - fn hash(&self, state: &mut H) { - format!("{}:{}:{}", "USB", self.model, self.serial).hash(state); - } -} - -impl Eq for UsbtmcAddr {} - -impl PartialEq for UsbtmcAddr { - fn eq(&self, other: &Self) -> bool { - self.serial == other.serial && self.model == other.model - } -} - -impl Display for UsbtmcAddr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "USB:{}:{}", self.model, self.serial) - } -} - -impl FromStr for UsbtmcAddr { - type Err = InstrumentError; - - fn from_str(s: &str) -> std::result::Result { - //USB:2450:01234567 - let split: Vec<&str> = s.split(':').collect(); - if split.len() != 3 { - return Err(InstrumentError::AddressParsingError { - unparsable_string: s.to_string(), - }); - } - - let (ix, model, serial) = (split[0], split[1], split[2]); - - if ix.trim() != "USB" { - return Err(InstrumentError::AddressParsingError { - unparsable_string: s.to_string(), - }); - } - let context = rusb::Context::new()?; - for device in DeviceList::new_with_context(context)?.iter() { - let desc = device.device_descriptor()?; - if desc.vendor_id() == KEITHLEY_VID - && desc.product_id() == u16::from_str_radix(model, 16)? - { - let handle = device.open()?; - let languages = handle.read_languages(Duration::from_millis(100))?; - let Some(language) = languages.first() else { - continue; - }; - let sn = handle.read_serial_number_string( - *language, - &desc, - Duration::from_millis(100), - )?; - if *serial == sn { - return Ok(Self { - device, - model: model.to_string(), - serial: serial.to_string(), - }); - } - } - } - - Err(InstrumentError::ConnectionError { - details: format!( - "USB device with model '{model}' and serial number '{serial}' could not be found" - ), - }) - } -} - -#[derive(Debug)] -pub struct Stream { - handle: InstrumentHandle, - nonblocking: bool, -} - -impl TryFrom for Stream { - type Error = InstrumentError; - - fn try_from(addr: UsbtmcAddr) -> std::result::Result { - Ok(Self { - handle: tmc::Instrument::new(addr.device)? - .ok_or(InstrumentError::ConnectionError { - details: "unable to connect to USB instrument".to_string(), - })? - .open()?, - nonblocking: false, - }) - } -} - -impl TryFrom> for Stream { - type Error = InstrumentError; - fn try_from(handle: InstrumentHandle) -> std::result::Result { - Ok(Self { - handle, - nonblocking: false, - }) - } -} - -impl NonBlock for Stream { - fn set_nonblocking(&mut self, enable: bool) -> Result<()> { - self.nonblocking = enable; - Ok(()) - } -} - -impl interface::Interface for Stream {} - -impl Write for Stream { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.handle.write_raw(buf)?; - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - //Nothing to force-flush on USBTMC, handled by `write_raw` above - Ok(()) - } -} - -impl Read for Stream { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - let message_available = if self.nonblocking { - self.handle.read_stb(Some(Duration::from_millis(10)))? - } else { - while !self.handle.read_stb(Some(Duration::from_millis(10)))? {} - true - }; - - if message_available { - let msg = self.handle.read_raw(Some(match u32::try_from(buf.len()) { - Ok(v) => v, - Err(e) => { - return Err(std::io::Error::new( - ErrorKind::Other, - format!("buffer larger than can be read: {e}"), - )); - } - }))?; - msg.take(buf.len() as u64).read(buf) - } else { - Ok(0) - } - } -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index fbc6d17..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(lint_reasons, rustdoc_missing_doc_code_examples)] -#![deny( - clippy::undocumented_unsafe_blocks, - clippy::pedantic, - clippy::nursery, - clippy::arithmetic_side_effects -)] -#![feature(assert_matches)] -//#![warn(missing_docs, rustdoc::all)] -//#![allow(rustdoc::missing_doc_code_examples)] -#![doc(html_logo_url = "../../../ki-comms_doc_icon.png")] - -//! The TSP Instrument crate defines the necessary components to enable communication -//! with an instrument at various levels of abstraction. The aim of the library is to -//! interact correctly, efficiently and reliably with Keithley instruments via multiple -//! connection interfaces. Right now LAN and USBTMC are implemented, and VISA is -//! planned - -//pub mod connect; -pub mod error; -pub mod instrument; -pub mod interface; -pub mod model; - -#[cfg(test)] -pub(crate) mod test_util; - -//pub use connect::{AsyncToSync, Connect, ConnectAsync, ConnectionAddr, Disconnect}; -pub use error::InstrumentError; -pub use instrument::firmware::Flash; -pub use interface::{connection_addr::ConnectionAddr, usbtmc, Interface}; -pub use model::{ki2600, tti, versatest}; diff --git a/src/model/ki2600.rs b/src/model/ki2600.rs deleted file mode 100644 index a4077d0..0000000 --- a/src/model/ki2600.rs +++ /dev/null @@ -1,980 +0,0 @@ -use std::io::{BufRead, Read, Write}; - -use bytes::Buf; - -use crate::{ - instrument::{self, info::InstrumentInfo, language, Info, Login, Script}, - interface::Interface, - interface::NonBlock, - Flash, InstrumentError, -}; - -pub struct Instrument { - info: Option, - interface: Box, -} - -impl Instrument { - #[must_use] - pub fn is(info: &InstrumentInfo) -> bool { - info.model.as_ref().map_or(false, |model| { - model.split_ascii_whitespace().last().map_or(false, is_2600) - }) - } - - #[must_use] - pub const fn new(interface: Box) -> Self { - Self { - info: None, - interface, - } - } - - pub fn add_info(&mut self, info: InstrumentInfo) -> &Self { - self.info = Some(info); - self - } -} - -//Implement device_interface::Interface since it is a subset of instrument::Instrument trait. -impl instrument::Instrument for Instrument {} - -fn is_2600(model: impl AsRef) -> bool { - [ - "2601", - "2602", - "2611", - "2612", - "2635", - "2636", - "2601A", - "2602A", - "2611A", - "2612A", - "2635A", - "2636A", - "2651A", - "2657A", - "2601B", - "2601B-PULSE", - "2602B", - "2606B", - "2611B", - "2612B", - "2635B", - "2636B", - "2604B", - "2614B", - "2634B", - "2601B-L", - "2602B-L", - "2611B-L", - "2612B-L", - "2635B-L", - "2636B-L", - "2604B-L", - "2614B-L", - "2634B-L", - "3706", - "3706-SNFP", - "3706-S", - "3706-NFP", - "3706A", - "3706A-SNFP", - "3706A-S", - "3706A-NFP", - "707B", - "708B", - ] - .contains(&model.as_ref()) -} - -impl Info for Instrument {} - -impl language::Language for Instrument {} - -impl Login for Instrument { - fn check_login(&mut self) -> crate::error::Result { - self.write_all(b"print('unlocked')\n")?; - - let mut resp: Vec = vec![0; 256]; - let _read = self.read(&mut resp)?; - - let resp = std::str::from_utf8(resp.as_slice()) - .unwrap_or("") - .trim_matches(char::from(0)) - .trim(); - - if resp.contains("FAILURE") { - Ok(instrument::State::Needed) - } else { - Ok(instrument::State::NotNeeded) - } - } - - fn login(&mut self, token: &[u8]) -> crate::error::Result<()> { - if instrument::State::NotNeeded == self.check_login()? { - return Ok(()); - } - - self.write_all(format!("password {}\n", String::from_utf8_lossy(token)).as_bytes())?; - - if instrument::State::Needed == self.check_login()? { - return Err(InstrumentError::LoginRejected); - } - - Ok(()) - } -} - -impl Script for Instrument {} - -impl Flash for Instrument { - fn flash_firmware(&mut self, image: &[u8], _: Option) -> crate::error::Result<()> { - let image = image.reader(); - self.write_all(b"flash\n")?; - - for line in image.lines() { - self.write_all(format!("{}\n", line?).as_bytes())?; - } - - self.write_all(b"endflash\n")?; - Ok(()) - } -} - -impl Read for Instrument { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - self.interface.read(buf) - } -} - -impl Write for Instrument { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.interface.write(buf) - } - - fn flush(&mut self) -> std::io::Result<()> { - self.interface.flush() - } -} - -impl NonBlock for Instrument { - fn set_nonblocking(&mut self, enable: bool) -> crate::error::Result<()> { - self.interface.set_nonblocking(enable) - } -} - -impl Drop for Instrument { - fn drop(&mut self) { - let _ = self.interface.write_all(b"abort\n"); - } -} - -#[cfg(test)] -mod unit { - use std::{ - assert_matches::assert_matches, - io::{BufRead, Read, Write}, - }; - - use bytes::Buf; - use mockall::{mock, Sequence}; - - use crate::{ - instrument::{self, info::Info, Login, Script}, - interface::NonBlock, - interface::{self}, - test_util, Flash, InstrumentError, - }; - - use super::Instrument; - - #[test] - fn login_not_needed() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - // A successful login attempt on a TTI instrument is as follows: - // 1. Instrument connects to interface - // 2. Instrument sends "*STB?\n" - // 3. Instrument reads from interface and receives status byte - // 4. Instrument returns `instrument::State::NotNeeded` - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::NotNeeded)); - - assert!(instrument.login(b"secret_token").is_ok()); - } - - #[test] - #[allow(clippy::too_many_lines)] //Allow for now. - fn login_success() { - let mut _interface = MockInterface::new(); - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() { first check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() {write(b"login {token}")} - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"password secret_token\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - // login() { second check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - - assert_matches!(instrument.login(b"secret_token"), Ok(())); - - assert_matches!(instrument.check_login(), Ok(instrument::State::NotNeeded)); - } - - #[test] - #[allow(clippy::too_many_lines)] //Allow for now - fn login_failure() { - let mut _interface = MockInterface::new(); - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() { first check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() {write(b"login {token}")} - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"password secret_token\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - // login() { second check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - - assert_matches!( - instrument.login(b"secret_token"), - Err(InstrumentError::LoginRejected) - ); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - } - - #[test] - fn info() { - let mut _interface = MockInterface::new(); - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*IDN?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 50) - .return_once(|buf: &mut [u8]| { - let msg = b"KEITHLEY INSTRUMENTS,MODEL 2636B,0123456789,1.2.3d\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - let info = instrument - .info() - .expect("instrument can get instrument information from MockInterface"); - - let exp_vendor = "KEITHLEY INSTRUMENTS".to_string(); - let exp_model = "2636B".to_string(); - let exp_serial = "0123456789".to_string(); - let exp_fw = "1.2.3d".to_string(); - - assert_eq!(info.vendor.unwrap(), exp_vendor); - assert_eq!(info.model.unwrap(), exp_model); - assert_eq!(info.serial_number.unwrap(), exp_serial); - assert_eq!(info.firmware_rev.unwrap(), exp_fw); - } - - #[test] - fn write_script() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], false, false) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_run() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.run()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], false, true) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_save() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.save()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], true, false) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_save_run() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.save()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.run()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], true, true) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn flash_firmware() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"flash\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - for line in test_util::SIMPLE_FAKE_TEXTUAL_FW.reader().lines() { - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(move |buf: &[u8]| { - buf == format!( - "{}\n", - line.as_ref() - .expect("textual test firmware should return all Ok for lines()") - ) - .as_bytes() - }) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"endflash\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .flash_firmware(test_util::SIMPLE_FAKE_TEXTUAL_FW, Some(0)) - .expect("instrument should have written fw to MockInterface"); - } - - // Define a mock interface to be used in the tests above. - mock! { - Interface {} - - impl interface::Interface for Interface {} - - impl Read for Interface { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result; - } - - impl Write for Interface { - fn write(&mut self, buf: &[u8]) -> std::io::Result; - - fn flush(&mut self) -> std::io::Result<()>; - } - - impl NonBlock for Interface { - fn set_nonblocking(&mut self, enable: bool) -> crate::error::Result<()>; - } - } -} diff --git a/src/model/mod.rs b/src/model/mod.rs deleted file mode 100644 index 95155b3..0000000 --- a/src/model/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::{ - instrument::{info::get_info, Instrument}, - InstrumentError, Interface, -}; - -pub mod ki2600; -pub mod tti; -pub mod versatest; - -impl TryFrom> for Box { - type Error = InstrumentError; - - fn try_from(mut interface: Box) -> std::result::Result { - let info = get_info(interface.as_mut())?; - if tti::Instrument::is(&info) { - Ok(Box::new(tti::Instrument::new(interface))) - } else if ki2600::Instrument::is(&info) { - Ok(Box::new(ki2600::Instrument::new(interface))) - } else if versatest::Instrument::is(&info) { - Ok(Box::new(versatest::Instrument::new(interface))) - } else { - Err(InstrumentError::InstrumentError { - error: "unable to determine instrument type".to_string(), - }) - } - } -} diff --git a/src/model/resources/flashUtil.tsp b/src/model/resources/flashUtil.tsp deleted file mode 100644 index a7cceab..0000000 --- a/src/model/resources/flashUtil.tsp +++ /dev/null @@ -1,185 +0,0 @@ --- This table encodes which firmware part numbers are expected for the various --- model numbers reported by the module. The key is the model number reported --- by the module. The value is the expected firmware part number of the image. --- Note that unprogrammed modules may report their model number as the firmware --- part number. -local gFwPartTable = -{ - ["Sparta"] = "066-2199", - ["VTSMU-48-2"] = "066-2199", - ["VTSMU-48-8"] = "066-2199", - ["VTSMU-48-16"] = "066-2199", - ["VTSMU-200-1"] = "066-2206", - ["VTSMU-200-1-LC"] = "066-2206", - ["VTSMU-200-2"] = "066-2206", - ["VTSMU-200-2-LC"] = "066-2206", - ["KingArthur"] = "066-2200", - ["VTPSU-50-2-ST"] = "066-2200", - ["900071100"] = "066-2205", -- This is the load test module - ["066-2199"] = "066-2199", - ["066-2200"] = "066-2200", - ["066-2205"] = "066-2205", - ["066-2206"] = "066-2206", -} - --- This table encodes which firmware part numbers as reported by the firmware --- image file are compatible with the expected firmware part number for the --- module. That is to say, if the table above indicates firmware part number --- 066-AAAA is the firmware to be loaded on the module, we check this table --- using the firmware part number reported by the image as the key. If the --- value on the right is 066-AAAA, we are good. -local gFwCompatibility = -{ - ["Sparta"] = "066-2199", - ["KingArthur"] = "066-2200", - ["066-2199"] = "066-2199", - ["066-2200"] = "066-2200", - ["066-2205"] = "066-2205", - ["066-2206"] = "066-2206", -} - --- This table is used to indicate which modules use dual interfaces and --- requires the firmware update function to program both interfaces. The --- key is the model number. -local gSplitModules = -{ - ["VTSMU-48-16"] = true, - ["VTSMU-200-2"] = true, - ["VTSMU-200-2-LC"] = true, - ["900071100"] = true, -} - -checkbanks = function(lSlot, lDualBanks, lAction) - local lLowerBank = false - local lUpperBank = false - - if lDualBanks then - lLowerBank = lSlot.bank[1] - lUpperBank = lSlot.bank[2] - if lLowerBank and lLowerBank.flash then - lLowerBank = lLowerBank.flash - else - if lSlot.flash then - print("Warning: Bank[1] not detected but slot level interface detected.") - print("Warning: Assuming MRD image.") - lLowerBank = lSlot.flash - else - print("Warning: Bank[1] not detected. Lower bank will not be " .. lAction .. ".") - end - end - if lUpperBank then - lUpperBank = lUpperBank.flash - else - print("Warning: Bank[2] not detected. Upper bank will not be " .. lAction .. ".") - end - else - lLowerBank = lSlot.flash - end - - return lLowerBank, lUpperBank -end - -flashupdate = function(lSlot) - local lOffset = 0 - local lSectorNumber = 1 - local lSectorAddress - local lSectorData - local lPart - local lVersion - local lDualBanks - local lUpperBank = false - local lLowerBank = false - - lPart = gFwCompatibility[flash.part] - lVersion = flash.version - - if (flash.part == "MediumMrd") then - print("Loading MRD firmware onto model " .. lSlot.model) - elseif lPart ~= gFwPartTable[lSlot.model] then - print("Firmware image not appropriate for module. Module: " .. lSlot.model .. ", Image: " .. lPart) - print("Flash not updated.") - return - end - print("Updating module to version " .. lVersion) - - lDualBanks = gSplitModules[lSlot.model] - lLowerBank, lUpperBank = checkbanks(lSlot, lDualBanks, "programmed") - - errorqueue.clear() - lSectorAddress, lSectorData = flash.sector(lSectorNumber, true) - while lSectorAddress and (errorqueue.count == 0) do - print('Programming sector ' .. lSectorNumber) - if lLowerBank then - lLowerBank.sector.load(lSectorData) - lLowerBank.sector.program(lSectorAddress + lOffset) - end - if lUpperBank then - lUpperBank.sector.load(lSectorData) - lUpperBank.sector.program(lSectorAddress + lOffset) - end - lSectorNumber = lSectorNumber + 1 - lSectorAddress, lSectorData = flash.sector(lSectorNumber, true) - end - print("Done programming flash.") -end - -flashverify = function(lSlot, lCompress) - local lSectorNumber = 1 - local lSectorAddress - local lSectorData - local lRealData - local lDualBanks - local lUpperBank = false - local lLowerBank = false - - errorqueue.clear() - lDualBanks = gSplitModules[lSlot.model] - lLowerBank, lUpperBank = checkbanks(lSlot, lDualBanks, "checked") - lSectorAddress, lSectorData = flash.sector(lSectorNumber, lCompress) - while lSectorAddress and (errorqueue.count == 0) do - if lLowerBank then - lRealData = lLowerBank.read(lSectorAddress, 32768, lCompress) - if lRealData == lSectorData then - print('Sector ' .. lSectorNumber .. ' (lower) same') - else - print('Sector ' .. lSectorNumber .. ' (lower) different') - end - end - if lUpperBank then - lRealData = lUpperBank.read(lSectorAddress, 32768, lCompress) - if lRealData == lSectorData then - print('Sector ' .. lSectorNumber .. ' (upper) same') - else - print('Sector ' .. lSectorNumber .. ' (upper) different') - end - end - lSectorNumber = lSectorNumber + 1 - lSectorAddress, lSectorData = flash.sector(lSectorNumber, lCompress) - end -end - -flashencode = function (lAddress, lData) - local lLength = string.len(lData) - local lChunkLength - local lString - local lIndex - local lByteIndex - - lByteIndex = 1 - while lLength > 0 do - if lLength > 16 then - lChunkLength = 16 - else - lChunkLength = lLength - end - lString = string.format("S3%02X%08X", lChunkLength + 5, lAddress) - for lIndex = 1, lChunkLength do - lString = lString .. string.format("%02X", string.byte(lData, lByteIndex)) - lByteIndex = lByteIndex + 1 - end - lString = lString .. "--" - lLength = lLength - lChunkLength - lAddress = lAddress + lChunkLength - print(lString) - end -end diff --git a/src/model/tti.rs b/src/model/tti.rs deleted file mode 100644 index 0d1f8c4..0000000 --- a/src/model/tti.rs +++ /dev/null @@ -1,970 +0,0 @@ -use std::{ - io::{Read, Write}, - thread::sleep, - time::Duration, -}; - -use bytes::Buf; -use language::{CmdLanguage, Language}; - -use crate::{ - instrument::{self, info::InstrumentInfo, language, Info, Login, Script}, - interface::Interface, - interface::NonBlock, - Flash, InstrumentError, -}; - -pub struct Instrument { - info: Option, - interface: Box, -} - -impl Instrument { - #[must_use] - pub fn is(info: &InstrumentInfo) -> bool { - info.model.as_ref().map_or(false, is_tti) - } - - #[must_use] - pub const fn new(interface: Box) -> Self { - Self { - info: None, - interface, - } - } - - pub fn add_info(&mut self, info: InstrumentInfo) -> &Self { - self.info = Some(info); - self - } -} - -fn is_tti(model: impl AsRef) -> bool { - [ - "2450", "2470", "DMM7510", "2460", "2461", "2461-SYS", "DMM7512", "DMM6500", "DAQ6510", - ] - .contains(&model.as_ref()) -} - -//Implement device_interface::Interface since it is a subset of instrument::Instrument trait. -impl instrument::Instrument for Instrument {} - -impl Info for Instrument {} - -impl Language for Instrument { - fn get_language(&mut self) -> Result { - self.write_all(b"*LANG?\n")?; - let mut lang: Vec = vec![0; 16]; - let _read = self.read(&mut lang)?; - String::from_utf8_lossy(&lang).to_string().as_str().parse() - } - - fn change_language(&mut self, lang: CmdLanguage) -> Result<(), InstrumentError> { - self.write_all(format!("*LANG {lang}\n").as_bytes())?; - Ok(()) - } -} - -impl Login for Instrument { - fn check_login(&mut self) -> crate::error::Result { - self.write_all(b"*STB?\n")?; - - std::thread::sleep(Duration::from_millis(1000)); - - let mut resp: Vec = vec![0; 256]; - let _read = self.read(&mut resp)?; - - let resp = std::str::from_utf8(resp.as_slice()) - .unwrap_or("") - .trim_matches(char::from(0)) - .trim(); - - if resp.contains("FAILURE") { - Ok(instrument::State::Needed) - } else { - Ok(instrument::State::NotNeeded) - } - } - - fn login(&mut self, token: &[u8]) -> crate::error::Result<()> { - if instrument::State::NotNeeded == self.check_login()? { - return Ok(()); - } - - self.write_all(format!("login {}\n", String::from_utf8_lossy(token)).as_bytes())?; - - if instrument::State::Needed == self.check_login()? { - return Err(InstrumentError::LoginRejected); - } - - Ok(()) - } -} - -impl Script for Instrument {} - -impl Flash for Instrument { - fn flash_firmware(&mut self, image: &[u8], _: Option) -> crate::error::Result<()> { - const CHUNK_SIZE: usize = 1024; - //let len = image.len(); - //let mut written = 0usize; - let mut image = image.reader(); - - self.write_all(b"localnode.prompts=localnode.DISABLE\n")?; - self.write_all(b"if ki.upgrade ~= nil and ki.upgrade.noacklater ~= nil then ki.upgrade.noacklater() end\n")?; - self.write_all(b"prevflash\n")?; - - loop { - let mut buf = vec![0; CHUNK_SIZE]; - let b = image.read(&mut buf)?; - //written += b; - if b == 0 { - break; - } - let buf = &buf[..b]; - sleep(Duration::from_millis(1)); - self.write_all(buf)?; - } - - self.write_all(b"endflash\n")?; - Ok(()) - } -} - -impl Read for Instrument { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - self.interface.read(buf) - } -} - -impl Write for Instrument { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.interface.write(buf) - } - - fn flush(&mut self) -> std::io::Result<()> { - self.interface.flush() - } -} - -impl NonBlock for Instrument { - fn set_nonblocking(&mut self, enable: bool) -> crate::error::Result<()> { - self.interface.set_nonblocking(enable) - } -} - -impl Drop for Instrument { - fn drop(&mut self) { - let _ = self.write_all(b"abort\n"); - } -} - -#[cfg(test)] -mod unit { - use std::{ - assert_matches::assert_matches, - io::{Read, Write}, - }; - - use bytes::Buf; - use mockall::{mock, Sequence}; - - use crate::{ - instrument::{self, info::Info, Language, Login, Script}, - interface::{self, NonBlock}, - test_util, Flash, InstrumentError, - }; - - use super::Instrument; - - #[test] - fn login_not_needed() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - // A successful login attempt on a TTI instrument is as follows: - // 1. Instrument connects to interface - // 2. Instrument sends "*STB?\n" - // 3. Instrument reads from interface and receives status byte - // 4. Instrument returns `instrument::State::NotNeeded` - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"0\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"0\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::NotNeeded)); - - assert!(instrument.login(b"secret_token").is_ok()); - } - - #[test] - #[allow(clippy::too_many_lines)] //Allow for now - fn login_success() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() { first check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() {write(b"login {token}")} - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"login secret_token\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - // login() { second check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"0\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"0\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - - assert_matches!(instrument.login(b"secret_token"), Ok(())); - - assert_matches!(instrument.check_login(), Ok(instrument::State::NotNeeded)); - } - - #[test] - #[allow(clippy::too_many_lines)] //Allow for now - fn login_failure() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() { first check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() {write(b"login {token}")} - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"login secret_token\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - // login() { second check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*STB?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - - assert_matches!( - instrument.login(b"secret_token"), - Err(InstrumentError::LoginRejected) - ); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - } - - #[test] - fn info() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_set_nonblocking() - .times(..) - .returning(|_| Ok(())); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*IDN?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 50) - .return_once(|buf: &mut [u8]| { - let msg = b"KEITHLEY INSTRUMENTS,MODEL 2450,0123456789,1.2.3d\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - let info = instrument - .info() - .expect("instrument can get instrument information from MockInterface"); - - let exp_vendor = "KEITHLEY INSTRUMENTS".to_string(); - let exp_model = "2450".to_string(); - let exp_serial = "0123456789".to_string(); - let exp_fw = "1.2.3d".to_string(); - - assert_eq!(info.vendor.unwrap(), exp_vendor); - assert_eq!(info.model.unwrap(), exp_model); - assert_eq!(info.serial_number.unwrap(), exp_serial); - assert_eq!(info.firmware_rev.unwrap(), exp_fw); - } - - #[test] - fn get_language_tsp() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*LANG?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 4) - .return_once(|buf: &mut [u8]| { - let msg = b"TSP\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_eq!( - instrument.get_language().unwrap(), - instrument::CmdLanguage::Tsp - ); - } - - #[test] - fn get_language_scpi() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*LANG?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 5) - .return_once(|buf: &mut [u8]| { - let msg = b"SCPI\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_eq!( - instrument.get_language().unwrap(), - instrument::CmdLanguage::Scpi - ); - } - - #[test] - fn change_language() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*LANG TSP\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*LANG SCPI\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert!(instrument - .change_language(instrument::CmdLanguage::Tsp) - .is_ok()); - - assert!(instrument - .change_language(instrument::CmdLanguage::Scpi) - .is_ok()); - } - - #[test] - fn write_script() { - let optional_writes: Vec> = vec![ - (*b"abort\n").into(), - (*b"_orig_prompts = localnode.prompts localnode.prompts = 0\n").into(), - (*b"localnode.prompts = _orig_prompts _orig_prompts = nil\n").into(), - ]; - let expected: Vec> = vec![ - (*b"test_script=nil\n").into(), - (*b"loadscript test_script\n").into(), - (*b"line1\n").into(), - (*b"line2\n").into(), - (*b"line3\n").into(), - (*b"\nendscript\n").into(), - ]; - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - for o in optional_writes { - interface - .expect_write() - .times(..) - .withf(move |buf: &[u8]| buf == o) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - for e in expected { - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(move |buf: &[u8]| buf == e) - .returning(|buf: &[u8]| Ok(buf.len())); - } - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], false, false) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_run() { - let optional_writes: Vec> = vec![ - (*b"abort\n").into(), - (*b"_orig_prompts = localnode.prompts localnode.prompts = 0\n").into(), - (*b"localnode.prompts = _orig_prompts _orig_prompts = nil\n").into(), - ]; - let expected: Vec> = vec![ - (*b"test_script=nil\n").into(), - (*b"loadscript test_script\n").into(), - (*b"line1\n").into(), - (*b"line2\n").into(), - (*b"line3\n").into(), - (*b"\nendscript\n").into(), - (*b"test_script.run()\n").into(), - ]; - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - for o in optional_writes { - interface - .expect_write() - .times(..) - .withf(move |buf: &[u8]| buf == o) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - for e in expected { - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(move |buf: &[u8]| buf == e) - .returning(|buf: &[u8]| Ok(buf.len())); - } - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], false, true) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_save() { - let optional_writes: Vec> = vec![ - (*b"abort\n").into(), - (*b"_orig_prompts = localnode.prompts localnode.prompts = 0\n").into(), - (*b"localnode.prompts = _orig_prompts _orig_prompts = nil\n").into(), - ]; - let expected: Vec> = vec![ - (*b"test_script=nil\n").into(), - (*b"loadscript test_script\n").into(), - (*b"line1\n").into(), - (*b"line2\n").into(), - (*b"line3\n").into(), - (*b"\nendscript\n").into(), - (*b"test_script.save()\n").into(), - ]; - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - for o in optional_writes { - interface - .expect_write() - .times(..) - .withf(move |buf: &[u8]| buf == o) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - for e in expected { - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(move |buf: &[u8]| buf == e) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], true, false) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_save_run() { - let optional_writes: Vec> = vec![ - (*b"abort\n").into(), - (*b"_orig_prompts = localnode.prompts localnode.prompts = 0\n").into(), - (*b"localnode.prompts = _orig_prompts _orig_prompts = nil\n").into(), - ]; - let expected: Vec> = vec![ - (*b"test_script=nil\n").into(), - (*b"loadscript test_script\n").into(), - (*b"line1\n").into(), - (*b"line2\n").into(), - (*b"line3\n").into(), - (*b"\nendscript\n").into(), - (*b"test_script.save()\n").into(), - (*b"test_script.run()\n").into(), - ]; - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - for o in optional_writes { - interface - .expect_write() - .times(..) - .withf(move |buf: &[u8]| buf == o) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - for e in expected { - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(move |buf: &[u8]| buf == e) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], true, true) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn flash_firmware() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| String::from_utf8_lossy(buf).contains("localnode.prompts")) - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"if ki.upgrade ~= nil and ki.upgrade.noacklater ~= nil then ki.upgrade.noacklater() end\n") - .returning(|buf: &[u8]| Ok(buf.len()) ); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"prevflash\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == test_util::SIMPLE_FAKE_BINARY_CHUNK0) - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == test_util::SIMPLE_FAKE_BINARY_CHUNK1) - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == test_util::SIMPLE_FAKE_BINARY_CHUNK2) - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == test_util::SIMPLE_FAKE_BINARY_CHUNK3) - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"endflash\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .flash_firmware(test_util::SIMPLE_FAKE_BINARY_FW, Some(0)) - .expect("instrument should have written fw to MockInterface"); - } - - // Define a mock interface to be used in the tests above. - mock! { - Interface {} - - impl interface::Interface for Interface {} - - - impl Read for Interface { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result; - } - - impl Write for Interface { - fn write(&mut self, buf: &[u8]) -> std::io::Result; - - fn flush(&mut self) -> std::io::Result<()>; - } - - impl NonBlock for Interface { - fn set_nonblocking(&mut self, enable: bool) -> crate::error::Result<()>; - } - } -} diff --git a/src/model/versatest.rs b/src/model/versatest.rs deleted file mode 100644 index 2979b13..0000000 --- a/src/model/versatest.rs +++ /dev/null @@ -1,994 +0,0 @@ -use std::{ - io::{BufRead, Read, Write}, - time::Duration, -}; - -use crate::{ - instrument::{self, info::InstrumentInfo, language, Info, Login, Script}, - interface::Interface, - interface::NonBlock, - Flash, InstrumentError, -}; -use bytes::Buf; -use language::Language; -use serde::{Deserialize, Serialize}; - -impl Instrument { - #[must_use] - pub fn is(info: &InstrumentInfo) -> bool { - info.model.as_ref().map_or(false, is_versatest) - } - - #[must_use] - pub const fn new(interface: Box) -> Self { - Self { - info: None, - interface, - } - } - - pub fn add_info(&mut self, info: InstrumentInfo) -> &Self { - self.info = Some(info); - self - } -} - -fn is_versatest(model: impl AsRef) -> bool { - ["VERSATEST-600", "TSPop"].contains(&model.as_ref()) -} - -pub struct Instrument { - info: Option, - interface: Box, -} - -//Implement device_interface::Interface since it is a subset of instrument::Instrument trait. -impl instrument::Instrument for Instrument {} - -impl Info for Instrument {} - -impl Language for Instrument {} - -impl Login for Instrument { - fn check_login(&mut self) -> crate::error::Result { - self.write_all(b"print('unlocked')\n")?; - - let mut resp: Vec = vec![0; 256]; - let _read = self.read(&mut resp)?; - - let resp = std::str::from_utf8(resp.as_slice()) - .unwrap_or("") - .trim_matches(char::from(0)) - .trim(); - - if resp.contains("FAILURE") { - Ok(instrument::State::Needed) - } else { - Ok(instrument::State::NotNeeded) - } - } - - fn login(&mut self, token: &[u8]) -> crate::error::Result<()> { - if instrument::State::NotNeeded == self.check_login()? { - return Ok(()); - } - - self.write_all(format!("password {}\n", String::from_utf8_lossy(token)).as_bytes())?; - - if instrument::State::Needed == self.check_login()? { - return Err(InstrumentError::LoginRejected); - } - - Ok(()) - } -} - -impl Script for Instrument {} - -impl Read for Instrument { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - self.interface.read(buf) - } -} - -impl Write for Instrument { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.interface.write(buf) - } - - fn flush(&mut self) -> std::io::Result<()> { - self.interface.flush() - } -} - -/// The information necessary to flash an instrument. -#[derive(Serialize, Deserialize, Debug)] -struct FirmwareInfo { - /// For VersaTest only: `true` - the firmware is for a module; `false`: the firmware is for the mainframe - #[serde(rename = "IsModule")] - is_module: bool, - - /// For VersaTest only: The slot number of the module to update. - #[serde(rename = "Slot")] - slot: u8, -} -pub const VERSATEST_FLASH_UTIL_STR: &[u8] = include_bytes!("resources/flashUtil.tsp"); -impl Flash for Instrument { - fn flash_firmware( - &mut self, - image: &[u8], - firmware_info: Option, - ) -> crate::error::Result<()> { - let mut is_module = false; - let slot_number: u16 = firmware_info.unwrap_or(0); - if slot_number > 0 { - is_module = true; - } - - //TODO This is temporary: Only use while not defined in FW - if is_module { - self.write_script(b"FlashUtil", VERSATEST_FLASH_UTIL_STR, false, true)?; - } - //.update {"FileName": "C:/Users/esarver1/Downloads/trebuchet-mainframe-sd-225642.x", "IsModule": false, "Slot": 1} - //.update {"FileName": "C:/Users/esarver1/Downloads/kingarthur-module-225665.x", "IsModule": true, "Slot": 1} - - self.write_all(b"localnode.prompts=0\n")?; - let image = image.reader(); - self.write_all(b"flash\n")?; - - for line in image.lines() { - self.write_all(format!("{}\n", line?).as_bytes())?; - } - self.write_all(b"endflash\n")?; - - if is_module { - //TODO This is temporary: Only use while not defined in FW - self.write_all(b"FlashUtil()\n")?; - self.write_all(format!("flashupdate(slot[{slot_number}])\n").as_bytes())?; - - let flash_util_global_functions = [b"flashupdate", b"flashverify", b"flashencode"]; - - for func in flash_util_global_functions { - //wait before deleting functions - std::thread::sleep(Duration::from_millis(100)); - let _ = - self.write_all(format!("{} = nil\n", String::from_utf8_lossy(func)).as_bytes()); - } - - let script_name = "FlashUtil"; - self.write_all(format!("{script_name} = nil\n").as_bytes())?; - //TODO use this when the FW team has implemented it: - // self.write(format!("slot[{slot_number}].firmware.update()\n").as_bytes()); - } else { - //Update Mainframe - self.write_all(b"firmware.update()\n")?; - } - //self.write("localnode.prompts=1\n".to_string().as_bytes()); - - Ok(()) - } -} - -impl NonBlock for Instrument { - fn set_nonblocking(&mut self, enable: bool) -> crate::error::Result<()> { - self.interface.set_nonblocking(enable) - } -} - -impl Drop for Instrument { - fn drop(&mut self) { - let _ = self.interface.write_all(b"abort\n"); - } -} - -#[cfg(test)] -mod unit { - use std::{ - assert_matches::assert_matches, - io::{BufRead, Read, Write}, - }; - - use bytes::Buf; - use mockall::{mock, Sequence}; - - use crate::{ - instrument::{self, info::Info, Login, Script}, - interface::{self, NonBlock}, - test_util, Flash, InstrumentError, - }; - - use super::Instrument; - - #[test] - fn login_not_needed() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - // A successful login attempt on a TTI instrument is as follows: - // 1. Instrument connects to interface - // 2. Instrument sends "*STB?\n" - // 3. Instrument reads from interface and receives status byte - // 4. Instrument returns `instrument::State::NotNeeded` - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 2) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::NotNeeded)); - - assert!(instrument.login(b"secret_token").is_ok()); - } - - #[test] - #[allow(clippy::too_many_lines)] //Allow for now. - fn login_success() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() { first check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() {write(b"login {token}")} - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"password secret_token\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - // login() { second check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"unlocked\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - - assert_matches!(instrument.login(b"secret_token"), Ok(())); - - assert_matches!(instrument.check_login(), Ok(instrument::State::NotNeeded)); - } - - #[test] - #[allow(clippy::too_many_lines)] //Allow for now - fn login_failure() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() { first check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // login() {write(b"login {token}")} - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"password secret_token\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - // login() { second check_login() } - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - - // check_login() - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"print('unlocked')\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 8) - .return_once(|buf: &mut [u8]| { - let msg = b"FAILURE\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInstrument should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - - assert_matches!( - instrument.login(b"secret_token"), - Err(InstrumentError::LoginRejected) - ); - - assert_matches!(instrument.check_login(), Ok(instrument::State::Needed)); - } - - #[test] - fn info() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"*IDN?\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_read() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf.len() >= 50) - .return_once(|buf: &mut [u8]| { - let msg = b"KEITHLEY INSTRUMENTS,MODEL 2450,0123456789,1.2.3d\n"; - if buf.len() >= msg.len() { - let bytes = msg[..] - .reader() - .read(buf) - .expect("MockInterface should write to buffer"); - assert_eq!(bytes, msg.len()); - } - Ok(msg.len()) - }); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - let info = instrument - .info() - .expect("instrument can get instrument information from MockInterface"); - - let exp_vendor = "KEITHLEY INSTRUMENTS".to_string(); - let exp_model = "2450".to_string(); - let exp_serial = "0123456789".to_string(); - let exp_fw = "1.2.3d".to_string(); - - assert_eq!(info.vendor.unwrap(), exp_vendor); - assert_eq!(info.model.unwrap(), exp_model); - assert_eq!(info.serial_number.unwrap(), exp_serial); - assert_eq!(info.firmware_rev.unwrap(), exp_fw); - } - - #[test] - fn write_script() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], false, false) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_run() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.run()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], false, true) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_save() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.save()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], true, false) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn write_script_save_run() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"_orig_prompts = localnode.prompts localnode.prompts = 0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"localnode.prompts = _orig_prompts _orig_prompts = nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - //Accept any number of flushes - interface.expect_flush().times(..).returning(|| Ok(())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script=nil\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"loadscript test_script\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line1\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line2\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"line3\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"\nendscript\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.save()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"test_script.run()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .write_script(b"test_script", &b"line1\nline2\nline3"[..], true, true) - .expect("instrument should have written script to MockInterface"); - } - - #[test] - fn flash_firmware() { - let mut interface = MockInterface::new(); - - let mut seq = Sequence::new(); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"localnode.prompts=0\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"flash\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - for line in test_util::SIMPLE_FAKE_TEXTUAL_FW.reader().lines() { - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(move |buf: &[u8]| { - buf == format!( - "{}\n", - line.as_ref() - .expect("textual test firmware should return all Ok for lines()") - ) - .as_bytes() - }) - .returning(|buf: &[u8]| Ok(buf.len())); - } - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"endflash\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - interface - .expect_write() - .times(1) - .in_sequence(&mut seq) - .withf(|buf: &[u8]| buf == b"firmware.update()\n") - .returning(|buf: &[u8]| Ok(buf.len())); - interface - .expect_write() - .times(..) - .withf(|buf: &[u8]| buf == b"abort\n") - .returning(|buf: &[u8]| Ok(buf.len())); - - let mut instrument: Instrument = Instrument::new(Box::new(interface)); - - instrument - .flash_firmware(test_util::SIMPLE_FAKE_TEXTUAL_FW, Some(0)) - .expect("instrument should have written fw to MockInterface"); - } - - // Define a mock interface to be used in the tests above. - mock! { - Interface {} - - impl interface::Interface for Interface {} - - - impl Read for Interface { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result; - } - - impl Write for Interface { - fn write(&mut self, buf: &[u8]) -> std::io::Result; - - fn flush(&mut self) -> std::io::Result<()>; - } - impl NonBlock for Interface { - fn set_nonblocking(&mut self, enable: bool) -> crate::error::Result<()>; - } - } -} diff --git a/src/test_util/mod.rs b/src/test_util/mod.rs deleted file mode 100644 index 7af739d..0000000 --- a/src/test_util/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub const SIMPLE_FAKE_BINARY_FW: &[u8] = include_bytes!("./simple_fake_binary_fw.test"); -pub const SIMPLE_FAKE_BINARY_CHUNK0: &[u8] = include_bytes!("./simple_fake_binary_fw.chunk0"); -pub const SIMPLE_FAKE_BINARY_CHUNK1: &[u8] = include_bytes!("./simple_fake_binary_fw.chunk1"); -pub const SIMPLE_FAKE_BINARY_CHUNK2: &[u8] = include_bytes!("./simple_fake_binary_fw.chunk2"); -pub const SIMPLE_FAKE_BINARY_CHUNK3: &[u8] = include_bytes!("./simple_fake_binary_fw.chunk3"); -pub const SIMPLE_FAKE_TEXTUAL_FW: &[u8] = include_bytes!("./simple_fake_textual_fw.test"); diff --git a/src/test_util/simple_fake_binary_fw.chunk0 b/src/test_util/simple_fake_binary_fw.chunk0 deleted file mode 100644 index 7522b6b1468fa834055e6b103142c07b936d5fd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmV~$17H{c0Kl;Jwr$(?ZriqP+qP}nwr$(Coqz-)FhK}PFoF|;kc1*MVF*h&!V`gr zL?SX#h)Oh~6N8wF-b^DGLn;ml%ygxX-G>t(vyLVWFj+J$VxV{ zlY^Y(A~$)+OFja~PXP*2h{6=1D8(pF2})9m(v+brs7?)PQj6Nu zp)U2PPXij#h{iObDa~k33tG~O*0iB5?PyO2I?{>GbfGKV=uQuM(u>~op)dXD&j1E8 zh`|hDD8m@e2u3oB(Trg%;~38bCNhc1Okpb1n9dAlGK<;FVJ`ES&jJ>*h{Y^nDa%;S z3Rbd;)vRGH>sZeQHnNG$Y+)*>T;VF$xXul3a*NyC;V$>M&jTLvh{rtPDbIM$3tsYy*Sz5^?|9D#KJtmr zeBmqK_|6Z0@{8a6;V=I{4P;=07}Q_}H-sS#WoW|~)^LV5f)R~mWTP0>Xht`NF^y$x z;~3X?#y5cpO=Mz|nABt@H-#xpWopxy)^w&fgBi_aX0w>pY-TryIn8Bm^O)Cs2AJOh z7POFsEn-oNS=sj9hHnfqAZDLcK z+1wVkw3V%GV_VzV-VS!Olb!8iSG(EW9`>}Cz3pRP``OpT1dE678^pvMP<5|yn-V0vzl9#>WRj+y7 z8{YJmx4q+C?|I(`KJ<}~ed1G}`P>)2^p&rD<6GbP-Vc8Clb`+KSHJn)AO7^0zy0H1 G|M?%r_5ct7 diff --git a/src/test_util/simple_fake_binary_fw.chunk1 b/src/test_util/simple_fake_binary_fw.chunk1 deleted file mode 100644 index 90600f99c5454b0b833b3f377a489c5f3e1087eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmV~$1Aq_!0KmZ7vTfV8KHIi!+qP}nwr$(C?Ylq(1|$eU2}W>25Ry=YCJbQ-M|dI- zkw`=)3Q>thbYc*bSi~j{afwHK5|EHYBqj+-Nk(!~kdjoSCJkvxM|v`lkxXPJ3t7oV zc5;xDT;wJXdC5lr`6)m_3Q?FM6r~u&DM3j}QJON8r5xp{Kt(E1nJQGJ8r7*mO=?k_ zI@F~e^=Uvu8qt_0G^H8MX+cX`(V8~2r5)|*Ku0>!nJ#pt8{O$aPkPatKJ=v@{TaYO z1~Hf+3}qO@8NoS|UJKW_S_j$lW9`TqbJmneBdBICw@tQZh^xvbJ@sYd!1Rz=k%mu}y4h zGn?DOmbS9BZER~h+uOm8cCxcw>}of=+rysrvbTNgYd`xtz<~~OutOZ`Fo!$Bk&be- zV;t)^$2-A^PI9tSoa!{EJHwgIa<+4v>pbVXz=bYyu}fU)GMBr;m9BENYh3F(*So=u zZgR6*-0C*ByThICa<_Zj>pu5;z=Iz0utz-VF^_w~lb-UlXFTgU&wIg(Uh=Y6yy`Wt zd&8UF^0s%p>pk!Lz=uBau}^&JGoSmym%j3~Z+z=J-}}Lje)6+l{OUKq`@^69^0$Bd H>p%Yk$8H1= diff --git a/src/test_util/simple_fake_binary_fw.chunk2 b/src/test_util/simple_fake_binary_fw.chunk2 deleted file mode 100644 index e677bf4528e13b9956a27716bc5d0f8bbf4391d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmV~$1Aq_!0KmYoW!tvx`fS^_ZQHhO+qP}nw(kNFm>>iNBpAU7K}bRonlOYV9N~#T zL?RKHC`2V1(TPD!ViB7-#3df_NkBppk(eYTB^k*{K}u4Qnlz*(9qGwHMlz9^EMz4c z*~vjpa*>-ngYE-8NHK|2y z>QI+@)TaRrX+&e1(3EC0rv)u(MQhs7mUgtK10Cr^XS&dpZgi&yJ?TYn`p}nt^k)DA z8N^_QFqB~oX9Ob|#c0MbmT`<{0u!0UWTr5cX-sDZGnvI~<}jCe%x3`$S;S(Nu#{yi zX9X)+#cI~DmUXOW0~^`IX11`EZER-;JK4o<_OO?I?B@UnImBU(aFk;l=L9D?#c9rP zmUEov0vEZ&Wv+0QYh33BH@U@a?r@iT+~)xgdBkI$@RVmf=LIi$#cSU1mUq1810VUs zXTI>2Z+zzmKl#OP{_vN71TwHe3@U0cgB!w-hBCBa3~M;U8^MT1GO|&OYBZx8!M0~^}N#x}93 z&1`N9TiVLjwy~}4Y;OlU+R4s#v8&zeZV!9f%ii{}ul?-r00%nA!47e#!yN7iM>@*U zj&ZEx9Pb1tI?2gSajMgt?hI!-%h}FxuJfGl0vEc-#V&EF%UtdXSGvm8u5qpFT<-=q zy2;IMajVZgd`N92}4-I5uOM{ zBodK{LR6v=ofyO<7O{y#T;dU*1SBL8iAh3Il98Mgq$CxoNkdxFk)8}>Bomp*LRPYo zogCyO7rDtpUh)w@ehN^KLKLP5MJYycN>Gwgl%@=2DMxuKP?1VhrV3T5Ms;dXlUmfK z4t1$VeHze^Ml_}gO=(7RTF{bKw5APhX-9iH(2-7brVCx^Mt6G9lV0?u4}IxJe+Dp+ zK@4UHLm9?!Mlh05jAjgD8OL}gFp)`2W(rf8#&l*dlUdAW4s)5ud={{fMJ#3sOIgNp zR)oEPH>V_oaPK? zImdY}aFI(~<_cH2#&vFRlUv;84tKf7eID?TM?B^UPkF|3UhtAvyygvWdB=M`@R3h^ z<_ll>#&>@3lVAMi4}bYbAOjo3pawIzs38n#C_@{@u!b|d5sYXgBOAr2Ml-rGjA<-m z8^^fDGrkE-Xd)Av#H1!OxhYI(DpQ-rw5Bt?8O&%VGn>V%W;44v%xNxjo5#H7Gr;^7 zu%Lx3Y!QoE%;J`?q@^rv8OvJE@>Z~-m8@(Pt6I(K*083vtZg0ZTF?46u%V4?Y!jQ> z%;vVRrLAmj8{68>_I9wNo$PEEyV}j}_OPeD>}?=1`K%;Ao3q@x_| z7{@x!@lJ4}lbq}nr#j8)&Tyu)ob4RvI?wqoaG{G_>=Ku{%;m0drK?=+8rQnc^=@#Z zo80Ucx4O;k?r^8O-0dFsy3hR{@Sul0>=BQ8%;TQ$q^CUX8P9so^Iq_xm%Qv1uX@ev z-teZkyzL$Dde8el@S%@<>=U2*%;&!FrLTPL8{hiQ_kQrBpZx3>zxvJZ{_v;2{OuqA G`p^H!UJMWb diff --git a/src/test_util/simple_fake_binary_fw.test b/src/test_util/simple_fake_binary_fw.test deleted file mode 100644 index e911c8ec2afa04b9666226c0a73db90ca56848f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmWO717i>h6hPtYn{95{wpOcU+qP}HwrtzBZQHhOzxN}~cK{Fw7z7jy9Ku0(hyW2G z5=4e55EY_9bcg{lAr{1jI1m@&L3~I62_X?Ah9r;_0w55QL2^g|DIpc4hBS~C(m{I2 z02v_@WQHt|6|zBg$N@Pa7vzRKkQeenekcG1p%4T?VJHH@P!x(m2o#4BP!dW(X($6_ zp&XQl3Q!R$L1m}{RiPSGhZ;~5YC&zN19hPu)Q1Mp5E?;aXaY^488n9$&=OifYiI*) zp&hh`4$u)gL1*X!U7;IvhaS)qdO>gK1AU<%^oId35C*|u7y?6K7z~FIFcL<=Xb6Qc z7z1Nr9E^tvFcBufWS9a|VH!+_888!O!EBfVb73CLhXt?@7Qtdz0!v{TEQb}a5>~-# zSOaTe9ju29un{)FX4nE-VH<3R9k3I2!EV?Cdto2!hXZgB4#8nK0!QH(9ETHd5>CNs zI0I+l9Gr&>a1k!SWw-)Y;Tl|r8*meD!ELw$ci|q~hX?Qw9>HUH0#D%?Jck$X5?;Y; zcmr?Y9lVDR@DV=2XZQkN;TwF1AMg`?!Eg8jf8iehA`&tRDjGV5!|)gZBVr_sj8QNu zM#JbB17l(=jE!+HF2=+7m;e)EB20`)FewILAST1)m;zH`Dol-OFfFFT^q2uNVkXRt zSuiVR!|a#?b7C&cjd?IH=EMA001ILv48p=#1cR|C7Q+xMjwP@pmcr6l2FqeOERPki zB38o6SOu$MHLQ*`uqM{R+E@qcVm+*n4X`0L!p7JHn_@F;jxDeyw!+rf2HRpgY>yqV zBX+{h*af>{H|&l*uqXDy-q;8GVn6JU18^V?!ofHMhvG0Cjw5g+j>6FxieWeg$Kp5~ zj}verPQuAJ1*hUPoQ^YaCeFgyI0xtAJe-dUa3LSeNC+@=CxCi&*KHQH7@E{(-!*~Rb;xRmqC-5Ym!qa#L&*C{e zj~DPFUc$?G1+U^YypA{UCf>r^cn9y|J-m+(@F70J$M^)F;xl}XFYqP4!q@l)-{L!b zk00;VA+|q(~H*qEJ+dM$st- z#iUpio8nMhibwG&0VSkFl$erGQVO6zN=C^k1*N1^l$z2|T1rRhDFbDsOq7|jP*%!D z*(nF*q+FDn@=#vNNBOA$6{JEGM1`pc1yfNfMj=$3N>E8EMWv|>m8Ei2o+?m9szjBk z3RR_QRGn&2O{zt;sSeepdQ_hpP(x}&jj0JWrDoKeT2M=BMXjj~wWW5{o;pxR>O`HX z3w5P#)SY@zPwGXzsSov~e$<}^&_EhQgJ}p2rC~IjM$kwaMWZQ{!e|VQrExT#CeTEh zM3ZR>O{Hlxoo3KXnnkl|4$Y-`G@lmGLRv(NX$dW*Wwe}D&`MfGt7#3brFFEPHqb`e zM4M>~ZKZ9rop#Vp+C{r*5ACIWw4V;pK{`Z-=?ERAV|1KO&`CN)r|ArxrE_$iF3?4~ zM3?CbU8QSuoo>)gx<$9?4&9}Dbe|s3LwZDy=?OihXY`z2&`WwnujviFrFZn6KF~+{ zM4#ykeWh>ooqo_y`bEF#5B;To|I?35%q*;I>>Q56a|DjakvK9(;iw#qqjL<7$+0*# z$KkjfkK=O!PRNNkF(=`q9KeB`jFWQ;PRXe_HK*aUoQ~6T2F}QtI5TJAtelOra}LhQ zxi~lH;k=xW^K$_%$b~qF3v&?;=AvATL%2AX;F4U5OLG}6%jLK{SKx|Vi7RszuFBQ8 zI@jQuT#IXS9j?puxIQ=FhTMo7a}#dL&A2(Y;FjEqTXP$3%k8*5ci@iPi92%_?#kV` zJNMw8+>3j2AMVTjxIYizfjo!@^AH}&!+1E4;E_CvM{_8L@faS<<9Iwz;E6nmC-W4Z z%F}o{&)}Ini)Zs3p3C!iJ}=;fyoeX`5?;#7csZ}&mAr~q^BP{u>v%nH;ElYAH}e+W z%G-E5@8F%hi+A%L-pl)VKOf+Oe25S85kAVt_&A^7lYEL#^BF$N=lDEd;EQ~TFY^_? z%GdZh-{6~ki*NHCzRUOcK0n}x{D>d(6Mo9i_&LAem;8!f^BaE4@Ay4`;E()?Kl2y< z%HQ}q|KOkei+}SU{>%UVA3q8Si-?MeOE?KH5hS8SlE@N8qDnN0E-@sg#FE$&N8(C6 zi7yExp(K*Tl0=e9fCNf1NiHcQrKFP7l19=>I!P}XB%@@K%#ua2N;b(ZIV7j#lH8I< z@=89*F9oEa6p|n*EJY+(ib^pFk>XN9N=hjyEoG#vl#}vOK`KfmsVr5bs#KHeQbTG= zEvYSaq^{JH`qDreN+W43O{A$bljhPwT1qQvEp4Q&w3GJIK{`q&=`3BOt8|m@(nESm zFX=6Pq_6ao{xU!Y${-mmLu9B7li@N#M#?A|Euj)7V`Qw1lkqY^Cdwq4EK_8vOq1y{ zLuSe>nJsf zLw3q8*)4lyuk4fkazGBsAvr8ZnXc}E(XiSZzu{Dmy)p#0T6KFzB zq=_|&Ce;89)MT1mQ)o&}rKvTIrqy(sUNdM$&7_$%i)Phqnq6~fPR*scHIL@ie41Yi zXhAKcL0VXgXs{O5Vj7~wwS<<`Qd(NeXjv_%<+XxV)Jj@et7uiNrq#8E*3?>BTkB|D zt*7<1fi~1e+E|-tQ*EZrwS~6SR@z$IXj^Tk?X`n;)K1!2yJ%PKrrouN_S9b5Tl;8V z?Wg^9fDY6_I#`G3P#vbjb%c)8Q94>fHB86oSRJS1b%IXRNjh1l=v1Ai({+Z<)LA-P z=jdFWr}K4zF4RT3SeNKhU8c)*g|5_9x?0!hT3x5>b%SoyO}bgP=vLjP+jWQT)Lpt; z_vl{Tr~CDQ9@Im6SdZvYJ*LO?gr3w>dRouuSv{xc^@3j1OL|$a=vBR@*Y$?p)LVL6 z@915TM|oZ z0TyV*>^ zuobajD{93o#EM%9D`};yw3V^4R?f;>1*>S4tg=RSVA zXpO9~HL<4F%$i#ZYiX^lwY9Of*3Q~n2kU5^th05ouGY=ETMz4Ly{xzOvA)*N`r7~- zXoGC94Y8p%%!b6#w1rxjjj^#d&c@pWn`o14vQ4q6HqEBn44Y}QY_`p@xi-({ z+X7o?i)^tiv8A@mmfH$jX{&6tt+BPX&eq!o+i06?vu&}hw#~NN4%=zFY`5*Py|&Nx z+W|XhhwQK&v7>g(j@t=4X{YS8ow2ia&d%EfyJ(l}vR$#OcFnHa4ZCT#?6%#pyLQj+ z+XH)OkL`~zxL0- z(aG7x)y>_*d3cZD5j~Pe_9!0Jqj_|X;W0gy$M!fL*W-D7Pv8kXktg;fp40<8(35#` zPvI#&m8bSJp4QWOde7h)J(FklES}Y~d3Mj?IX#!>_B@`~^Lc(R;03*q2YF#H;=x|j zi+P9__Yz*xOL=K8<7K^^m-h-@(JOgnui{m`npgK4UejxNZLi~Xy`ID_X$4HC;4Qb;!}N^Pxl!<(`Wf?pW}0Vp3nCMzR(x> zVqfA*eVH%!6~59}`D$O|Yki%s_YJ<$H~D7Y;#+;2Z}%O((|7r9-{X6IpYQhre$Ws3 zVL#$W{g@y36MoW9`Ds7nXZ@U?_X~c}FZpG^;#d8eU-uh+({K50zvFlPp5ONe{?H%! yV}IgL{h2@a7yi;;`D=gUZ~dLW_YeNjKlx|>;$QunfA=5$(|`GI|KorCpZ^Dnq!>K_ diff --git a/src/test_util/simple_fake_textual_fw.test b/src/test_util/simple_fake_textual_fw.test deleted file mode 100644 index 980d988..0000000 --- a/src/test_util/simple_fake_textual_fw.test +++ /dev/null @@ -1,11 +0,0 @@ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ \ No newline at end of file