@@ -88,20 +88,113 @@ echo "[STEP 4] Merging Python + C++ coverage"
8888echo " ==================================="
8989
9090# Merge LCOV reports (ignore inconsistencies in Python LCOV export)
91- # Use --omit-lines to exclude LOG macro calls from coverage
92- # The regex matches LOG, LOG_ERROR, LOG_WARNING, etc.
93- echo " [ACTION] Merging Python and C++ coverage with LOG exclusion"
94- lcov -a python-coverage.info -a cpp-coverage.info -o total.info \
95- --ignore-errors inconsistent,corrupt \
96- --omit-lines ' \bLOG[A-Z_]*\('
91+ echo " [ACTION] Merging Python and C++ coverage"
92+ lcov -a python-coverage.info -a cpp-coverage.info -o total-unfiltered.info \
93+ --ignore-errors inconsistent,corrupt
9794
98- echo " [INFO] LOG statements excluded from coverage using --omit-lines "
95+ echo " [INFO] Coverage merged successfully "
9996
10097# Normalize paths so everything starts from mssql_python/
10198echo " [ACTION] Normalizing paths in LCOV report"
102- sed -i " s|$( pwd) /||g" total.info
99+ sed -i " s|$( pwd) /||g" total-unfiltered.info
100+
101+ # Filter out LOG statements from coverage data
102+ # Since we joined multi-line LOGs during build, they're now on single lines
103+ # We can filter them using a regex pattern
104+ echo " [ACTION] Filtering LOG statements from coverage data"
105+ python3 - << 'PYTHON_FILTER '
106+ import re
107+ import os
108+
109+ with open('total-unfiltered.info', 'r') as f:
110+ content = f.read()
111+
112+ # Process file section by section
113+ sections = content.split('SF:')
114+ output_sections = []
115+
116+ if sections[0].strip():
117+ output_sections.append(sections[0]) # Keep any header
118+
119+ total_excluded = 0
120+ LOG_PATTERN = re.compile(r'\bLOG[A-Z_]*\s*\(')
121+
122+ for section in sections[1:]:
123+ if not section.strip():
124+ continue
125+
126+ lines = section.split('\n')
127+ source_file = lines[0].strip()
128+
129+ # Read source file to find lines with LOG macros
130+ excluded_lines = set()
131+ if os.path.exists(source_file):
132+ try:
133+ with open(source_file, 'r', encoding='utf-8', errors='ignore') as src:
134+ for line_num, src_line in enumerate(src, 1):
135+ if LOG_PATTERN.search(src_line):
136+ excluded_lines.add(line_num)
137+ except Exception as e:
138+ print(f"[WARNING] Could not read {source_file}: {e}")
139+
140+ # Process section lines - filter DA entries and recalculate LH/LF
141+ new_section = [f'SF:{source_file}']
142+ da_entries = []
143+ other_lines = []
144+ lines_hit = 0
145+ lines_found = 0
146+
147+ for line in lines[1:]:
148+ line = line.rstrip()
149+ if not line:
150+ continue
151+
152+ if line.startswith('DA:'):
153+ # DA:line_number,hit_count
154+ match = re.match(r'DA:(\d+),(\d+)', line)
155+ if match:
156+ line_num = int(match.group(1))
157+ hit_count = int(match.group(2))
158+
159+ if line_num not in excluded_lines:
160+ da_entries.append(line)
161+ lines_found += 1
162+ if hit_count > 0:
163+ lines_hit += 1
164+ else:
165+ total_excluded += 1
166+ elif line.startswith('LH:') or line.startswith('LF:'):
167+ # Skip old counters - we'll add new ones
168+ continue
169+ else:
170+ other_lines.append(line)
171+
172+ # Rebuild section with correct order: SF, DA entries, other, LH/LF, end_of_record
173+ new_section.extend(da_entries)
174+
175+ # Add other lines (FN, FNDA, etc.) but keep end_of_record for last
176+ for line in other_lines:
177+ if line != 'end_of_record':
178+ new_section.append(line)
179+
180+ # Add recalculated counters
181+ new_section.append(f'LH:{lines_hit}')
182+ new_section.append(f'LF:{lines_found}')
183+ new_section.append('end_of_record')
184+
185+ output_sections.append('\n'.join(new_section))
186+
187+ # Write filtered coverage with recalculated statistics
188+ with open('total.info', 'w') as f:
189+ f.write('\n'.join(output_sections))
190+
191+ print(f"[INFO] Filtered {total_excluded} LOG statement lines from coverage")
192+ PYTHON_FILTER
193+
194+ echo " [INFO] LOG statements filtered from coverage data"
103195
104196# Generate full HTML report
197+ echo " [ACTION] Generating HTML coverage report"
105198genhtml total.info \
106199 --output-directory unified-coverage \
107200 --quiet \
0 commit comments