Skip to content

Commit 05b356f

Browse files
committed
feat(nvs): Test nvs_partition_gen.py and nvs_check.py with pytest
Little fixes in nvs_check.py
1 parent 6cb2080 commit 05b356f

File tree

5 files changed

+405
-23
lines changed

5 files changed

+405
-23
lines changed

.gitlab/ci/host-test.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,17 @@ test_idf_build_apps_load_soc_caps:
388388
extends: .host_test_template
389389
script:
390390
- python tools/ci/check_soc_headers_load_in_idf_build_apps.py
391+
392+
test_nvs_gen_check:
393+
extends: .host_test_template
394+
artifacts:
395+
paths:
396+
- XUNIT_RESULT.xml
397+
- components/nvs_flash/nvs_partition_tool
398+
reports:
399+
junit: XUNIT_RESULT.xml
400+
variables:
401+
LC_ALL: C.UTF-8
402+
script:
403+
- cd ${IDF_PATH}/components/nvs_flash/nvs_partition_tool
404+
- pytest --noconftest test_nvs_gen_check.py --junitxml=XUNIT_RESULT.xml

components/nvs_flash/nvs_partition_tool/nvs_check.py

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
# SPDX-License-Identifier: Apache-2.0
44
from typing import Dict
55
from typing import List
6+
from typing import Optional
7+
from typing import Set
68

79
from nvs_logger import NVS_Logger
810
from nvs_parser import nvs_const
911
from nvs_parser import NVS_Entry
1012
from nvs_parser import NVS_Page
1113
from nvs_parser import NVS_Partition
1214

13-
# from pprint import pprint
14-
1515

1616
EMPTY_ENTRY = NVS_Entry(-1, bytearray(32), 'Erased')
1717

18-
used_namespaces: Dict[int, None] = {}
18+
used_namespaces: Dict[int, Optional[str]] = {}
1919
found_namespaces: Dict[int, str] = {}
2020
blobs: Dict = {}
2121
blob_chunks: List[NVS_Entry] = []
@@ -83,7 +83,7 @@ def check_page_crc(nvs_page: NVS_Page, nvs_log: NVS_Logger) -> bool:
8383
return False
8484

8585

86-
def identify_entry_duplicates(entry: NVS_Entry, seen_written_entires: Dict[str, list[NVS_Entry]]) -> Dict[str, list[NVS_Entry]]:
86+
def identify_entry_duplicates(entry: NVS_Entry, seen_written_entires: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]:
8787
if entry.state == 'Written':
8888
if entry.key in seen_written_entires:
8989
seen_written_entires[entry.key].append(entry)
@@ -92,11 +92,12 @@ def identify_entry_duplicates(entry: NVS_Entry, seen_written_entires: Dict[str,
9292
return seen_written_entires
9393

9494

95-
def check_page_entries(nvs_page: NVS_Page, nvs_log: NVS_Logger) -> Dict[str, list[NVS_Entry]]:
96-
seen_written_entires: Dict[str, list[NVS_Entry]] = {}
95+
def check_page_entries(nvs_page: NVS_Page, nvs_log: NVS_Logger) -> Dict[str, List[NVS_Entry]]:
96+
seen_written_entires: Dict[str, List[NVS_Entry]] = {}
9797

9898
for entry in nvs_page.entries:
9999
# entry: NVS_Entry
100+
entry.page = nvs_page
100101

101102
# Entries stored in 'page.entries' are primitive data types, blob indexes or string/blob data
102103

@@ -205,7 +206,7 @@ def filter_namespaces_fake_duplicates(duplicate_entries_dict: Dict[str, List[NVS
205206
new_duplicate_entries_dict: Dict[str, List[NVS_Entry]] = {}
206207
for key, duplicate_entries in duplicate_entries_dict.items():
207208
seen_entries: List[NVS_Entry] = []
208-
entry_same_namespace_collisions_list: set[NVS_Entry] = set()
209+
entry_same_namespace_collisions_list: Set[NVS_Entry] = set()
209210

210211
# Search through the "duplicates" and see if there are real duplicates
211212
# E.g. the key can be the same if the namespace is different
@@ -241,8 +242,8 @@ def filter_blob_related_duplicates(duplicate_entries_dict: Dict[str, List[NVS_En
241242
seen_blob_index: List[NVS_Entry] = []
242243
seen_blob_data: List[NVS_Entry] = []
243244
seen_another_type_data: List[NVS_Entry] = []
244-
blob_index_chunk_index_collisions_list: set[NVS_Entry] = set()
245-
blob_data_chunk_index_collisions_list: set[NVS_Entry] = set()
245+
blob_index_chunk_index_collisions_list: Set[NVS_Entry] = set()
246+
blob_data_chunk_index_collisions_list: Set[NVS_Entry] = set()
246247

247248
# Search through the "duplicates" and see if there are real duplicates
248249
# E.g. the key can be the same for blob_index and blob_data
@@ -297,26 +298,44 @@ def filter_blob_related_duplicates(duplicate_entries_dict: Dict[str, List[NVS_En
297298
return new_duplicate_entries_dict
298299

299300

300-
def filter_entry_duplicates(seen_written_entires: Dict[str, list[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]:
301+
def filter_entry_duplicates(seen_written_entires: Dict[str, List[NVS_Entry]]) -> Dict[str, List[NVS_Entry]]:
301302
duplicate_entries_list = {key: v for key, v in seen_written_entires.items() if len(v) > 1}
302303
duplicate_entries_list_1 = filter_namespaces_fake_duplicates(duplicate_entries_list)
303304
duplicate_entries_list_2 = filter_blob_related_duplicates(duplicate_entries_list_1)
304305
return duplicate_entries_list_2
305306

306307

307-
def print_entry_duplicates(page: NVS_Page, duplicate_entries_list: Dict[str, List[NVS_Entry]], nvs_log: NVS_Logger) -> None:
308+
def print_entry_duplicates(duplicate_entries_list: Dict[str, List[NVS_Entry]], nvs_log: NVS_Logger) -> None:
309+
if len(duplicate_entries_list) > 0:
310+
nvs_log.info(nvs_log.red('Found duplicate entries:'))
311+
nvs_log.info(nvs_log.red('Entry\tKey\t\t\tType\t\tNamespace idx\tPage\tPage status'))
312+
308313
for _, duplicate_entries in duplicate_entries_list.items():
309-
# duplicate_entries: list[NVS_Entry]
310-
nvs_log.info(
311-
nvs_log.red(
312-
f'''Entry key {duplicate_entries[0].key} on page no. {page.header["page_index"]}
313-
with status {page.header["status"]} is used by the following entries:'''
314-
)
315-
)
314+
# duplicate_entries: List[NVS_Entry]
316315
for entry in duplicate_entries:
316+
# entry: NVS_Entry
317+
if entry.metadata['namespace'] == 0:
318+
entry_type = f'namespace ({entry.data["value"]})'
319+
else:
320+
entry_type = entry.metadata['type']
321+
322+
if entry.page is not None:
323+
page_num = entry.page.header['page_index']
324+
page_status = entry.page.header['status']
325+
else:
326+
page_num = 'Unknown'
327+
page_status = 'Unknown'
328+
329+
entry_key_tab_cnt = len(entry.key) // 8
330+
entry_key_tab = '\t' * (3 - entry_key_tab_cnt)
331+
332+
namespace_tab_cnt = len(entry_type) // 8
333+
namepace_tab = '\t' * (2 - namespace_tab_cnt)
334+
namespace_str = f'{entry.metadata["namespace"]}'
335+
317336
nvs_log.info(
318337
nvs_log.red(
319-
f'Entry #{entry.index:03d} {entry.key} is a duplicate!'
338+
f'#{entry.index:03d}\t{entry.key}{entry_key_tab}{entry_type}{namepace_tab}{namespace_str}\t\t{page_num}\t{page_status}'
320339
)
321340
)
322341

@@ -378,8 +397,8 @@ def check_blobs(nvs_log: NVS_Logger) -> None:
378397
def check_namespaces(nvs_log: NVS_Logger) -> None:
379398
# Undefined namespace index check
380399
for used_ns in used_namespaces:
381-
key = found_namespaces.pop(used_ns, '')
382-
if key == '':
400+
key = found_namespaces.pop(used_ns, None)
401+
if key is None:
383402
nvs_log.info(
384403
nvs_log.red('Undefined namespace index!'),
385404
f'Namespace index: {used_ns:03d}',
@@ -395,14 +414,22 @@ def check_namespaces(nvs_log: NVS_Logger) -> None:
395414
)
396415

397416

417+
def reset_global_variables() -> None:
418+
global used_namespaces, found_namespaces, blobs, blob_chunks
419+
used_namespaces = {}
420+
found_namespaces = {}
421+
blobs = {}
422+
blob_chunks = []
423+
424+
398425
def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
399426
# Partition size check
400427
check_partition_size(nvs_partition, nvs_log)
401428

402429
# Free/empty page check
403430
check_empty_page_present(nvs_partition, nvs_log)
404431

405-
seen_written_entires_all: Dict[str, list[NVS_Entry]] = {}
432+
seen_written_entires_all: Dict[str, List[NVS_Entry]] = {}
406433

407434
for page in nvs_partition.pages:
408435
# page: NVS_Page
@@ -428,7 +455,7 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
428455
# Duplicate entry check (2) - same key, different index
429456
duplicates = filter_entry_duplicates(seen_written_entires_all)
430457
# Print duplicate entries
431-
print_entry_duplicates(page, duplicates, nvs_log)
458+
print_entry_duplicates(duplicates, nvs_log)
432459

433460
nvs_log.info() # Empty line
434461

@@ -437,3 +464,5 @@ def integrity_check(nvs_partition: NVS_Partition, nvs_log: NVS_Logger) -> None:
437464

438465
# Namespace checks
439466
check_namespaces(nvs_log)
467+
468+
reset_global_variables()

components/nvs_flash/nvs_partition_tool/nvs_parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ def key_decode(data: bytearray) -> Optional[str]:
219219
self.state = entry_state
220220
self.is_empty = self.raw == bytearray({0xFF}) * nvs_const.entry_size
221221
self.index = index
222+
self.page = None
222223

223224
namespace = self.raw[0]
224225
entry_type = self.raw[1]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[pytest]
2+
addopts = -s -p no:pytest_embedded
3+
4+
# log related
5+
log_cli = True
6+
log_cli_level = INFO
7+
log_cli_format = %(asctime)s %(levelname)s %(message)s
8+
log_cli_date_format = %Y-%m-%d %H:%M:%S
9+
10+
## log all to `system-out` when case fail
11+
junit_logging = stdout
12+
junit_log_passing_tests = False

0 commit comments

Comments
 (0)