Skip to content

Commit

Permalink
can setRegion/getStatus multiple times without potential leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Zilong-Li committed Sep 26, 2024
1 parent 45b51be commit 2efd1c7
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 58 deletions.
8 changes: 8 additions & 0 deletions news.org
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
#+title: News and Changes
* v0.6.0
- add =BcfReader::getStatus=
- fix =BcfReader::getVariantsCount=
- improve memory safety

* v0.5.2
- throw errors if a query region doesn't exist

* v0.5.1
- add =BcfHeader::updateSamples=

Expand Down
70 changes: 56 additions & 14 deletions test/bcf-reader.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "../vcfpp.h"
#include "catch.hh"
#include <exception>

using namespace vcfpp;
using namespace std;
Expand Down Expand Up @@ -68,7 +69,7 @@ TEST_CASE("parse PL in vcf - vector<int>", "[bcf-reader]")
{
string vcffile{"test-GL.vcf.gz"};
BcfWriter bw(vcffile, "VCF4.2");
bw.header.addContig("chr20");
bw.header.addContig("chr20");
bw.header.addINFO("AF", "A", "Float", "Estimated allele frequency in the range (0,1)");
bw.header.addFORMAT("GT", "1", "String", "Genotype");
bw.header.addFORMAT("PL", "G", "Integer", "List of Phred-scaled genotype likelihoods");
Expand All @@ -78,35 +79,36 @@ TEST_CASE("parse PL in vcf - vector<int>", "[bcf-reader]")
BcfReader br(vcffile);
BcfRecord var(br.header);
vector<int> pl;
REQUIRE(br.getNextVariant(var)==true);
var.getFORMAT("PL",pl);
REQUIRE(br.getNextVariant(var) == true);
var.getFORMAT("PL", pl);
for(auto g : pl) cout << g << endl;
}

TEST_CASE("parse GL in vcf - vector<float>", "[bcf-reader]")
{
string vcffile{"test-GL.vcf.gz"};
BcfWriter bw(vcffile, "VCF4.2");
bw.header.addContig("chr20");
bw.header.addContig("chr20");
bw.header.addINFO("AF", "A", "Float", "Estimated allele frequency in the range (0,1)");
bw.header.addFORMAT("GT", "1", "String", "Genotype");
bw.header.addFORMAT("GL", "G", "Float", "List of log scale genotype likelihoods");
for(auto & s : {"id01", "id02"}) bw.header.addSample(s); // add 3 samples
bw.writeLine("chr20\t2006060\trs146931526\tG\tA\t100\tPASS\tAF=0.02\tGT:GL\t0/1:-323.03,-99.29,-802.53\t1/1:-133.03,-299.29,-902.53");
bw.writeLine("chr20\t2006060\trs146931526\tG\tA\t100\tPASS\tAF=0.02\tGT:GL\t0/"
"1:-323.03,-99.29,-802.53\t1/1:-133.03,-299.29,-902.53");
bw.close();
BcfReader br(vcffile);
BcfRecord var(br.header);
vector<float> gl;
REQUIRE(br.getNextVariant(var)==true);
var.getFORMAT("GL",gl);
REQUIRE(br.getNextVariant(var) == true);
var.getFORMAT("GL", gl);
for(auto g : gl) cout << g << endl;
}

TEST_CASE("parse vcf with multialleles - vector<int>", "[bcf-reader]")
{
string vcffile{"test-multialleles.vcf.gz"};
BcfWriter bw(vcffile, "VCF4.2");
bw.header.addContig("chr20");
bw.header.addContig("chr20");
bw.header.addINFO("AF", "A", "Float", "Estimated allele frequency in the range (0,1)");
bw.header.addFORMAT("GT", "1", "String", "Genotype");
for(auto & s : {"id01", "id02", "id03"}) bw.header.addSample(s); // add 3 samples
Expand All @@ -116,7 +118,7 @@ TEST_CASE("parse vcf with multialleles - vector<int>", "[bcf-reader]")
BcfReader br("test-multialleles.vcf.gz");
BcfRecord var(br.header);
vector<int> gt;
REQUIRE(br.getNextVariant(var)==true);
REQUIRE(br.getNextVariant(var) == true);
auto l2 = var.asString();
REQUIRE(l2 == l1 + "\n");
var.getGenotypes(gt);
Expand All @@ -127,7 +129,7 @@ TEST_CASE("parse EV in vcf - vector<string>", "[bcf-reader]")
{
string vcffile{"test-GL.vcf.gz"};
BcfWriter bw(vcffile, "VCF4.2");
bw.header.addContig("chr20");
bw.header.addContig("chr20");
bw.header.addINFO("AF", "A", "Float", "Estimated allele frequency in the range (0,1)");
bw.header.addFORMAT("GT", "1", "String", "Genotype");
bw.header.addFORMAT("EV", "G", "String", "Classes of evidence supporting final genotype");
Expand All @@ -137,10 +139,10 @@ TEST_CASE("parse EV in vcf - vector<string>", "[bcf-reader]")
BcfReader br(vcffile);
BcfRecord var(br.header);
vector<string> ev;
REQUIRE(br.getNextVariant(var)==true);
var.getFORMAT("EV",ev);
REQUIRE(ev[0]=="RD");
REQUIRE(ev[1]=="SR,PE");
REQUIRE(br.getNextVariant(var) == true);
var.getFORMAT("EV", ev);
REQUIRE(ev[0] == "RD");
REQUIRE(ev[1] == "SR,PE");
}

TEST_CASE("throw error when file is not valid", "[bcf-reader]")
Expand All @@ -150,3 +152,43 @@ TEST_CASE("throw error when file is not valid", "[bcf-reader]")
BcfReader bw;
CHECK_THROWS(bw.open("ff://no-access.vcf.gz"));
}

TEST_CASE("throw error if the region is not valid", "[bcf-reader]")
{
BcfReader * br = nullptr;
try
{
br = new BcfReader("test.vcf.gz", "XXXX");
delete br;
}
catch(exception & e)
{
cout << e.what();
}
}

TEST_CASE("can check the status of a region", "[bcf-reader]")
{
int status;
BcfReader br("test.vcf.gz");
status = br.getStatus("chr21:5030089-5030090");
REQUIRE(status == 0); // valid but empty
status = br.getStatus("chr21:5030089-");
REQUIRE(status == 1); // valid and not empty
status = br.getStatus("chr22:5030089");
REQUIRE(status == -2); // not valid or not found in the VCF
BcfReader br2("test-no-index.vcf.gz");
status = br2.getStatus("chr21");
REQUIRE(status == -1); // no index file found
}

TEST_CASE("can count the number of variants in a valid region", "[bcf-reader]")
{
// BcfReader br("test.vcf.gz", "chr21:5030089-5030090");
int nVariants = -1;
BcfReader br("test.vcf.gz");
nVariants = br.getVariantsCount("chr21:5030089-5030090");
REQUIRE(nVariants == 0);
nVariants = br.getVariantsCount("chr21:5030089-");
REQUIRE(nVariants == 13);
}
Binary file added test/test-no-index.vcf.gz
Binary file not shown.
Loading

0 comments on commit 2efd1c7

Please sign in to comment.