Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test for AuxException cases #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/XAMAuxData.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public Errors, Error

# These are the numerical types supported by the BAM format.
const AUX_NUMBER_TYPES = Union{Int8, UInt8, Int16, UInt16, Int32, UInt32, Float32}
const BIT_INTEGERS = Union{UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64, Int64, UInt128, Int128}

include("auxtag.jl")

Expand Down Expand Up @@ -80,11 +81,20 @@ function as_aux_value end
as_sam_aux_value(x) = as_aux_value(x)
as_bam_aux_value(x) = as_aux_value(x)

as_aux_value(x::Real) = Float32(x)::Float32
as_aux_value(x::Float32) = x
as_aux_value(x::Float16) = Float32(x)

function as_aux_value(x::AbstractChar)::Union{Char, Error}
function as_aux_value(x::Real)
f = Float32(x)
if !isinf(x) & isinf(f)
throw(AuxException(Errors.InvalidFloat))
end
f
end

function as_aux_value(x::AbstractChar)::Char
c = Char(x)::Char
isascii(c) ? c : throw(AuxException(Errors.InvalidChar))
is_printable_char(c) ? c : throw(AuxException(Errors.InvalidChar))
end

as_aux_value(x::Hex) = x
Expand Down Expand Up @@ -180,6 +190,7 @@ const ELTYPE_DICT = Dict(
)

is_printable_char(x::UInt8) = in(x, UInt8('!'):UInt8('~'))
is_printable_char(c::Char) = '!' ≤ c ≤ '~'

"""
Errors
Expand Down
8 changes: 4 additions & 4 deletions src/auxtag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ function try_auxtag(x::Union{String, SubString{String}})
try_auxtag(cu1, cu2)
end

function try_auxtag(x::AbstractString)
(x, s) = @something iterate(x) return nothing
(y, s) = @something iterate(x, s) return nothing
isnothing(iterate(x, s)) || return nothing
function try_auxtag(str::AbstractString)
(x, s) = @something iterate(str) return nothing
(y, s) = @something iterate(str, s) return nothing
isnothing(iterate(str, s)) || return nothing
try_auxtag(Char(x)::Char, Char(y)::Char)
end

Expand Down
5 changes: 3 additions & 2 deletions src/bam.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,9 @@ function bytes_needed(x::AbstractVector{<:AUX_NUMBER_TYPES})
end

as_bam_aux_value(x::AUX_NUMBER_TYPES) = x
as_bam_aux_value(x::Signed) = Int32(x)
as_bam_aux_value(x::Unsigned) = UInt32(x)

as_bam_aux_value(x::Signed) = Int32(x)::Int32
as_bam_aux_value(x::Unsigned) = UInt32(x)::UInt32

function Base.setindex!(aux::MutableAuxiliary, val, k)
key = convert(AuxTag, k)
Expand Down
2 changes: 1 addition & 1 deletion src/delimited.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ end

function DelimitedIterator(x, d::T) where {T}
v = ImmutableMemoryView(x)
eltype(v) == T || error("MemoryView(x) must be of eltype T") # TODO
eltype(v) == T || error("MemoryView element type is different from delimiter type")
DelimitedIterator{T}(v, d)
end

Expand Down
18 changes: 16 additions & 2 deletions src/sam.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import ..AuxTag, ..AbstractAuxiliary, ..ELTYPE_DICT, ..is_printable_char, ..is_p
import ..DelimitedIterator, ..get_type_tag, ..Error, ..Errors, ..load_hex, ..validate_hex
import ..try_auxtag, ..Unsafe, ..as_sam_aux_value, ..AUX_NUMBER_TYPES, ..hexencode!
import ..iter_encodings, ..AbstractEncodedIterator, ..AuxException, ..striptype
import ..is_well_formed
import ..is_well_formed, ..BIT_INTEGERS

public Auxiliary, AuxTag, Hex, Errors, Error

Expand Down Expand Up @@ -230,7 +230,21 @@ function load_auxvalue(type_tag::UInt8, mem::ImmutableMemoryView{UInt8})
end
end

as_sam_aux_value(x::Integer) = Int32(x)::Int32
function as_sam_aux_value(x::Integer)::Int32
try
return Int32(x)::Int32
catch
throw(AuxException(Errors.InvalidInt))
end
end

function as_sam_aux_value(x::BIT_INTEGERS)::Int32
if (x < typemin(Int32)) | (x > typemax(Int32))
throw(AuxException(Errors.InvalidInt))
else
x % Int32
end
end

function setindex_nonexisting!(aux::MutableAuxiliary, val, key::AuxTag)
v = as_sam_aux_value(val)
Expand Down
87 changes: 87 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ end
@test AuxTag("ac") == AuxTag('a', 'c') == AuxTag(0x61, 0x63)
for good in ["AB", "A1", "a9", "w5"]
@test try_auxtag(good) isa AuxTag
@test try_auxtag(Test.GenericString(good)) isa AuxTag
end
for bad in ["", "A", "ABC", "A11", "5A", "AØ", "a!"]
@test try_auxtag(bad) === nothing
@test try_auxtag(Test.GenericString(bad)) === nothing
end

@test sort!(AuxTag.(["XA", "X1", "ab", "AB"])) == AuxTag.(["AB", "X1", "XA", "ab"])
Expand Down Expand Up @@ -83,6 +85,19 @@ end
@test aux["hc"] == Errors.InvalidTypeTag
end

@testset "Display" begin
aux = SAM.Auxiliary("AB:i:242\tkV:Z:abcdef gh \tJJ:A:!\tzZ:f:-1.2")
buf = IOBuffer()
show(buf, MIME"text/plain"(), aux)
str = String(take!(buf))
@test str == """
4-element XAMAuxData.SAM.Auxiliary{MemoryViews.ImmutableMemoryView{UInt8}}:
"AB" => 242
"kV" => "abcdef gh "
"JJ" => '!'
"zZ" => -1.2f0"""
end

@testset "Mutating" begin
aux = SAM.Auxiliary(UInt8[], 1)
d = Dict{AuxTag, Any}()
Expand Down Expand Up @@ -340,6 +355,19 @@ end # SAM
end
end

@testset "Display" begin
aux = BAM.Auxiliary("ABS\0\xf2kVZabcdef gh \0JJA!zZf\x9a\x99\x99\xbf")
buf = IOBuffer()
show(buf, MIME"text/plain"(), aux)
str = String(take!(buf))
@test str == """
4-element XAMAuxData.BAM.Auxiliary{MemoryViews.ImmutableMemoryView{UInt8}}:
"AB" => 0xf200
"kV" => "abcdef gh "
"JJ" => '!'
"zZ" => -1.2f0"""
end

@testset "Mutating" begin
aux = BAM.Auxiliary(UInt8[], 1)
d = Dict{AuxTag, Any}()
Expand Down Expand Up @@ -632,4 +660,63 @@ end
end
end

@testset "Exception types" begin
@test_throws(
"Not enough bytes remaining in Aux data to encode a full field",
first(values(SAM.Auxiliary("\t"))),
)

@test_throws(
"Invalid AuxTag. Tags must conform to r\"^[A-Za-z][A-Za-z0-9]\$\".",
first(values(SAM.Auxiliary("11:i:1"))),
)

@test_throws(
"Invalid SAM tag header. Expected <AuxTag>:<type tag>:, but found no colons.",
first(values(SAM.Auxiliary("ABi111"))),
)

@test_throws(
"BAM string or Hex type not terminated by null byte",
BAM.Auxiliary("ABZabc")["AB"],
)

@test_throws(
"BAM string or Hex type not terminated by null byte",
BAM.Auxiliary("ABH1234")["AB"],
)

@test_throws(
"Unknown type tag in aux value.",
BAM.Auxiliary("ABW123")["AB"],
)

@test_throws(
"Invalid array element type tag. Valid values are CcSsIif.",
BAM.Auxiliary("ABBW1234")["AB"],
)

@test_throws(
"Auxiliary Char (type 'A') must be in '!':'~'.",
SAM.Auxiliary(UInt8[], 1)["AB"] = '\n',
)

@test_throws(
"Data in SAM Auxiliary cannot be parsed as base-ten Int32.",
SAM.Auxiliary(UInt8[], 1)["AB"] = typemax(Int64)
)

@test_throws(
"Data in SAM Auxiliary cannot be parsed as Float32.",
SAM.Auxiliary(UInt8[], 1)["AB"] = 22e304,
)
@test SAM.Auxiliary(UInt8[], 1)["AB"] = Inf64 isa Any
@test SAM.Auxiliary(UInt8[], 1)["AB"] = -Inf64 isa Any

@test_throws(
"Auxiliary String (type 'Z') can only contain bytes in re\"[ !-~]\".",
SAM.Auxiliary(UInt8[], 1)["AB"] = "Rødgrød med fløde"
)
end

end # module
Loading