Skip to content

Commit 5873b06

Browse files
author
Bulat Shakirzyanov
committed
basic tests for number types
1 parent 8b23c23 commit 5873b06

File tree

5 files changed

+182
-13
lines changed

5 files changed

+182
-13
lines changed

ext/types/bigint.c

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <errno.h>
12
#include "../php_cassandra.h"
23
#include "bigint.h"
34

@@ -27,13 +28,57 @@ PHP_METHOD(CassandraBigint, __construct)
2728
return;
2829
}
2930

30-
if (!ctype_digit(value, value_len)) {
31-
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "Invalid integer value \"%s\"", value);
31+
cassandra_bigint* number = (cassandra_bigint*) zend_object_store_get_object(getThis() TSRMLS_CC);
32+
int point = 0;
33+
int base = 10;
34+
35+
// Determine the sign of the number.
36+
int negative = 0;
37+
if (value[point] == '+') {
38+
point++;
39+
} else if (value[point] == '-') {
40+
point++;
41+
negative = 1;
42+
}
43+
44+
if (value[point] == '0') {
45+
switch(value[point + 1]) {
46+
case 'b':
47+
point += 2;
48+
base = 2;
49+
break;
50+
case 'x':
51+
point += 2;
52+
base = 16;
53+
break;
54+
default:
55+
base = 8;
56+
break;
57+
}
58+
}
59+
60+
char* end;
61+
errno = 0;
62+
63+
number->value = strtoll(&(value[point]), &end, base);
64+
65+
if (negative)
66+
number->value = number->value * -1;
67+
68+
if (errno) {
69+
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "Invalid integer value: '%s'", value);
3270
return;
3371
}
3472

35-
cassandra_bigint* number = (cassandra_bigint*) zend_object_store_get_object(getThis() TSRMLS_CC);
36-
number->value = strtoll(value, NULL, 10);
73+
if (end != &value[value_len]) {
74+
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "Non digit characters were found in value: '%s'", value);
75+
return;
76+
}
77+
78+
if (end == &value[point]) {
79+
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "No digits were found in value: '%s'", value);
80+
return;
81+
}
3782
}
3883
/* }}} */
3984

ext/util/math.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ php_cassandra_parse_integer(char* in, int in_len, mpz_t* number)
2727
if (in[point] == '0') {
2828
switch(in[point + 1]) {
2929
case 'b':
30+
point += 2;
3031
base = 2;
3132
break;
3233
case 'x':
34+
point += 2;
3335
base = 16;
3436
break;
35-
case '.':
36-
break;
3737
default:
3838
base = 8;
3939
break;
@@ -55,6 +55,11 @@ php_cassandra_parse_integer(char* in, int in_len, mpz_t* number)
5555
return 0;
5656
}
5757

58+
if (end != &in[in_len]) {
59+
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "Non digit characters were found in value: '%s'", in);
60+
return 0;
61+
}
62+
5863
if (end == &in[point]) {
5964
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "No digits were found in value: \"%s\"", in);
6065
return 0;
@@ -93,7 +98,7 @@ php_cassandra_parse_decimal(char* in, int in_len, mpz_t* number, int* scale)
9398
int dot = -1;
9499
// out will be storing the string representation of the integer part
95100
// of the decimal value
96-
char* out = (char*) emalloc((in_len + 1) * sizeof(char));
101+
char* out = (char*) ecalloc((in_len + 1), sizeof(char));
97102
// holds length of the formatted integer number
98103
int out_len = 0;
99104

@@ -158,9 +163,9 @@ php_cassandra_parse_decimal(char* in, int in_len, mpz_t* number, int* scale)
158163
else if (c == 'e' || c == 'E')
159164
break;
160165
// Throw an exception if the character was not a decimal or an
161-
// exponent and is not a digit.
162-
else if (!isdigit(c)) {
163-
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "Unrecognized character at %d: %c", point, c);
166+
// exponent and is not a hexadecimal digit.
167+
else if (!isxdigit(c)) {
168+
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "Unrecognized character '%c' at %d", c, point);
164169
return 0;
165170
}
166171

@@ -177,13 +182,13 @@ php_cassandra_parse_decimal(char* in, int in_len, mpz_t* number, int* scale)
177182
memcpy(&out[negative], &in[start], dot - start);
178183
memcpy(&out[negative + dot - start], &in[dot + 1], point - dot);
179184

180-
out_len = point - start;
185+
out_len = point - start + negative;
181186
*scale = point - 1 - dot;
182187
} else {
183188
// If there was no decimal then the unscaled value is just the number
184189
// formed from all the digits and the scale is zero.
185190
memcpy(&out[negative], &in[start], point - start);
186-
out_len = point - start;
191+
out_len = point - start + negative;
187192
*scale = 0;
188193
}
189194

@@ -195,8 +200,8 @@ php_cassandra_parse_decimal(char* in, int in_len, mpz_t* number, int* scale)
195200
int ok = php_cassandra_parse_integer(out, out_len, number);
196201

197202
if (!ok) {
198-
efree(out);
199203
zend_throw_exception_ex(cassandra_ce_InvalidArgumentException, 0 TSRMLS_CC, "Unable to extract integer part of decimal value: \"%s\", %s", in, out);
204+
efree(out);
200205
return 0;
201206
}
202207
efree(out);

tests/Cassandra/BigintTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Cassandra;
4+
5+
class BigintTest extends \PHPUnit_Framework_TestCase
6+
{
7+
/**
8+
* @expectedException InvalidArgumentException
9+
* @expectedExceptionMessage Non digit characters were found in value: '123.123'
10+
*/
11+
public function testThrowsWhenCreatingNotAnInteger()
12+
{
13+
new Bigint("123.123");
14+
}
15+
16+
/**
17+
* @dataProvider validNumbers
18+
*/
19+
public function testCorrectlyParsesStrings($number, $expected)
20+
{
21+
$number = new Bigint($number);
22+
$this->assertEquals($expected, $number->value());
23+
$this->assertEquals($expected, (string) $number);
24+
}
25+
26+
public function validNumbers()
27+
{
28+
return array(
29+
array("123", "123"),
30+
array("0123", "83"),
31+
array("0x123", "291"),
32+
array("0b1010101", "85"),
33+
array("-123", "-123"),
34+
array("-0123", "-83"),
35+
array("-0x123", "-291") ,
36+
array("-0b1010101", "-85")
37+
);
38+
}
39+
}

tests/Cassandra/DecimalTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Cassandra;
4+
5+
class DecimalTest extends \PHPUnit_Framework_TestCase
6+
{
7+
/**
8+
* @expectedException InvalidArgumentException
9+
* @expectedExceptionMessage Unrecognized character 'q' at 0
10+
*/
11+
public function testThrowsWhenCreatingNotAnInteger()
12+
{
13+
new Decimal("qwe");
14+
}
15+
16+
/**
17+
* @dataProvider validNumbers
18+
*/
19+
public function testCorrectlyParsesStrings($number, $value, $scale, $string)
20+
{
21+
$number = new Decimal($number);
22+
$this->assertEquals($value, $number->value());
23+
$this->assertEquals($scale, $number->scale());
24+
$this->assertEquals($string, (string) $number);
25+
}
26+
27+
public function validNumbers()
28+
{
29+
return array(
30+
array("123", "123", 0, "123"),
31+
array("0123", "83", 0, "83"),
32+
array("0x123", "291", 0, "291"),
33+
array("0b1010101", "85", 0, "85"),
34+
array("-123", "-123", 0, "-123"),
35+
array("-0123", "-83", 0, "-83"),
36+
array("-0x123", "-291", 0, "-291"),
37+
array("-0b1010101", "-85", 0, "-85"),
38+
array("1313123123.234234234234234234123", "1313123123234234234234234234123", 21, "1313123123.234234234234234234123")
39+
);
40+
}
41+
}

tests/Cassandra/VarintTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Cassandra;
4+
5+
class VarintTest extends \PHPUnit_Framework_TestCase
6+
{
7+
/**
8+
* @expectedException InvalidArgumentException
9+
* @expectedExceptionMessage Non digit characters were found in value: '123.123'
10+
*/
11+
public function testThrowsWhenCreatingNotAnInteger()
12+
{
13+
new Varint("123.123");
14+
}
15+
16+
/**
17+
* @dataProvider validNumbers
18+
*/
19+
public function testCorrectlyParsesStrings($number, $expected)
20+
{
21+
$number = new Varint($number);
22+
$this->assertEquals($expected, $number->value());
23+
$this->assertEquals($expected, (string) $number);
24+
}
25+
26+
public function validNumbers()
27+
{
28+
return array(
29+
array("123", "123"),
30+
array("0123", "83"),
31+
array("0x123", "291"),
32+
array("0b1010101", "85"),
33+
array("-123", "-123"),
34+
array("-0123", "-83"),
35+
array("-0x123", "-291") ,
36+
array("-0b1010101", "-85")
37+
);
38+
}
39+
}

0 commit comments

Comments
 (0)