mirror of
https://github.com/vlang/v.git
synced 2025-08-03 09:47:15 -04:00
441 lines
11 KiB
V
441 lines
11 KiB
V
import strconv
|
|
|
|
struct StrInt { // test struct
|
|
str_value string
|
|
int_value int
|
|
}
|
|
|
|
// test what should be caught by atoi_common_check
|
|
fn test_common_check() {
|
|
// Parsing of these strings should fail on all types.
|
|
ko := [
|
|
'', // Empty string
|
|
'-', // Only sign
|
|
'+', // Only sign
|
|
'_', // Only Underscore
|
|
'_10', // Start with underscore
|
|
'+_10', // Start with underscore after sign.
|
|
'-_16', // Start with underscore after sign.
|
|
'123_', // End with underscore
|
|
]
|
|
|
|
for v in ko {
|
|
if r := strconv.atoi(v) {
|
|
// These conversions should fail so force assertion !
|
|
assert false, 'The string "${v}" should not succeed or be considered as valid ${r}).'
|
|
} else {
|
|
// println('Parsing fails as it should for : "${v}')
|
|
assert true
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test things accepted, and rejected in atoi_common function.
|
|
fn test_atoi_common() {
|
|
// Parsing of theses value should succeed on all types.
|
|
ok := [
|
|
StrInt{'1', 1},
|
|
StrInt{'-1', -1},
|
|
StrInt{'0', 0},
|
|
StrInt{'+0', 0},
|
|
StrInt{'-0', 0},
|
|
StrInt{'-0_00', 0},
|
|
StrInt{'+0_00', 0},
|
|
StrInt{'+1', 1},
|
|
StrInt{'+123', 123},
|
|
StrInt{'-1_2_1', -121},
|
|
StrInt{'00000006', 6},
|
|
StrInt{'0_0_0_0_0_0_0_6', 6},
|
|
]
|
|
|
|
// Check that extracted int value matches its string.
|
|
for v in ok {
|
|
// println('Parsing ${v.str_value} should equals ${v.int_value}')
|
|
assert strconv.atoi(v.str_value)! == v.int_value
|
|
}
|
|
|
|
ko := [// Parsing of these strings should fail on all types.
|
|
'-3__1', // Two consecutives underscore.
|
|
'-3_1A', // Non radix 10 char.
|
|
'A42', // Non radix 10 char.
|
|
]
|
|
|
|
for v in ko {
|
|
if r := strconv.atoi(v) {
|
|
// These conversions should fail so force assertion !
|
|
assert false, 'The string ${v} int extraction should not succeed or be considered as valid ${r}).'
|
|
} else {
|
|
// println('Parsing fails as it should for : "${v}')
|
|
assert true
|
|
}
|
|
}
|
|
}
|
|
|
|
// performs numeric (bounds) tests over int type.
|
|
fn test_atoi() {
|
|
ok := [
|
|
StrInt{'1', 1},
|
|
StrInt{'-1', -1},
|
|
StrInt{'0', 0},
|
|
StrInt{'+3_14159', 314159},
|
|
StrInt{'-1_00_1', -1001},
|
|
StrInt{'-1_024', -1024},
|
|
StrInt{'123_456_789', 123456789},
|
|
StrInt{'00000006', 6},
|
|
StrInt{'0_0_0_0_0_0_0_6', 6},
|
|
StrInt{'2147483647', max_int},
|
|
StrInt{'-2147483648', min_int},
|
|
]
|
|
|
|
// Check that extracted int value matches its string.
|
|
for v in ok {
|
|
// println('Parsing ${v.str_value} should equals ${v.int_value}')
|
|
assert strconv.atoi(v.str_value)! == v.int_value
|
|
}
|
|
|
|
// Parsing of these values should fail !
|
|
ko := [
|
|
'-2147483649', // 32bits underflow by 1.
|
|
'+2147483648', // 32 bit overflow by 1.
|
|
'+3147483648', // 32 bit overflow by a lot.
|
|
'-2147244836470', // Large underflow.
|
|
'+86842255899621148766244',
|
|
]
|
|
|
|
for v in ko {
|
|
if r := strconv.atoi(v) {
|
|
// These conversions should fail so force assertion !
|
|
assert false, 'The string ${v} int extraction should not succeed or be considered as valid ${r}).'
|
|
} else {
|
|
// println('Parsing fails as it should for : "${v}')
|
|
assert true
|
|
}
|
|
}
|
|
}
|
|
|
|
// performs numeric (bounds) tests over i8 type.
|
|
fn test_atoi8() {
|
|
struct StrI8 { // Inner test struct
|
|
str_value string
|
|
int_value i8
|
|
}
|
|
|
|
ok := [
|
|
StrI8{'0', 0}, // All kind of zeroes
|
|
StrI8{'+0', 0},
|
|
StrI8{'-0', 0},
|
|
StrI8{'-0_00', 0},
|
|
StrI8{'+0_00', 0},
|
|
StrI8{'1', 1},
|
|
StrI8{'+1', 1},
|
|
StrI8{'-1', -1},
|
|
StrI8{'+123', 123},
|
|
StrI8{'-1_2_1', -121},
|
|
StrI8{'0_0_0_0_0_0_0_6', 6},
|
|
StrI8{'127', max_i8},
|
|
StrI8{'-128', min_i8},
|
|
]
|
|
|
|
// Check that extracted int value matches its string.
|
|
for v in ok {
|
|
// println('Parsing ${v.str_value} should equals ${v.int_value}')
|
|
assert strconv.atoi8(v.str_value)! == v.int_value
|
|
}
|
|
|
|
// Parsing of these values should fail !
|
|
ko := [
|
|
'-129', // i8 bits underflow by 1.
|
|
'+128', // i8 bit overflow by 1.
|
|
'+256', // i8 overflow with value equal to max u8.
|
|
'+3147483648', // i8 bit overflow by a lot.
|
|
'-4836470', // Large i8 underflow.
|
|
]
|
|
|
|
for v in ko {
|
|
if r := strconv.atoi8(v) {
|
|
// These conversions should fail so force assertion !
|
|
assert false, 'The string ${v} int extraction should not succeed or be considered as valid ${r}).'
|
|
} else {
|
|
// println('Parsing fails as it should for : "${v}')
|
|
assert true
|
|
}
|
|
}
|
|
}
|
|
|
|
// performs numeric (bounds) tests over i16 type.
|
|
fn test_atoi16() {
|
|
struct StrI16 { // Inner test struct
|
|
str_value string
|
|
int_value i16
|
|
}
|
|
|
|
ok := [
|
|
StrI16{'0', 0}, // All kind of zeroes
|
|
StrI16{'+0', 0},
|
|
StrI16{'-0', 0},
|
|
StrI16{'-0_00', 0},
|
|
StrI16{'+0_00', 0},
|
|
StrI16{'1', 1},
|
|
StrI16{'+1', 1},
|
|
StrI16{'-1', -1},
|
|
StrI16{'+123', 123},
|
|
StrI16{'-1_2_1', -121},
|
|
StrI16{'0_0_0_0_0_0_0_6', 6},
|
|
StrI16{'32767', max_i16},
|
|
StrI16{'-32768', min_i16},
|
|
]
|
|
|
|
// Check that extracted int value matches its string.
|
|
for v in ok {
|
|
// println('Parsing ${v.str_value} should equals ${v.int_value}')
|
|
assert strconv.atoi16(v.str_value)! == v.int_value
|
|
}
|
|
|
|
// Parsing of these values should fail !
|
|
ko := [
|
|
'-32769', // i16 bits underflow by 1.
|
|
'+32768', // i16 bit overflow by 1.
|
|
'+45_000', // i16 bit overflow by a lot.
|
|
'65536', // i16 overflow with value equal to u16 max.
|
|
'-483_647_909', // Large i16 underflow.
|
|
]
|
|
|
|
for v in ko {
|
|
if r := strconv.atoi16(v) {
|
|
// These conversions should fail so force assertion !
|
|
assert false, 'The string ${v} int extraction should not succeed or be considered as valid ${r}).'
|
|
} else {
|
|
// println('Parsing fails as it should for : "${v}')
|
|
assert true
|
|
}
|
|
}
|
|
}
|
|
|
|
// performs numeric (bounds) tests over i32 type. This test is redundant with atoi
|
|
// which performs same on int (actually 32bits). In the future, int COULD be mapped
|
|
// on arch with (e.g 64bits). That's why this test exists.
|
|
fn test_atoi32() {
|
|
struct StrI32 { // Inner test struct
|
|
str_value string
|
|
int_value i32
|
|
}
|
|
|
|
ok := [
|
|
StrI32{'0', 0}, // All kind of zeroes
|
|
StrI32{'+0', 0},
|
|
StrI32{'-0', 0},
|
|
StrI32{'-0_00', 0},
|
|
StrI32{'+0_00', 0},
|
|
StrI32{'1', 1},
|
|
StrI32{'+1', 1},
|
|
StrI32{'-1', -1},
|
|
StrI32{'+123', 123},
|
|
StrI32{'-1_2_1', -121},
|
|
StrI32{'0_0_0_0_0_0_0_6', 6},
|
|
StrI32{'2147483647', max_i32},
|
|
StrI32{'-2147483648', min_i32},
|
|
]
|
|
|
|
// Check that extracted int value matches its string.
|
|
for v in ok {
|
|
// println('Parsing ${v.str_value} should equals ${v.int_value}')
|
|
assert strconv.atoi32(v.str_value)! == v.int_value
|
|
}
|
|
|
|
// Parsing of these values should fail !
|
|
ko := [
|
|
'-2147483649', // i32 bits underflow by 1.
|
|
'+2147483648', // i32 bit overflow by 1.
|
|
'+4294967295', // Large Overflow but equal to u32 max.
|
|
'-483_647_909_912_754', // Large i32 underflow.
|
|
]
|
|
|
|
for v in ko {
|
|
if r := strconv.atoi32(v) {
|
|
// These conversions should fail so force assertion !
|
|
assert false, 'The string ${v} int extraction should not succeed or be considered as valid ${r}).'
|
|
} else {
|
|
// println('Parsing fails as it should for : "${v}')
|
|
assert true
|
|
}
|
|
}
|
|
}
|
|
|
|
fn test_atoi64() {
|
|
struct StrI64 { // Inner test struct
|
|
str_value string
|
|
int_value i64
|
|
}
|
|
|
|
ok := [
|
|
StrI64{'0', 0}, // All kind of zeroes
|
|
StrI64{'+0', 0},
|
|
StrI64{'-0', 0},
|
|
StrI64{'-0_00', 0},
|
|
StrI64{'+0_00', 0},
|
|
StrI64{'1', 1},
|
|
StrI64{'+1', 1},
|
|
StrI64{'-1', -1},
|
|
StrI64{'+123', 123},
|
|
StrI64{'-1_2_1', -121},
|
|
StrI64{'0_0_0_0_0_0_0_6', 6},
|
|
StrI64{'9223372036854775807', max_i64},
|
|
StrI64{'-9223372036854775808', min_i64},
|
|
]
|
|
|
|
// Check that extracted int value matches its string.
|
|
for v in ok {
|
|
// println('Parsing ${v.str_value} should equals ${v.int_value}')
|
|
assert strconv.atoi64(v.str_value)! == v.int_value
|
|
}
|
|
|
|
// Parsing of these values should fail !
|
|
ko := [
|
|
'-9223372036854775809', // i64 bits underflow by 1.
|
|
'+9223372036854775808', // i64 bit overflow by 1.
|
|
'+18446744073709551615', // Large Overflow but equal to u64 max.
|
|
'-483647909912754123456789', // Large i64 underflow.
|
|
]
|
|
|
|
for v in ko {
|
|
if r := strconv.atoi64(v) {
|
|
// These conversions should fail so force assertion !
|
|
assert false, 'The string ${v} int extraction should not succeed or be considered as valid ${r}).'
|
|
} else {
|
|
// println('Parsing fails as it should for : "${v}')
|
|
assert true
|
|
}
|
|
}
|
|
}
|
|
|
|
fn test_parse_int() {
|
|
// symbols coverage
|
|
assert strconv.parse_int('1234567890', 10, 32)! == 1234567890
|
|
assert strconv.parse_int('19aAbBcCdDeEfF', 16, 64)! == 0x19aAbBcCdDeEfF
|
|
// Different bases
|
|
assert strconv.parse_int('16', 16, 0)! == 0x16
|
|
assert strconv.parse_int('16', 8, 0)! == 0o16
|
|
assert strconv.parse_int('11', 2, 0)! == 3
|
|
// Different bit sizes
|
|
assert strconv.parse_int('127', 10, 8)! == 127
|
|
assert strconv.parse_int('128', 10, 8)! == 127
|
|
assert strconv.parse_int('32767', 10, 16)! == 32767
|
|
assert strconv.parse_int('32768', 10, 16)! == 32767
|
|
assert strconv.parse_int('2147483647', 10, 32)! == 2147483647
|
|
assert strconv.parse_int('2147483648', 10, 32)! == 2147483647
|
|
assert strconv.parse_int('9223372036854775807', 10, 64)! == 9223372036854775807
|
|
assert strconv.parse_int('9223372036854775808', 10, 64)! == 9223372036854775807
|
|
assert strconv.parse_int('baobab', 36, 64)? == 683058467
|
|
// Invalid bit sizes
|
|
if x := strconv.parse_int('123', 10, -1) {
|
|
println(x)
|
|
assert false
|
|
} else {
|
|
assert true
|
|
}
|
|
if x := strconv.parse_int('123', 10, 65) {
|
|
println(x)
|
|
assert false
|
|
} else {
|
|
assert true
|
|
}
|
|
}
|
|
|
|
fn test_common_parse_uint2() {
|
|
mut result, mut error := strconv.common_parse_uint2('1', 10, 8)
|
|
assert result == 1
|
|
assert error == 0
|
|
result, error = strconv.common_parse_uint2('123', 10, 8)
|
|
assert result == 123
|
|
assert error == 0
|
|
result, error = strconv.common_parse_uint2('123', 10, 65)
|
|
assert result == 0
|
|
assert error == -2
|
|
result, error = strconv.common_parse_uint2('123', 10, -1)
|
|
assert result == 0
|
|
assert error == -2
|
|
result, error = strconv.common_parse_uint2('', 10, 8)
|
|
assert result == 0
|
|
assert error == 1
|
|
result, error = strconv.common_parse_uint2('1a', 10, 8)
|
|
assert result == 1
|
|
assert error == 2
|
|
result, error = strconv.common_parse_uint2('12a', 10, 8)
|
|
assert result == 12
|
|
assert error == 3
|
|
result, error = strconv.common_parse_uint2('123a', 10, 8)
|
|
assert result == 123
|
|
assert error == 4
|
|
}
|
|
|
|
fn test_common_parse_uint2_fail() {
|
|
mut ascii_characters := [' ', '!', '"', '#', '\$', '%', '&', "'", '(', ')', '*', '+', ',',
|
|
'-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|',
|
|
'}', '~']
|
|
mut special_characters := [':', ';', '<', '=', '>', '?', '@', 'X', 'Y', 'Z', '[', '\\', ']',
|
|
'^', '_', '`']
|
|
|
|
num0, err0 := strconv.common_parse_uint2('1Ab', 16, 32)
|
|
assert num0 == 427
|
|
assert err0 == 0
|
|
|
|
for ch in ascii_characters {
|
|
// println("ch: [${ch}]")
|
|
txt_str := '${ch[0]:c}12Ab'
|
|
num, err := strconv.common_parse_uint2(txt_str, 16, 32)
|
|
assert err != 0
|
|
}
|
|
|
|
for ch in special_characters {
|
|
// println("ch: [${ch}]")
|
|
txt_str := '${ch[0]:c}12Ab'
|
|
num, err := strconv.common_parse_uint2(txt_str, 16, 32)
|
|
assert err != 0
|
|
}
|
|
}
|
|
|
|
fn test_common_parse_uint2_compatibility() {
|
|
test_list := [
|
|
'1234,1234',
|
|
'1_234,1234',
|
|
'1_2_34,1234',
|
|
'_12__34,1',
|
|
'12__34,1',
|
|
'_1234,1',
|
|
'1234_,1',
|
|
'0x1234,4660',
|
|
'0x_1234,4660',
|
|
'0x1_234,4660',
|
|
'0x1_2_3_4,4660',
|
|
'0_x1234,1',
|
|
'0x1234_,1',
|
|
'0o1234,668',
|
|
'0o_1234,668',
|
|
'0o1_234,668',
|
|
'0o1_2_3_4,668',
|
|
'0_o1234,1',
|
|
'0o1234_,1',
|
|
'0b111,7',
|
|
'0b_111,7',
|
|
'0b1_11,7',
|
|
'0b1_1_1,7',
|
|
'0_b111,1',
|
|
'0b111_,1',
|
|
'0xa,10',
|
|
'0xA,10',
|
|
'0xf,15',
|
|
'0xf,15',
|
|
'0_xf,1',
|
|
'0x_0_0_f_,1',
|
|
'0x_0_0__f,1',
|
|
'0x_0_0_f,15',
|
|
]
|
|
|
|
for tst in test_list {
|
|
query := tst.split(',')
|
|
mut a0 := strconv.common_parse_uint(query[0], 0, 32, true, true) or { 1 }
|
|
// println("${a0} => ${query[1]}")
|
|
assert a0.str() == query[1]
|
|
}
|
|
}
|