@@ -1131,28 +1131,72 @@ mod tests {
11311131 assert ! ( !mm. is_match( ) ) ;
11321132 }
11331133
1134- /// Hardware-gated integration test for fast deploy.
1134+ // ---------------------------------------------------------------
1135+ // Hardware-gated verify-deployment tests for each ESP32 family MCU.
1136+ //
1137+ // These tests are `#[ignore]` so they never run in CI. To exercise
1138+ // them on a local bench, set the env vars described below and run:
1139+ //
1140+ // uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real -- --ignored --nocapture
1141+ //
1142+ // Each test reads **two** environment variables:
1143+ //
1144+ // <MCU>_PORT – serial port the board is attached to (e.g. COM13, /dev/ttyUSB0)
1145+ // <MCU>_FIRMWARE – absolute path to a pre-flashed firmware.bin
1146+ //
1147+ // where <MCU> is one of ESP32, ESP32S2, ESP32S3, ESP32C2, ESP32C3,
1148+ // ESP32C6, ESP32H2, ESP32P4.
1149+ //
1150+ // The firmware directory must also contain `bootloader.bin` and
1151+ // `partitions.bin` so that verify-flash can check all three regions
1152+ // in a single esptool invocation.
1153+ //
1154+ // Bootloader offsets per chip (from esp32.rs header comment):
1155+ // 0x1000 – esp32, esp32s2
1156+ // 0x0 – esp32c2, esp32c3, esp32c5, esp32c6, esp32h2, esp32s3
1157+ // 0x2000 – esp32p4
1158+ // ---------------------------------------------------------------
1159+
1160+ /// Shared implementation for all per-chip hardware-gated verify tests.
11351161 ///
1136- /// Requires a real ESP32-S3 attached to `COM13` that has been
1137- /// pre-flashed with the FastLED reference firmware at
1138- /// `C:\Users\niteris\dev\fastled\.pio\build\esp32s3\firmware.bin`.
1139- /// Run with:
1140- /// ```
1141- /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32s3 -- --ignored --nocapture
1142- /// ```
1143- ///
1144- /// Asserts (a) verify against the same image returns `Match` in
1145- /// under 15 seconds, and (b) verify against a tampered firmware
1146- /// (1 byte flipped) returns `Mismatch`.
1147- #[ test]
1148- #[ ignore = "requires ESP32-S3 attached to COM13 with FastLED reference firmware" ]
1149- fn try_verify_deployment_real_esp32s3 ( ) {
1150- let port = "COM13" ;
1151- let reference: std:: path:: PathBuf =
1152- r"C:\Users\niteris\dev\fastled\.pio\build\esp32s3\firmware.bin" . into ( ) ;
1153- if !reference. exists ( ) {
1162+ /// 1. Reads `{port_env}` and `{firmware_env}` from the environment.
1163+ /// 2. Asserts that verify against the pre-flashed image returns `Match`
1164+ /// in under 15 seconds.
1165+ /// 3. Asserts that a tampered image (1 byte flipped) returns `Mismatch`.
1166+ fn run_verify_deployment_test (
1167+ chip : & str ,
1168+ bootloader_offset : & str ,
1169+ port_env : & str ,
1170+ firmware_env : & str ,
1171+ ) {
1172+ let port = std:: env:: var ( port_env) . unwrap_or_else ( |_| {
1173+ panic ! (
1174+ "set {} to the serial port your {} board is attached to (e.g. COM13)" ,
1175+ port_env, chip
1176+ )
1177+ } ) ;
1178+ let firmware_path = std:: env:: var ( firmware_env) . unwrap_or_else ( |_| {
11541179 panic ! (
1155- "reference firmware not found at {}; pre-build FastLED's esp32s3 env first" ,
1180+ "set {} to the absolute path of the pre-flashed firmware.bin for {}" ,
1181+ firmware_env, chip
1182+ )
1183+ } ) ;
1184+ let reference = std:: path:: PathBuf :: from ( & firmware_path) ;
1185+ assert ! (
1186+ reference. is_file( ) ,
1187+ "reference firmware not found at {}; build and flash it first" ,
1188+ reference. display( )
1189+ ) ;
1190+ let ref_dir = reference
1191+ . parent ( )
1192+ . unwrap_or_else ( || std:: path:: Path :: new ( "." ) ) ;
1193+ for name in [ "bootloader.bin" , "partitions.bin" ] {
1194+ let artifact = ref_dir. join ( name) ;
1195+ assert ! (
1196+ artifact. is_file( ) ,
1197+ "[{}] missing {} next to {}; otherwise this only verifies firmware.bin" ,
1198+ chip,
1199+ name,
11561200 reference. display( )
11571201 ) ;
11581202 }
@@ -1161,46 +1205,46 @@ mod tests {
11611205 flash_mode : "dio" . to_string ( ) ,
11621206 flash_freq : "80m" . to_string ( ) ,
11631207 default_baud : "921600" . to_string ( ) ,
1164- before_reset : "default-reset " . to_string ( ) ,
1165- after_reset : "hard-reset " . to_string ( ) ,
1208+ before_reset : "default_reset " . to_string ( ) ,
1209+ after_reset : "hard_reset " . to_string ( ) ,
11661210 } ;
11671211 let deployer = Esp32Deployer :: new (
1168- "esp32s3" , "921600" , "0x0" , "0x8000" , "0x10000" , & params, true ,
1212+ chip,
1213+ "921600" ,
1214+ bootloader_offset,
1215+ "0x8000" ,
1216+ "0x10000" ,
1217+ & params,
1218+ true ,
11691219 ) ;
11701220
1171- // Phase 1: matching image → Match
1221+ // Phase 1: matching image -> Match
11721222 let start = std:: time:: Instant :: now ( ) ;
11731223 let outcome = deployer
1174- . try_verify_deployment ( & reference, port)
1175- . expect ( "verify must not fail to run against attached ESP32-S3" ) ;
1224+ . try_verify_deployment ( & reference, & port)
1225+ . unwrap_or_else ( |e| panic ! ( "verify must not fail against attached {}: {}" , chip , e ) ) ;
11761226 let elapsed = start. elapsed ( ) ;
11771227 assert ! (
11781228 outcome. is_match( ) ,
1179- "expected Match against pre-flashed firmware; got {:?}" ,
1229+ "[{}] expected Match against pre-flashed firmware; got {:?}" ,
1230+ chip,
11801231 outcome
11811232 ) ;
11821233 assert ! (
11831234 elapsed < std:: time:: Duration :: from_secs( 15 ) ,
1184- "verify took {:?} — should complete in <15s for the FastLED 2.4MB image" ,
1235+ "[{}] verify took {:?} -- should complete in <15s" ,
1236+ chip,
11851237 elapsed
11861238 ) ;
1187- eprintln ! ( "verify (Match) elapsed: {:?}" , elapsed) ;
1239+ eprintln ! ( "[{}] verify (Match) elapsed: {:?}" , chip , elapsed) ;
11881240
1189- // Phase 2: tampered image → Mismatch
1241+ // Phase 2: tampered image -> Mismatch
11901242 let tmp = tempfile:: TempDir :: new ( ) . unwrap ( ) ;
11911243 // Copy bootloader and partitions next to the tampered firmware so
11921244 // build_verify_flash_args picks them up alongside firmware.bin.
1193- let ref_dir = reference. parent ( ) . unwrap ( ) ;
1194- std:: fs:: copy (
1195- ref_dir. join ( "bootloader.bin" ) ,
1196- tmp. path ( ) . join ( "bootloader.bin" ) ,
1197- )
1198- . unwrap ( ) ;
1199- std:: fs:: copy (
1200- ref_dir. join ( "partitions.bin" ) ,
1201- tmp. path ( ) . join ( "partitions.bin" ) ,
1202- )
1203- . unwrap ( ) ;
1245+ for name in [ "bootloader.bin" , "partitions.bin" ] {
1246+ std:: fs:: copy ( ref_dir. join ( name) , tmp. path ( ) . join ( name) ) . unwrap ( ) ;
1247+ }
12041248 let tampered = tmp. path ( ) . join ( "firmware.bin" ) ;
12051249 let mut bytes = std:: fs:: read ( & reference) . unwrap ( ) ;
12061250 // Flip a byte well past the image header to avoid invalidating
@@ -1211,13 +1255,121 @@ mod tests {
12111255 std:: fs:: write ( & tampered, & bytes) . unwrap ( ) ;
12121256
12131257 let outcome = deployer
1214- . try_verify_deployment ( & tampered, port)
1215- . expect ( "verify must not fail to run with tampered firmware" ) ;
1258+ . try_verify_deployment ( & tampered, & port)
1259+ . unwrap_or_else ( |e| {
1260+ panic ! (
1261+ "[{}] verify must not fail with tampered firmware: {}" ,
1262+ chip, e
1263+ )
1264+ } ) ;
12161265 assert ! (
12171266 !outcome. is_match( ) ,
1218- "expected Mismatch for tampered firmware; got {:?}" ,
1267+ "[{}] expected Mismatch for tampered firmware; got {:?}" ,
1268+ chip,
12191269 outcome
12201270 ) ;
1221- eprintln ! ( "verify (Mismatch) detected correctly" ) ;
1271+ eprintln ! ( "[{}] verify (Mismatch) detected correctly" , chip) ;
1272+ }
1273+
1274+ /// ESP32 (Xtensa, bootloader at 0x1000).
1275+ ///
1276+ /// ```text
1277+ /// ESP32_PORT=COM5 ESP32_FIRMWARE=C:\path\to\firmware.bin \
1278+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32 -- --ignored --nocapture
1279+ /// ```
1280+ #[ test]
1281+ #[ ignore = "requires real ESP32 board — set ESP32_PORT and ESP32_FIRMWARE" ]
1282+ fn try_verify_deployment_real_esp32 ( ) {
1283+ run_verify_deployment_test ( "esp32" , "0x1000" , "ESP32_PORT" , "ESP32_FIRMWARE" ) ;
1284+ }
1285+
1286+ /// ESP32-S2 (Xtensa single-core, bootloader at 0x1000).
1287+ ///
1288+ /// ```text
1289+ /// ESP32S2_PORT=COM6 ESP32S2_FIRMWARE=C:\path\to\firmware.bin \
1290+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32s2 -- --ignored --nocapture
1291+ /// ```
1292+ #[ test]
1293+ #[ ignore = "requires real ESP32-S2 board — set ESP32S2_PORT and ESP32S2_FIRMWARE" ]
1294+ fn try_verify_deployment_real_esp32s2 ( ) {
1295+ run_verify_deployment_test ( "esp32s2" , "0x1000" , "ESP32S2_PORT" , "ESP32S2_FIRMWARE" ) ;
1296+ }
1297+
1298+ /// ESP32-S3 (Xtensa dual-core, bootloader at 0x0).
1299+ ///
1300+ /// This is the original baseline test, now using env-var configuration
1301+ /// consistent with the rest of the family.
1302+ ///
1303+ /// ```text
1304+ /// ESP32S3_PORT=COM13 ESP32S3_FIRMWARE=C:\Users\niteris\dev\fastled\.pio\build\esp32s3\firmware.bin \
1305+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32s3 -- --ignored --nocapture
1306+ /// ```
1307+ #[ test]
1308+ #[ ignore = "requires real ESP32-S3 board — set ESP32S3_PORT and ESP32S3_FIRMWARE" ]
1309+ fn try_verify_deployment_real_esp32s3 ( ) {
1310+ run_verify_deployment_test ( "esp32s3" , "0x0" , "ESP32S3_PORT" , "ESP32S3_FIRMWARE" ) ;
1311+ }
1312+
1313+ /// ESP32-C2 (RISC-V single-core, bootloader at 0x0).
1314+ ///
1315+ /// ```text
1316+ /// ESP32C2_PORT=COM7 ESP32C2_FIRMWARE=C:\path\to\firmware.bin \
1317+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32c2 -- --ignored --nocapture
1318+ /// ```
1319+ #[ test]
1320+ #[ ignore = "requires real ESP32-C2 board — set ESP32C2_PORT and ESP32C2_FIRMWARE" ]
1321+ fn try_verify_deployment_real_esp32c2 ( ) {
1322+ run_verify_deployment_test ( "esp32c2" , "0x0" , "ESP32C2_PORT" , "ESP32C2_FIRMWARE" ) ;
1323+ }
1324+
1325+ /// ESP32-C3 (RISC-V single-core, bootloader at 0x0).
1326+ ///
1327+ /// ```text
1328+ /// ESP32C3_PORT=COM8 ESP32C3_FIRMWARE=C:\path\to\firmware.bin \
1329+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32c3 -- --ignored --nocapture
1330+ /// ```
1331+ #[ test]
1332+ #[ ignore = "requires real ESP32-C3 board — set ESP32C3_PORT and ESP32C3_FIRMWARE" ]
1333+ fn try_verify_deployment_real_esp32c3 ( ) {
1334+ run_verify_deployment_test ( "esp32c3" , "0x0" , "ESP32C3_PORT" , "ESP32C3_FIRMWARE" ) ;
1335+ }
1336+
1337+ /// ESP32-C6 (RISC-V single-core, bootloader at 0x0).
1338+ ///
1339+ /// ```text
1340+ /// ESP32C6_PORT=COM9 ESP32C6_FIRMWARE=C:\path\to\firmware.bin \
1341+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32c6 -- --ignored --nocapture
1342+ /// ```
1343+ #[ test]
1344+ #[ ignore = "requires real ESP32-C6 board — set ESP32C6_PORT and ESP32C6_FIRMWARE" ]
1345+ fn try_verify_deployment_real_esp32c6 ( ) {
1346+ run_verify_deployment_test ( "esp32c6" , "0x0" , "ESP32C6_PORT" , "ESP32C6_FIRMWARE" ) ;
1347+ }
1348+
1349+ /// ESP32-H2 (RISC-V single-core, bootloader at 0x0).
1350+ ///
1351+ /// ```text
1352+ /// ESP32H2_PORT=COM10 ESP32H2_FIRMWARE=C:\path\to\firmware.bin \
1353+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32h2 -- --ignored --nocapture
1354+ /// ```
1355+ #[ test]
1356+ #[ ignore = "requires real ESP32-H2 board — set ESP32H2_PORT and ESP32H2_FIRMWARE" ]
1357+ fn try_verify_deployment_real_esp32h2 ( ) {
1358+ run_verify_deployment_test ( "esp32h2" , "0x0" , "ESP32H2_PORT" , "ESP32H2_FIRMWARE" ) ;
1359+ }
1360+
1361+ /// ESP32-P4 (RISC-V dual-core, OPI flash, bootloader at 0x2000).
1362+ ///
1363+ /// Note: ESP32-P4 uses OPI flash and has a different bootloader offset
1364+ /// (0x2000) compared to other ESP32 chips.
1365+ ///
1366+ /// ```text
1367+ /// ESP32P4_PORT=COM11 ESP32P4_FIRMWARE=C:\path\to\firmware.bin \
1368+ /// uv run cargo test -p fbuild-deploy esp32::tests::try_verify_deployment_real_esp32p4 -- --ignored --nocapture
1369+ /// ```
1370+ #[ test]
1371+ #[ ignore = "requires real ESP32-P4 board — set ESP32P4_PORT and ESP32P4_FIRMWARE" ]
1372+ fn try_verify_deployment_real_esp32p4 ( ) {
1373+ run_verify_deployment_test ( "esp32p4" , "0x2000" , "ESP32P4_PORT" , "ESP32P4_FIRMWARE" ) ;
12221374 }
12231375}
0 commit comments