55import logging
66import hashlib
77import time
8-
98import uuid
9+ import lz4 .frame
1010from pathlib import Path
1111from datetime import datetime , timezone
1212
@@ -78,41 +78,53 @@ def _execute_and_wait_for_transfer(e2e_cfg: Configuration, interface: str, trans
7878 assert progress_received , f"No progress update received for transfer { target_id } "
7979
8080
81- def _run_full_transfer_cycle (e2e_cfg : Configuration , transfer_type : str , device_path : str ):
81+ def _run_full_transfer_cycle (e2e_cfg : Configuration , transfer_type : str , device_path : str , encoding : str = None ):
8282 """
83- Executes a complete Server -> Device -> Server test loop.
83+ Executes a complete Server -> Device -> Server test loop with optional encoding .
8484 Generates unique content, downloads to the device, uploads back to the server,
8585 and verifies the data integrity.
8686 """
87- logger .info (f"Testing full file transfer loop for type: { transfer_type } " )
87+ logger .info (f"Testing full file transfer loop for type: '{ transfer_type } ', encoding: '{ encoding } '" )
88+
89+ # Generate test data unique to the transfer type and encoding
90+ test_payload = f"Zephyr { transfer_type .capitalize ()} Transfer Test Payload! (Encoding: { encoding } ) " * 200
8891
89- # Generate test data unique to the transfer type
90- test_payload = f"Zephyr { transfer_type .capitalize ()} Transfer Test Payload! " * 200
91- test_bytes = test_payload .encode ('utf-8' )
92- file_digest = f"sha256:{ hashlib .sha256 (test_bytes ).hexdigest ()} "
92+ # We hash the UNCOMPRESSED bytes, as device code calculates digest of decompressed chunks
93+ raw_bytes = test_payload .encode ('utf-8' )
94+ file_digest = f"sha256:{ hashlib .sha256 (raw_bytes ).hexdigest ()} "
9395
94- download_filename = f"{ transfer_type } _download.txt"
95- upload_filename = f"{ transfer_type } _upload.txt"
96+ enc_suffix = f"{ encoding } " if encoding else "txt"
97+ download_filename = f"{ transfer_type } _download.{ enc_suffix } "
98+ upload_filename = f"{ transfer_type } _upload.{ enc_suffix } "
9699
97100 dl_id = str (uuid .uuid4 ())
98101 ul_id = str (uuid .uuid4 ())
99102
103+ # If encoding is lz4, create an lz4 compressed file for the server to serve
104+ server_download_bytes = raw_bytes
105+ if encoding == "lz4" :
106+ server_download_bytes = lz4 .frame .compress (raw_bytes )
107+
100108 # Write the initial file to the HTTP server's data directory
101109 download_file_path = Path (e2e_cfg .http_server_data_dir ) / download_filename
102- download_file_path .write_bytes (test_bytes )
110+ download_file_path .write_bytes (server_download_bytes )
103111
104112 # --- PHASE 1: DOWNLOAD (Server to Device) ---
105113 dl_data = {
106114 "url" : f"https://192.0.2.2:8443/{ download_filename } " ,
107115 "id" : dl_id ,
108116 "progress" : True ,
109117 "digest" : file_digest ,
110- "fileSizeBytes" : len (test_bytes ),
118+ "fileSizeBytes" : len (raw_bytes ),
111119 "httpHeaderKeys" : ["Content-Type" ],
112- "httpHeaderValues" : ["text/plain" ],
120+ "httpHeaderValues" : ["application/octet-stream" if encoding else " text/plain" ],
113121 "destinationType" : transfer_type ,
114122 "destination" : device_path ,
115123 }
124+
125+ if encoding :
126+ dl_data ["encoding" ] = encoding
127+
116128 logger .info (f"Initiating { transfer_type } download..." )
117129 _execute_and_wait_for_transfer (e2e_cfg , interface_ft_server_to_device , dl_data )
118130
@@ -122,21 +134,35 @@ def _run_full_transfer_cycle(e2e_cfg: Configuration, transfer_type: str, device_
122134 "id" : ul_id ,
123135 "progress" : True ,
124136 "httpHeaderKeys" : ["Content-Type" ],
125- "httpHeaderValues" : ["text/plain" ],
137+ "httpHeaderValues" : ["application/octet-stream" if encoding else " text/plain" ],
126138 "sourceType" : transfer_type ,
127139 "source" : device_path ,
128140 }
141+
142+ if encoding :
143+ ul_data ["encoding" ] = encoding
144+
129145 logger .info (f"Initiating { transfer_type } upload..." )
130146 _execute_and_wait_for_transfer (e2e_cfg , interface_ft_device_to_server , ul_data )
131147
132148 # --- PHASE 3: VERIFICATION ---
133149 uploaded_file_path = Path (e2e_cfg .http_server_data_dir ) / upload_filename
134150 assert uploaded_file_path .exists (), "The device failed to upload the file back to the server"
135151
136- actual_payload = uploaded_file_path .read_bytes ()
137- assert actual_payload == test_bytes , f"Data corruption! Uploaded file does not match downloaded file for { transfer_type } ."
152+ actual_uploaded_bytes = uploaded_file_path .read_bytes ()
138153
139- logger .info (f"Full transfer loop for '{ transfer_type } ' completed." )
154+ # If encoding is lz4, the device compressed the file. We need to decompress to verify.
155+ if encoding == "lz4" :
156+ try :
157+ actual_payload = lz4 .frame .decompress (actual_uploaded_bytes )
158+ except Exception as e :
159+ assert False , f"Failed to decompress the uploaded LZ4 file: { e } "
160+ else :
161+ actual_payload = actual_uploaded_bytes
162+
163+ assert actual_payload == raw_bytes , f"Data corruption! Uploaded file does not match downloaded file for { transfer_type } with encoding { encoding } ."
164+
165+ logger .info (f"Full transfer loop for '{ transfer_type } ' (encoding: '{ encoding } ') completed." )
140166
141167
142168def validate_file_transfer_capabilities (e2e_cfg : Configuration ):
@@ -145,16 +171,22 @@ def validate_file_transfer_capabilities(e2e_cfg: Configuration):
145171 ft_res = http_get_server_data (e2e_cfg , interface_ft_capabilities )
146172
147173 assert (i in ft_res for i in ["encodings" , "targets" , "unixPermissions" ]), "Wrong capabilities"
148- assert ft_res .get ("encodings" ) is None , "Wrong encodings"
174+ assert ft_res .get ("encodings" ) == [ "lz4" ] , "Incorrect capability encodings"
149175 assert ft_res .get ("targets" ) == ["streaming" , "filesystem" ], "Wrong targets"
150176 assert not ft_res .get ("unixPermissions" ), "Wrong unix permissions"
151177
152178 logger .info ("File transfer test (capabilities) completed successfully" )
153179
154-
180+ # Raw Transfer Tests
155181def validate_file_transfer_stream (e2e_cfg : Configuration ):
156- _run_full_transfer_cycle (e2e_cfg , transfer_type = "stream" , device_path = "loopback" )
157-
182+ _run_full_transfer_cycle (e2e_cfg , transfer_type = "stream" , device_path = "loopback" , encoding = None )
158183
159184def validate_file_transfer_filesystem (e2e_cfg : Configuration ):
160- _run_full_transfer_cycle (e2e_cfg , transfer_type = "filesystem" , device_path = "/lfs1/test_fs_transfer.txt" )
185+ _run_full_transfer_cycle (e2e_cfg , transfer_type = "filesystem" , device_path = "/lfs1/test_fs_transfer.txt" , encoding = None )
186+
187+ # LZ4 Transfer Tests
188+ def validate_file_transfer_stream_lz4 (e2e_cfg : Configuration ):
189+ _run_full_transfer_cycle (e2e_cfg , transfer_type = "stream" , device_path = "loopback" , encoding = "lz4" )
190+
191+ def validate_file_transfer_filesystem_lz4 (e2e_cfg : Configuration ):
192+ _run_full_transfer_cycle (e2e_cfg , transfer_type = "filesystem" , device_path = "/lfs1/test_fs_transfer_lz4.txt" , encoding = "lz4" )
0 commit comments