v/vlib/x/encoding/asn1/core_test.v

163 lines
6.3 KiB
V

// Copyright (c) 2022, 2024 blackshirt. All rights reserved.
// Use of this source code is governed by a MIT License
// that can be found in the LICENSE file.
module asn1
struct TagCreation {
class TagClass
constructed bool
number int
err IError
}
fn test_tag_new_constructor() {
tags := [
TagCreation{.universal, false, 1, none},
TagCreation{.universal, true, 1, none},
// sequence should be constructed set
TagCreation{.universal, true, 16, none},
TagCreation{.universal, false, 16, error('For SEQUENCE(OF) or SET(OF) type, should be in constructed form')},
// set
TagCreation{.universal, true, 17, none},
TagCreation{.universal, false, 17, error('For SEQUENCE(OF) or SET(OF) type, should be in constructed form')},
//
TagCreation{.universal, false, 28, none},
TagCreation{.universal, false, 0x1f, none}, // 31
TagCreation{.universal, false, 0x7f, none},
TagCreation{.universal, false, 255, none}, // 0xff
TagCreation{.universal, true, 255, none}, // 0xff
TagCreation{.universal, true, 16380, error('Not a valid tag number for universal class=16380')},
// Context Specific should be in constructed form
TagCreation{.context_specific, true, 128, none}, // 0x80
TagCreation{.context_specific, false, 128, error('Context Specific should be in constructed form')}, // 0x80
// Others was as is
TagCreation{.private, false, 256, none},
TagCreation{.private, true, 16383, none},
TagCreation{.private, true, 16500, error('Unallowed tag number, 16500 exceed limit')},
TagCreation{.application, false, 16000, none},
TagCreation{.application, false, 16384, error('Unallowed tag number, 16384 exceed limit')},
TagCreation{.application, true, 65535, error('Unallowed tag number, 65535 exceed limit')},
]
for i, c in tags {
// creates tag with constructed bit set
t := Tag.new(c.class, c.constructed, c.number) or {
assert err == c.err
continue
}
assert t.tag_class() == c.class
assert t.is_constructed() == c.constructed
assert t.tag_number() == c.number
}
}
struct TagLengthTest {
class TagClass
number int
explength int
err IError
}
fn test_class_tag_length_handling() ! {
tags := [
TagLengthTest{.universal, 0, 1, none},
TagLengthTest{.universal, 1, 1, none},
TagLengthTest{.universal, 28, 1, none},
TagLengthTest{.universal, 0x1f, 2, none}, // 31
TagLengthTest{.universal, 0x7f, 2, none},
TagLengthTest{.context_specific, 128, 3, none}, // 0x80
TagLengthTest{.universal, 255, 3, none}, // 0xff
TagLengthTest{.private, 256, 3, error('Not a valid tag number for universal class=256')},
TagLengthTest{.universal, 16380, 3, error('Not a valid tag number for universal class=16380')},
TagLengthTest{.private, 16383, 3, none},
TagLengthTest{.application, 16384, 4, error('Unallowed tag number, 16384 exceed limit')},
TagLengthTest{.application, 65535, 4, error('Unallowed tag number, 65535 exceed limit')},
]
for i, c in tags {
// creates tag with constructed bit set
t := Tag.new(c.class, true, c.number) or {
assert err == c.err
continue
}
n := t.tag_size()
assert n == c.explength
}
}
struct TagDecodeTest {
bytes []u8
class TagClass
constructed bool
number int
lastpos int
err IError
}
fn test_tag_decode() ! {
data := [
// 0b1000_000 telss its class is .context_specific, but constructed bit was not set
TagDecodeTest{[u8(0x80), 0x01], .context_specific, false, 0, 1, none},
TagDecodeTest{[u8(0xa0), 0x01], .context_specific, true, 0, 1, none}, //{2, 0, 1, true}},
TagDecodeTest{[u8(0x02), 0x00], .universal, false, 2, 1, none},
TagDecodeTest{[u8(0xfe), 0x00], .private, true, 30, 1, none},
TagDecodeTest{[u8(0x1f), 0x1f, 0x00], .universal, false, 31, 2, none}, // high tag form
TagDecodeTest{[u8(0x1f), 0x81, 0x00, 0x00], .universal, false, 128, 3, none},
TagDecodeTest{[u8(0x1f), 0x81, 0x80, 0x01, 0x00], .universal, false, 16385, 4, error('Tag number: base 128 integer too large')}, // 1x128^2 + 0x128^1 + 1x128*0
TagDecodeTest{[u8(0x00), 0x81, 0x80], .universal, false, 0, 1, none},
TagDecodeTest{[u8(0x00), 0x83, 0x01, 0x00], .universal, false, 0, 1, none},
TagDecodeTest{[u8(0x1f), 0x85], .universal, false, 0, 1, error('Tag: truncated base 128 integer')},
TagDecodeTest{[u8(0x1f), 0x85, 0x81], .universal, false, 0, 0, error('Tag: truncated base 128 integer')},
TagDecodeTest{[u8(0x30), 0x80], .universal, true, 0x10, 1, none},
TagDecodeTest{[u8(0xa0), 0x82, 0x00, 0xff], .context_specific, true, 0, 1, none},
]
for i, c in data {
// dump(i)
tag, pos := Tag.decode(c.bytes) or {
assert err == c.err
continue
}
assert tag.class == c.class
assert tag.constructed == c.constructed
assert tag.number == c.number
assert pos == c.lastpos
}
}
struct TagNumberTest {
num int
class TagClass
constructed bool
exp []u8
err IError
}
fn test_serialize_tag() ! {
data := [
TagNumberTest{0, .universal, false, [u8(0x00)], none},
TagNumberTest{32, .universal, false, [u8(0x1f), 0x20], none}, // multibyte tag: 0x1f 0x20
TagNumberTest{255, .universal, false, [u8(0x1f), 0x81, 0x7f], none}, // multibyte tag: 0x1f 0x81 0x7f
TagNumberTest{0, .universal, true, [u8(0x20)], none}, // bits 6 set, 0010 0000 == 32
TagNumberTest{1, .universal, true, [u8(0x21)], none}, // bits 6 set, 0010 0001 == 31
TagNumberTest{32, .universal, true, [u8(0x3f), 0x20], none}, // multibyte tag: 00111111 0x20
TagNumberTest{32, .application, true, [u8(0x7f), 0x20], none}, // multibyte tag: 127 (01111111) 0x20
TagNumberTest{32, .context_specific, true, [u8(0xbf), 0x20], none}, // multibyte tag: 197 (10111111) 0x20
TagNumberTest{32, .private, true, [u8(0xff), 0x20], none}, // multibyte tag: 255 (11111111) 0x20
TagNumberTest{255, .context_specific, true, [u8(0xbf), 0x81, 0x7f], none}, // multibyte tag: 0xbf 0x81 0x7f
// private class 0xdf = 0b1101_1111
TagNumberTest{16383, .private, false, [u8(0xdf), 0xff, 0x7f], none}, // multibyte tag: 0x1f 0xff 0x7f
// overflow max_tag_value
TagNumberTest{16385, .context_specific, true, [u8(0x1f), 0xff, 0x7f], error('Unallowed tag number, 16385 exceed limit')}, // multibyte tag: 0x1f 0xff 0x7f
]
for i, c in data {
mut dst := []u8{}
tag := Tag.new(c.class, c.constructed, c.num) or {
assert err == c.err
continue
}
tag.encode(mut dst)!
assert dst == c.exp
}
}