/ firmware / tests / sd_card_webpage.rs
sd_card_webpage.rs
 1  //! `describe("SD Card Webpage")`
 2  //!
 3  //! Manual integration test. The device:
 4  //!   1. mounts the SD card
 5  //!   2. ensures `/index.htm` exists (writes a minimal placeholder if absent)
 6  //!   3. starts its WiFi access point
 7  //!   4. starts a tiny HTTP/1.0 server on port 80 backed by the SD card
 8  //!
 9  //! The test then waits for an external HTTP GET to land at `/`. Pass
10  //! criterion: a request hits the device within the 5-minute timeout.
11  
12  #![no_std]
13  #![no_main]
14  
15  extern crate alloc;
16  
17  #[path = "common/mod.rs"]
18  mod common;
19  
20  use defmt::info;
21  
22  use common::{Device, tasks};
23  
24  esp_bootloader_esp_idf::esp_app_desc!();
25  
26  #[cfg(test)]
27  #[embedded_test::setup]
28  fn setup() {
29      rtt_target::rtt_init_defmt!();
30  }
31  
32  #[cfg(test)]
33  #[embedded_test::tests(default_timeout = 30, executor = esp_rtos::embassy::Executor::new())]
34  mod tests {
35      use super::*;
36  
37      #[init]
38      fn init() -> Device {
39          info!("=== SD Card Webpage — describe block ===");
40          common::setup::boot_device()
41      }
42  
43      /// `it("user can load index.htm from the device SD card over WiFi")`
44      #[test]
45      #[timeout(300)]
46      async fn user_loads_index_html_from_device_sd_card_over_wifi(
47          mut device: Device,
48      ) -> Result<(), &'static str> {
49          // SAFETY: every embedded-test runs inside an `esp_rtos::embassy::Executor`,
50          // so the current async context is owned by an Embassy executor.
51          let embassy_spawner =
52              unsafe { embassy_executor::Spawner::for_current_executor() }.await;
53  
54          tasks::sd_card::mount(&mut device)?;
55          tasks::sd_card::ensure_index_html(&mut device)?;
56          tasks::wifi::start_access_point(&mut device, embassy_spawner).await?;
57          tasks::http::start_server_serving_sd(&mut device, embassy_spawner)?;
58  
59          info!(">>> ACTION REQUIRED <<<");
60          info!(
61              ">>> 1. Connect your phone/laptop to WiFi ssid={=str}",
62              tasks::wifi::DEFAULT_ACCESS_POINT_SSID
63          );
64          info!(
65              ">>> 2. Password: {=str}",
66              tasks::wifi::DEFAULT_ACCESS_POINT_PASSWORD
67          );
68          info!(">>> 3. Open http://192.168.4.1/ in your browser");
69          info!(">>> Test will time out in 5 minutes if no request lands");
70  
71          tasks::http::wait_for_first_request(&mut device).await?;
72  
73          Ok(())
74      }
75  }