Skip to content

Improve test coverage#29

Closed
swetank18 wants to merge 10 commits intocompiler-research:developfrom
swetank18:improve-test-coverage
Closed

Improve test coverage#29
swetank18 wants to merge 10 commits intocompiler-research:developfrom
swetank18:improve-test-coverage

Conversation

@swetank18
Copy link
Copy Markdown

Closes #26

Summary

This PR improves test coverage for the ramcore library by adding a comprehensive test suite for the RAMStats functionality and SamParser integration.

Changes

New files:

  • inc/ramcore/RAMStats.hRAMStats struct, RAMStatsResult wrapper, and ComputeStats() declaration
  • src/ramcore/RAMStats.cxx — implementation using RNTupleReader field views with safe error handling
  • tools/ramstats.cxx — command-line tool equivalent to samtools flagstat
  • test/ramstatstests.cxx — 9 Google Test cases covering RAMStats

Modified files:

  • CMakeLists.txt — added RAMStats.h and RAMStats.cxx to the ramcore library
  • tools/CMakeLists.txt — added ramstats executable
  • test/CMakeLists.txt — added ramstatstests and samparsertest test targets

Tests Added

9 test cases in test/ramstatstests.cxx — all passing:

  • TotalReadsMatchesNTupleEntries — cross-validates against RNTupleReader::GetNEntries()
  • MappedPlusUnmappedEqualsTotal — ensures no reads are lost
  • StrandCountsEqualTotal — forward + reverse = total
  • MeanReadLengthIsPositive — sanity check on non-empty file
  • TotalBasesConsistentWithMeanLength — floating-point consistency
  • MeanMappingQualityInValidRange — SAM spec [0, 255]
  • ReadsPerChromosomeNotEmpty — chromosome map populated
  • ChromosomeCountsSumToAtMostTotal — unmapped reads excluded correctly
  • NonExistentFileReturnsEmpty — graceful failure on bad input

Test Results

100% tests passed, 0 tests failed out of 3
Total Test time (real) = 2.77 sec

Codecov

Patch coverage: 88.57% — above the 85% threshold required by .codecov.yml.

Implementation Notes

  • Uses RNTupleReader field views (record.flag, record.mapq, record.seq, record.refid) for efficient columnar access
  • Reference names resolved via RAMNTupleRecord::ReadAllRefs() and RAMNTupleRefs
  • RNTupleReader::Open wrapped in try/catch for safe error handling
  • No external dependencies beyond ROOT and the existing ramcore library

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 10, 2026

Codecov Report

❌ Patch coverage is 86.10272% with 46 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (develop@4504216). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/ramcore/RAMStats.cxx 82.55% 3 Missing and 12 partials ⚠️
tools/ramsort.cxx 0.00% 11 Missing ⚠️
tools/ramstats.cxx 0.00% 11 Missing ⚠️
src/ramcore/RAMSort.cxx 88.67% 4 Missing and 2 partials ⚠️
test/ramsorttests.cxx 93.18% 0 Missing and 3 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             develop      #29   +/-   ##
==========================================
  Coverage           ?   65.58%           
==========================================
  Files              ?       23           
  Lines              ?     1784           
  Branches           ?      740           
==========================================
  Hits               ?     1170           
  Misses             ?      522           
  Partials           ?       92           
Flag Coverage Δ
unittests 65.58% <86.10%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
test/ramstatstests.cxx 100.00% <100.00%> (ø)
test/samparsertest.cxx 100.00% <100.00%> (ø)
test/ramsorttests.cxx 93.18% <93.18%> (ø)
src/ramcore/RAMSort.cxx 88.67% <88.67%> (ø)
tools/ramsort.cxx 0.00% <0.00%> (ø)
tools/ramstats.cxx 0.00% <0.00%> (ø)
src/ramcore/RAMStats.cxx 82.55% <82.55%> (ø)
Files with missing lines Coverage Δ
test/ramstatstests.cxx 100.00% <100.00%> (ø)
test/samparsertest.cxx 100.00% <100.00%> (ø)
test/ramsorttests.cxx 93.18% <93.18%> (ø)
src/ramcore/RAMSort.cxx 88.67% <88.67%> (ø)
tools/ramsort.cxx 0.00% <0.00%> (ø)
tools/ramstats.cxx 0.00% <0.00%> (ø)
src/ramcore/RAMStats.cxx 82.55% <82.55%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 10 out of 50. Check the log or trigger a new build to see more.

Comment thread inc/ramcore/RAMStats.h
@@ -0,0 +1,42 @@
#ifndef RAMCORE_RAMSTATS_H
#define RAMCORE_RAMSTATS_H
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: header guard does not follow preferred style [llvm-header-guard]

Suggested change
#define RAMCORE_RAMSTATS_H
#ifndef GITHUB_WORKSPACE_INC_RAMCORE_RAMSTATS_H
#define GITHUB_WORKSPACE_INC_RAMCORE_RAMSTATS_H

inc/ramcore/RAMStats.h:41:

+ endif // GITHUB_WORKSPACE_INC_RAMCORE_RAMSTATS_H

Comment thread inc/ramcore/RAMStats.h
#ifndef RAMCORE_RAMSTATS_H
#define RAMCORE_RAMSTATS_H

#include <cstdint>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'cstdint' file not found [clang-diagnostic-error]

#include <cstdint>
         ^

Comment thread inc/ramcore/RAMStats.h

#include <cstdint>
#include <string>
#include <map>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: #includes are not sorted properly [llvm-include-order]

Suggested change
#include <map>
#include <map>
#include <string>

Comment thread inc/ramcore/RAMStats.h
#include <string>
#include <map>

namespace ramcore {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'ramcore' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

namespace ramcore {
          ^

Comment thread src/ramcore/RAMStats.cxx
@@ -0,0 +1,145 @@
#include "ramcore/RAMStats.h"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'ramcore/RAMStats.h' file not found [clang-diagnostic-error]

#include "ramcore/RAMStats.h"
         ^

Comment thread src/ramcore/RAMStats.cxx
#include <cstring>
#include <exception>
#include <iomanip>
#include <iostream>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header iomanip is not used directly [misc-include-cleaner]

Suggested change
#include <iostream>
#include <iostream>

Comment thread src/ramcore/RAMStats.cxx
#include <exception>
#include <iomanip>
#include <iostream>
#include <map>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header iostream is not used directly [misc-include-cleaner]

Suggested change
#include <map>
#include <map>

Comment thread src/ramcore/RAMStats.cxx
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header map is not used directly [misc-include-cleaner]

Suggested change
#include <memory>
#include <memory>

Comment thread src/ramcore/RAMStats.cxx
#include <iostream>
#include <map>
#include <memory>
#include <string>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header memory is not used directly [misc-include-cleaner]

Suggested change
#include <string>
#include <string>

Comment thread src/ramcore/RAMStats.cxx
return length;
}

RAMStatsResult ComputeStats(const char *filename)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'ComputeStats' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage]

Suggested change
RAMStatsResult ComputeStats(const char *filename)
RAMStatsResult ComputeStatsstatic (const char *filename)

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 10 out of 67. Check the log or trigger a new build to see more.

Comment thread inc/ramcore/RAMSort.h
@@ -0,0 +1,11 @@
#ifndef RAMCORE_RAMSORT_H
#define RAMCORE_RAMSORT_H
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: header guard does not follow preferred style [llvm-header-guard]

Suggested change
#define RAMCORE_RAMSORT_H
#ifndef GITHUB_WORKSPACE_INC_RAMCORE_RAMSORT_H
#define GITHUB_WORKSPACE_INC_RAMCORE_RAMSORT_H

inc/ramcore/RAMSort.h:10:

- #endif // RAMCORE_RAMSORT_H
+ #endif // GITHUB_WORKSPACE_INC_RAMCORE_RAMSORT_H

Comment thread inc/ramcore/RAMSort.h
/// \param outputFile Path to output .root RAM file
/// \param byName If true, sort by QNAME; otherwise sort by (refid, pos)
/// \return 0 on success, 1 on error
int ramsortntuple(const char *inputFile, const char *outputFile, bool byName = false);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: unknown type name 'bool' [clang-diagnostic-error]

int ramsortntuple(const char *inputFile, const char *outputFile, bool byName = false);
                                                                 ^

Comment thread inc/ramcore/RAMSort.h
/// \param outputFile Path to output .root RAM file
/// \param byName If true, sort by QNAME; otherwise sort by (refid, pos)
/// \return 0 on success, 1 on error
int ramsortntuple(const char *inputFile, const char *outputFile, bool byName = false);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: use of undeclared identifier 'false' [clang-diagnostic-error]

int ramsortntuple(const char *inputFile, const char *outputFile, bool byName = false);
                                                                               ^

Comment thread src/ramcore/RAMSort.cxx
@@ -0,0 +1,92 @@
#include "ramcore/RAMSort.h"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: 'ramcore/RAMSort.h' file not found [clang-diagnostic-error]

#include "ramcore/RAMSort.h"
         ^

Comment thread src/ramcore/RAMSort.cxx

#include <ROOT/RNTupleModel.hxx>
#include <ROOT/RNTupleReader.hxx>
#include <ROOT/RNTupleWriter.hxx>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: #includes are not sorted properly [llvm-include-order]

Suggested change
#include <ROOT/RNTupleWriter.hxx>
#include <ROOT/RNTupleView.hxx>

src/ramcore/RAMSort.cxx:7:

- #include <ROOT/RNTupleView.hxx>
+ #include <ROOT/RNTupleWriter.hxx>

Comment thread src/ramcore/RAMSort.cxx
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header string is not used directly [misc-include-cleaner]

Suggested change
#include <vector>
#include <vector>

Comment thread src/ramcore/RAMSort.cxx
#include <numeric>
#include <string>
#include <vector>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header vector is not used directly [misc-include-cleaner]

Suggested change

Comment thread src/ramcore/RAMSort.cxx
#include <string>
#include <vector>

int ramsortntuple(const char *inputFile, const char *outputFile, bool byName)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'ramsortntuple' can be made static or moved into an anonymous namespace to enforce internal linkage [misc-use-internal-linkage]

Suggested change
int ramsortntuple(const char *inputFile, const char *outputFile, bool byName)
static int ramsortntuple(const char *inputFile, const char *outputFile, bool byName)

Comment thread src/ramcore/RAMSort.cxx
std::unique_ptr<ROOT::RNTupleReader> reader;
try {
reader = ROOT::RNTupleReader::Open("RAM", inputFile);
} catch (const std::exception &e) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::exception" is directly included [misc-include-cleaner]

src/ramcore/RAMSort.cxx:11:

- #include <iostream>
+ #include <exception>
+ #include <iostream>

Comment thread src/ramcore/RAMStats.cxx
std::unique_ptr<ROOT::RNTupleReader> reader;
try {
reader = ROOT::RNTupleReader::Open("RAM", filename);
} catch (const std::exception &e) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: empty catch statements hide issues; to handle exceptions appropriately, consider re-throwing, handling, or avoiding catch altogether [bugprone-empty-catch]

   } catch (const std::exception &e) {
     ^

@RedBlueBird
Copy link
Copy Markdown

Hi @swetank18!
I am also interested in issue #26. I am reading prior PRs to help me better understand the current progress.
However, after reading through your PR description, it seems like you are introducing new functionalities like ramstat upon the existing codebase and adding tests for those new things you added.
This doesn't really address what the issue originally was asking for, which is adding more tests to cover the existing codebase.

Let me know if my understanding is incorrect.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 10 out of 101. Check the log or trigger a new build to see more.

Comment thread inc/ramcore/RAMStats.h
@@ -0,0 +1,48 @@
#ifndef RAMCORE_RAMSTATS_H
#define RAMCORE_RAMSTATS_H
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: header guard does not follow preferred style [llvm-header-guard]

Suggested change
#define RAMCORE_RAMSTATS_H
#ifndef GITHUB_WORKSPACE_INC_RAMCORE_RAMSTATS_H
#define GITHUB_WORKSPACE_INC_RAMCORE_RAMSTATS_H

inc/ramcore/RAMStats.h:47:

+ endif // GITHUB_WORKSPACE_INC_RAMCORE_RAMSTATS_H

Comment thread src/ramcore/RAMSort.cxx

#include <ROOT/RNTupleModel.hxx>
#include <ROOT/RNTupleReader.hxx>
#include <ROOT/RNTupleWriter.hxx>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: #includes are not sorted properly [llvm-include-order]

#include <ROOT/RNTupleWriter.hxx>
^

this fix will not be applied because it overlaps with another fix

Comment thread src/ramcore/RAMSort.cxx

#include <ROOT/RNTupleModel.hxx>
#include <ROOT/RNTupleReader.hxx>
#include <ROOT/RNTupleWriter.hxx>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header RNTupleReader.hxx is not used directly [misc-include-cleaner]

Suggested change
#include <ROOT/RNTupleWriter.hxx>
#include <ROOT/RNTupleWriter.hxx>

Comment thread src/ramcore/RAMSort.cxx
#include <ROOT/RNTupleWriter.hxx>
#include <ROOT/RNTupleWriteOptions.hxx>
#include <ROOT/RNTupleView.hxx>
#include <TFile.h>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: included header RNTupleView.hxx is not used directly [misc-include-cleaner]

Suggested change
#include <TFile.h>
#include <TFile.h>

Comment thread src/ramcore/RAMSort.cxx
{
RAMNTupleRecord::ReadAllRefs(inputFile);

std::unique_ptr<ROOT::RNTupleReader> reader;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::unique_ptr" is directly included [misc-include-cleaner]

src/ramcore/RAMSort.cxx:12:

- #include <numeric>
+ #include <memory>
+ #include <numeric>

Comment thread src/ramcore/RAMSort.cxx

std::unique_ptr<ROOT::RNTupleReader> reader;
try {
reader = ROOT::RNTupleReader::Open("RAM", inputFile);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: incomplete type 'ROOT::RNTupleReader' named in nested name specifier [clang-diagnostic-error]

      reader = ROOT::RNTupleReader::Open("RAM", inputFile);
                     ^
Additional context

inc/rntuple/RAMNTupleRecord.h:23: forward declaration of 'ROOT::RNTupleReader'

class RNTupleReader;
      ^

Comment thread src/ramcore/RAMSort.cxx
return 1;
}

const uint64_t nEntries = reader->GetNEntries();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member access into incomplete type 'ROOT::RNTupleReader' [clang-diagnostic-error]

   const uint64_t nEntries = reader->GetNEntries();
                                   ^
Additional context

inc/rntuple/RAMNTupleRecord.h:23: forward declaration of 'ROOT::RNTupleReader'

class RNTupleReader;
      ^

Comment thread src/ramcore/RAMSort.cxx
return 1;
}

const uint64_t nEntries = reader->GetNEntries();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "uint64_t" is directly included [misc-include-cleaner]

src/ramcore/RAMSort.cxx:11:

- #include <iostream>
+ #include <cstdint>
+ #include <iostream>

Comment thread src/ramcore/RAMSort.cxx
return 1;
}

auto viewRefId = reader->GetView<int32_t>("record.refid");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member access into incomplete type 'ROOT::RNTupleReader' [clang-diagnostic-error]

   auto viewRefId = reader->GetView<int32_t>("record.refid");
                          ^
Additional context

inc/rntuple/RAMNTupleRecord.h:23: forward declaration of 'ROOT::RNTupleReader'

class RNTupleReader;
      ^

Comment thread src/ramcore/RAMSort.cxx
return 1;
}

auto viewRefId = reader->GetView<int32_t>("record.refid");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "int32_t" is directly included [misc-include-cleaner]

   auto viewRefId = reader->GetView<int32_t>("record.refid");
                                    ^

@swetank18
Copy link
Copy Markdown
Author

Hi @swetank18! I am also interested in issue #26. I am reading prior PRs to help me better understand the current progress. However, after reading through your PR description, it seems like you are introducing new functionalities like ramstat upon the existing codebase and adding tests for those new things you added. This doesn't really address what the issue originally was asking for, which is adding more tests to cover the existing codebase.

Let me know if my understanding is incorrect.

Hi, thank you for reading through the PR carefully!
You're partially correct. The PR does two things:

New functionality ramstats tool and ramsort tool with their tests (these are better suited to their own PRs, which I have open as #28 and #30)
Existing codebase coverage test/samparsertest.cxx directly tests the existing SamParser class (parsing headers, records, edge cases, optional fields, line counting) which had zero test coverage before this PR. Similarly, the RAMNTupleUtils encode/decode functions were untested.

You're right that the PR description was misleading by mixing both concerns together. The part that genuinely addresses issue #26 is samparsertest.cxx it adds tests for pre-existing code that had no coverage.
Would it make more sense to split this PR? I can keep only the SamParser and RAMNTupleUtils tests here (which directly address #26) and move the ramstats-related tests to PR #28 where they belong.

@RedBlueBird
Copy link
Copy Markdown

RedBlueBird commented Mar 20, 2026

@swetank18

Would it make more sense to split this PR?

I recommend splitting it; otherwise, the PR title is a bit misleading.

@swetank18
Copy link
Copy Markdown
Author

Closing in favour of focused PRs: SamParser tests → new PR, ramstats tests → #28, ramsort tests → #30. This keeps each PR focused on a single concern as suggested.

@swetank18 swetank18 closed this Mar 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve testing coverage

3 participants