11#!/usr/bin/env python3
2- # SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+ # SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33# SPDX-License-Identifier: Apache-2.0
4+ from importlib .metadata import version
45from io import BufferedRandom
56from io import BytesIO
67from pathlib import Path
2122from nvs_parser import nvs_const
2223from nvs_parser import NVS_Entry
2324from nvs_parser import NVS_Partition
25+ from packaging .version import Version
26+
27+
28+ NVS_PART_GEN_VERSION_SKIP = '0.1.8'
29+
30+
31+ # Temporary workaround for pytest skipping tests based on the version of the esp-idf-nvs-partition-gen package
32+ @pytest .fixture (scope = 'session' , autouse = True )
33+ def before () -> None :
34+ ver = version ('esp-idf-nvs-partition-gen' )
35+ if Version (ver ) < Version (NVS_PART_GEN_VERSION_SKIP ):
36+ pytest .skip ('pass' )
2437
2538
2639class SilentLogger (NVS_Logger ):
@@ -101,7 +114,7 @@ def create_entry_data_bytearray(namespace_index: int, entry_type: int, span: int
101114
102115@pytest .fixture
103116def generate_nvs () -> Callable :
104- def _execute_nvs_setup (nvs_setup_func : Callable , size : int = 0x4000 , output : Optional [Path ] = None ) -> NVS_Partition :
117+ def _execute_nvs_setup (nvs_setup_func : Callable , output : Optional [Path ] = None ) -> NVS_Partition :
105118 nvs_file : Optional [Union [BytesIO , BufferedRandom ]] = None
106119 if output is None :
107120 nvs_file = BytesIO ()
@@ -110,15 +123,7 @@ def _execute_nvs_setup(nvs_setup_func: Callable, size: int = 0x4000, output: Opt
110123 nvs_file = open (output , 'wb+' )
111124 except OSError as e :
112125 raise RuntimeError (f'Cannot open file { output } , error: { e } ' )
113- size_fixed = nvs_partition_gen .check_size (str (size ))
114- nvs_obj = nvs_partition_gen .nvs_open (
115- result_obj = nvs_file ,
116- input_size = size_fixed ,
117- version = nvs_partition_gen .Page .VERSION2 ,
118- is_encrypt = False ,
119- key = None
120- )
121- nvs_setup_func (nvs_obj )
126+ nvs_obj = nvs_setup_func (nvs_file )
122127 nvs_partition_gen .nvs_close (nvs_obj )
123128 nvs_file .seek (0 )
124129 nvs_parsed = NVS_Partition ('test' , bytearray (nvs_file .read ()))
@@ -128,16 +133,36 @@ def _execute_nvs_setup(nvs_setup_func: Callable, size: int = 0x4000, output: Opt
128133
129134
130135# Setup functions
131- def setup_ok_primitive (nvs_obj : NVS ) -> None :
136+ def setup_ok_primitive (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
137+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x4000 ))
138+ nvs_obj = nvs_partition_gen .nvs_open (
139+ result_obj = nvs_file ,
140+ input_size = size_fixed ,
141+ version = nvs_partition_gen .Page .VERSION2 ,
142+ is_encrypt = False ,
143+ key = None ,
144+ read_only = read_only
145+ )
146+
132147 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
133148 nvs_partition_gen .write_entry (nvs_obj , 'int32_test' , 'data' , 'i32' , str (42 ))
134149 nvs_partition_gen .write_entry (nvs_obj , 'uint32_test' , 'data' , 'u32' , str (42 ))
135150 nvs_partition_gen .write_entry (nvs_obj , 'int8_test' , 'data' , 'i8' , str (100 ))
136151
152+ return nvs_obj
153+
154+
155+ def setup_ok_variable_len (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
156+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x5000 ))
157+ nvs_obj = nvs_partition_gen .nvs_open (
158+ result_obj = nvs_file ,
159+ input_size = size_fixed ,
160+ version = nvs_partition_gen .Page .VERSION2 ,
161+ is_encrypt = False ,
162+ key = None ,
163+ read_only = read_only
164+ )
137165
138- def setup_ok_variable_len (nvs_obj : NVS ) -> None :
139- size_fixed = nvs_partition_gen .check_size (str ('0x5000' ))
140- nvs_obj .size = size_fixed
141166 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
142167 nvs_partition_gen .write_entry (nvs_obj , 'short_string_key' , 'data' , 'string' , 'Hello world!' )
143168 nvs_partition_gen .write_entry (nvs_obj , 'blob_key' , 'file' , 'binary' ,
@@ -147,10 +172,20 @@ def setup_ok_variable_len(nvs_obj: NVS) -> None:
147172 nvs_partition_gen .write_entry (nvs_obj , 'multi_blob_key' , 'file' , 'binary' ,
148173 '../nvs_partition_generator/testdata/sample_multipage_blob.bin' )
149174
175+ return nvs_obj
176+
177+
178+ def setup_ok_mixed (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
179+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x6000 ))
180+ nvs_obj = nvs_partition_gen .nvs_open (
181+ result_obj = nvs_file ,
182+ input_size = size_fixed ,
183+ version = nvs_partition_gen .Page .VERSION2 ,
184+ is_encrypt = False ,
185+ key = None ,
186+ read_only = read_only
187+ )
150188
151- def setup_ok_mixed (nvs_obj : NVS ) -> None :
152- size_fixed = nvs_partition_gen .check_size (str ('0x6000' ))
153- nvs_obj .size = size_fixed
154189 prim_types = ['i8' , 'u8' , 'i16' , 'u16' , 'i32' , 'u32' ]
155190
156191 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
@@ -173,10 +208,20 @@ def setup_ok_mixed(nvs_obj: NVS) -> None:
173208 nvs_partition_gen .write_entry (nvs_obj , 'blob_key' , 'file' , 'binary' ,
174209 '../nvs_partition_generator/testdata/sample_multipage_blob.bin' )
175210
211+ return nvs_obj
212+
213+
214+ def setup_bad_mixed_same_key_different_page (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
215+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x6000 ))
216+ nvs_obj = nvs_partition_gen .nvs_open (
217+ result_obj = nvs_file ,
218+ input_size = size_fixed ,
219+ version = nvs_partition_gen .Page .VERSION2 ,
220+ is_encrypt = False ,
221+ key = None ,
222+ read_only = read_only
223+ )
176224
177- def setup_bad_mixed_same_key_different_page (nvs_obj : NVS ) -> None :
178- size_fixed = nvs_partition_gen .check_size (str ('0x6000' ))
179- nvs_obj .size = size_fixed
180225 prim_types = ['i8' , 'u8' , 'i16' , 'u16' , 'i32' , 'u32' ]
181226
182227 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
@@ -215,8 +260,20 @@ def setup_bad_mixed_same_key_different_page(nvs_obj: NVS) -> None:
215260 # the current used namespace index
216261 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
217262
263+ return nvs_obj
264+
265+
266+ def setup_bad_same_key_primitive (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
267+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x4000 ))
268+ nvs_obj = nvs_partition_gen .nvs_open (
269+ result_obj = nvs_file ,
270+ input_size = size_fixed ,
271+ version = nvs_partition_gen .Page .VERSION2 ,
272+ is_encrypt = False ,
273+ key = None ,
274+ read_only = read_only
275+ )
218276
219- def setup_bad_same_key_primitive (nvs_obj : NVS ) -> None :
220277 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
221278 nvs_partition_gen .write_entry (nvs_obj , 'unique_key' , 'data' , 'i16' , str (1234 ))
222279 nvs_partition_gen .write_entry (nvs_obj , 'same_key' , 'data' , 'i32' , str (42 ))
@@ -225,17 +282,39 @@ def setup_bad_same_key_primitive(nvs_obj: NVS) -> None:
225282 nvs_partition_gen .write_entry (nvs_obj , 'another_same_key' , 'data' , 'u16' , str (321 ))
226283 nvs_partition_gen .write_entry (nvs_obj , 'another_same_key' , 'data' , 'u16' , str (456 ))
227284
285+ return nvs_obj
286+
287+
288+ def setup_bad_same_key_variable_len (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
289+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x4000 ))
290+ nvs_obj = nvs_partition_gen .nvs_open (
291+ result_obj = nvs_file ,
292+ input_size = size_fixed ,
293+ version = nvs_partition_gen .Page .VERSION2 ,
294+ is_encrypt = False ,
295+ key = None ,
296+ read_only = read_only
297+ )
228298
229- def setup_bad_same_key_variable_len (nvs_obj : NVS ) -> None :
230299 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
231300 nvs_partition_gen .write_entry (nvs_obj , 'same_string_key' , 'data' , 'string' , 'Hello' )
232301 nvs_partition_gen .write_entry (nvs_obj , 'same_string_key' , 'data' , 'string' , 'world!' )
233302 nvs_partition_gen .write_entry (nvs_obj , 'unique_string_key' , 'data' , 'string' , 'I am unique!' )
234303
304+ return nvs_obj
305+
306+
307+ def setup_bad_same_key_blob_index (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
308+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x6000 ))
309+ nvs_obj = nvs_partition_gen .nvs_open (
310+ result_obj = nvs_file ,
311+ input_size = size_fixed ,
312+ version = nvs_partition_gen .Page .VERSION2 ,
313+ is_encrypt = False ,
314+ key = None ,
315+ read_only = read_only
316+ )
235317
236- def setup_bad_same_key_blob_index (nvs_obj : NVS ) -> None :
237- size_fixed = nvs_partition_gen .check_size (str ('0x6000' ))
238- nvs_obj .size = size_fixed
239318 nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
240319 nvs_partition_gen .write_entry (nvs_obj , 'blob_key' , 'file' , 'binary' ,
241320 '../nvs_partition_generator/testdata/sample_multipage_blob.bin' )
@@ -244,6 +323,28 @@ def setup_bad_same_key_blob_index(nvs_obj: NVS) -> None:
244323 nvs_partition_gen .write_entry (nvs_obj , 'blob_key' , 'file' , 'binary' ,
245324 '../nvs_partition_generator/testdata/sample_multipage_blob.bin' ) # Duplicate key
246325
326+ return nvs_obj
327+
328+
329+ def setup_read_only (nvs_file : Optional [Union [BytesIO , BufferedRandom ]]) -> NVS :
330+ size_fixed , read_only = nvs_partition_gen .check_size (str (0x1000 ))
331+ nvs_obj = nvs_partition_gen .nvs_open (
332+ result_obj = nvs_file ,
333+ input_size = size_fixed ,
334+ version = nvs_partition_gen .Page .VERSION2 ,
335+ is_encrypt = False ,
336+ key = None ,
337+ read_only = read_only
338+ )
339+
340+ nvs_partition_gen .write_entry (nvs_obj , 'storage' , 'namespace' , '' , '' )
341+ nvs_partition_gen .write_entry (nvs_obj , 'int32_test' , 'data' , 'i32' , str (42 ))
342+ nvs_partition_gen .write_entry (nvs_obj , 'uint32_test' , 'data' , 'u32' , str (42 ))
343+ nvs_partition_gen .write_entry (nvs_obj , 'int8_test' , 'data' , 'i8' , str (100 ))
344+ nvs_partition_gen .write_entry (nvs_obj , 'short_string_key' , 'data' , 'string' , 'Hello world!' )
345+
346+ return nvs_obj
347+
247348
248349# Helper functions
249350def prepare_duplicate_list (nvs : NVS_Partition ) -> Dict [str , List [NVS_Entry ]]:
@@ -331,3 +432,12 @@ def test_check_duplicates_bad_same_key_blob_index(generate_nvs: Callable, setup_
331432 # however there are 2 duplicates of each blob_index and blob_data
332433 assert len (list (duplicates .values ())[0 ]) == 6 # 6 entries with the blob_key (2x blob_index, 4x blob_data)
333434 nvs_check .integrity_check (nvs , logger )
435+
436+
437+ @pytest .mark .parametrize ('setup_func' , [setup_read_only ])
438+ def test_check_read_only_partition (generate_nvs : Callable , setup_func : Callable ) -> None :
439+ nvs = generate_nvs (setup_func )
440+ assert nvs .raw_data is not None
441+ assert len (nvs .raw_data ) == 0x1000
442+ assert nvs_check .check_partition_size (nvs , logger , read_only = True )
443+ assert not nvs_check .check_empty_page_present (nvs , logger )
0 commit comments