Skip to content

Commit 8bb6cef

Browse files
authored
Revised a few existing tests that are flawed (#1103)
1 parent cd64173 commit 8bb6cef

6 files changed

+486
-350
lines changed

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ trigger:
1616
jobs:
1717
- job: macOS
1818
pool:
19-
vmImage: 'macOS-10.13'
19+
vmImage: 'macOS-10.14'
2020
steps:
2121
- checkout: self
2222
clean: true

test/functional/sqlsrv/AEData.inc

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,9 @@ $sqlTypes = array(
8484
function is_incompatible_types_error( $dataType, $sqlType )
8585
{
8686
$errors = sqlsrv_errors();
87-
foreach ( $errors as $error )
88-
{
87+
foreach ($errors as $error) {
8988
// 22018 is the SQLSTATE for the operand crash error for incompatible types
90-
if ( $error['SQLSTATE'] == 22018 )
91-
{
89+
if ($error['SQLSTATE'] == '22018') {
9290
echo "Encrypted $sqlType is incompatible with encrypted $dataType\n";
9391
}
9492
}
@@ -109,7 +107,6 @@ function get_sqlType_constant( $sqlType )
109107
{
110108
switch ( $sqlType ) {
111109
case 'SQLSRV_SQLTYPE_BIGINT':
112-
case 'SQLSRV_SQLTYPE_BINARY':
113110
case 'SQLSRV_SQLTYPE_BIT':
114111
case 'SQLSRV_SQLTYPE_DATE':
115112
case 'SQLSRV_SQLTYPE_DATETIME':
@@ -135,6 +132,10 @@ function get_sqlType_constant( $sqlType )
135132
case 'SQLSRV_SQLTYPE_XML':
136133
return constant( $sqlType );
137134
break;
135+
case 'SQLSRV_SQLTYPE_BINARY':
136+
// our tests always use precision 5 for SQLSRV_SQLTYPE_BINARY
137+
return SQLSRV_SQLTYPE_BINARY(5);
138+
break;
138139
case 'SQLSRV_SQLTYPE_CHAR':
139140
// our tests always use precision 5 for SQLSRV_SQLTYPE_CHAR
140141
return SQLSRV_SQLTYPE_CHAR(5);
@@ -146,7 +147,7 @@ function get_sqlType_constant( $sqlType )
146147
case 'SQLSRV_SQLTYPE_NCHAR':
147148
// our tests always use precision 5 for SQLSRV_SQLTYPE_NCHAR
148149
return SQLSRV_SQLTYPE_NCHAR(5);
149-
break;
150+
break;
150151
case 'SQLSRV_SQLTYPE_NUMERIC':
151152
// our tests always use precision 10 scale 5 for SQLSRV_SQLTYPE_NUMERIC
152153
return SQLSRV_SQLTYPE_NUMERIC(10, 5);
@@ -157,7 +158,7 @@ function get_sqlType_constant( $sqlType )
157158
}
158159
}
159160

160-
function isDateTimeType( $sqlType )
161+
function isDateTimeType($sqlType)
161162
{
162163
return ($sqlType == 'SQLSRV_SQLTYPE_DATE' ||
163164
$sqlType == 'SQLSRV_SQLTYPE_DATETIME' ||
@@ -167,4 +168,20 @@ function isDateTimeType( $sqlType )
167168
$sqlType == 'SQLSRV_SQLTYPE_TIME');
168169
}
169170

171+
function isLOBType($sqlType)
172+
{
173+
return ($sqlType == 'SQLSRV_SQLTYPE_TEXT' || $sqlType == 'SQLSRV_SQLTYPE_NTEXT' || $sqlType == 'SQLSRV_SQLTYPE_IMAGE');
174+
}
175+
176+
function isCompatible($compatList, $dataType, $sqlType)
177+
{
178+
foreach ($compatList[$dataType] as $compatType) {
179+
if (stripos($compatType, $sqlType) !== false) {
180+
return true;
181+
}
182+
}
183+
184+
return false;
185+
}
186+
170187
?>

test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_numeric.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ foreach ($dataTypes as $dataType) {
5252
}
5353
}
5454
// 22018 is the SQLSTATE for any incompatible conversion errors
55-
if ($isCompatible && sqlsrv_errors()[0]['SQLSTATE'] == 22018) {
55+
if ($isCompatible && sqlsrv_errors()[0]['SQLSTATE'] == '22018') {
5656
echo "$sqlType should be compatible with $dataType\n";
5757
$success = false;
5858
}

test/functional/sqlsrv/sqlsrv_ae_output_param_sqltype_datetime.phpt

Lines changed: 143 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,154 @@
11
--TEST--
22
Test for inserting and retrieving encrypted data of datetime types
33
--DESCRIPTION--
4-
Bind output params using sqlsrv_prepare with all sql_type
4+
Bind output/inout params using sqlsrv_prepare with all sql_type
55
--SKIPIF--
66
<?php require('skipif_versions_old.inc'); ?>
77
--FILE--
8-
<?php
9-
require_once('MsCommon.inc');
10-
require_once('AEData.inc');
11-
12-
date_default_timezone_set("Canada/Pacific");
13-
$dataTypes = array("date", "datetime", "datetime2", "smalldatetime", "time", "datetimeoffset");
14-
$directions = array("SQLSRV_PARAM_OUT", "SQLSRV_PARAM_INOUT");
15-
16-
// this is a list of implicit datatype conversion that SQL Server allows (https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-type-conversion-database-engine)
17-
$compatList = array("date" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
18-
"datetime" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
19-
"datetime2" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
20-
"smalldatetime" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
21-
"time" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
22-
"datetimeoffset" => array("SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIMEOFFSET") );
23-
24-
$conn = AE\connect();
25-
26-
foreach ($dataTypes as $dataType) {
27-
echo "\nTesting $dataType:\n";
28-
$success = true;
29-
30-
// create table
31-
$tbname = GetTempTableName("", false);
32-
$colMetaArr = array(new AE\ColumnMeta($dataType, "c_det"), new AE\ColumnMeta($dataType, "c_rand", null, false));
33-
AE\createTable($conn, $tbname, $colMetaArr);
34-
35-
if (AE\isColEncrypted()) {
36-
// Create a Store Procedure
37-
$spname = 'selectAllColumns';
38-
createProc($conn, $spname, "@c_det $dataType OUTPUT, @c_rand $dataType OUTPUT", "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname");
39-
}
40-
8+
<?php
9+
require_once('MsCommon.inc');
10+
require_once('AEData.inc');
11+
12+
date_default_timezone_set("Canada/Pacific");
13+
$dataTypes = array("date", "datetime", "datetime2", "smalldatetime", "time", "datetimeoffset");
14+
15+
$directions = array(SQLSRV_PARAM_OUT, SQLSRV_PARAM_INOUT);
16+
17+
// this is a list of implicit datatype conversion that SQL Server allows (https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-type-conversion-database-engine)
18+
$compatList = array("date" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
19+
"datetime" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
20+
"datetime2" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
21+
"smalldatetime" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
22+
"time" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_DATETIME2"),
23+
"datetimeoffset" => array("SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_DATETIMEOFFSET") );
24+
25+
function testOutputParam($conn, $spname, $direction, $dataType, $sqlType)
26+
{
27+
// The driver does not support these types as output params, simply return
28+
if (isDateTimeType($sqlType) || isLOBType($sqlType)) {
29+
return true;
30+
}
31+
32+
global $compatList;
33+
34+
$sqlTypeConstant = get_sqlType_constant($sqlType);
35+
36+
// Call store procedure
37+
$outSql = AE\getCallProcSqlPlaceholders($spname, 2);
38+
39+
// Set these to NULL such that the PHP type of each output parameter is inferred
40+
// from the SQLSRV_SQLTYPE_* constant
41+
$c_detOut = null;
42+
$c_randOut = null;
43+
$stmt = sqlsrv_prepare(
44+
$conn,
45+
$outSql,
46+
array(array( &$c_detOut, $direction, null, $sqlTypeConstant),
47+
array(&$c_randOut, $direction, null, $sqlTypeConstant ))
48+
);
49+
if (!$stmt) {
50+
die(print_r(sqlsrv_errors(), true));
51+
}
52+
sqlsrv_execute($stmt);
53+
54+
$success = false;
55+
$errors = sqlsrv_errors();
56+
if (AE\IsDataEncrypted()) {
57+
// With data encrypted, errors are totally expected
58+
if (empty($errors)) {
59+
echo "Encrypted data: $dataType should NOT be compatible with $sqlType\n";
60+
} else {
61+
// This should return 22018, the SQLSTATE for any incompatible conversion,
62+
// except the XML type
63+
$success = ($errors[0]['SQLSTATE'] === '22018');
64+
if (!$success) {
65+
if ($sqlType === 'SQLSRV_SQLTYPE_XML') {
66+
$success = ($errors[0]['SQLSTATE'] === '42000');
67+
} else {
68+
echo "Encrypted data: unexpected errors with SQL type: $sqlType\n";
69+
}
70+
}
71+
}
72+
} else {
73+
$compatible = isCompatible($compatList, $dataType, $sqlType);
74+
if ($compatible) {
75+
if (!empty($errors)) {
76+
echo "$dataType should be compatible with $sqlType.\n";
77+
} else {
78+
$success = true;
79+
}
80+
} else {
81+
$implicitConv = 'Implicit conversion from data type ';
82+
83+
// 22018 is the SQLSTATE for any incompatible conversion errors
84+
if ($errors[0]['SQLSTATE'] === '22018') {
85+
$success = true;
86+
} elseif (strpos($errors[0]['message'], $implicitConv) !== false) {
87+
$success = true;
88+
} else {
89+
echo "Failed with SQL type: $sqlType\n";
90+
}
91+
}
92+
}
93+
return $success;
94+
}
95+
96+
////////////////////////////////////////////////////////////////////////////////////////
97+
98+
$conn = AE\connect();
99+
100+
foreach ($dataTypes as $dataType) {
101+
echo "\nTesting $dataType:\n";
102+
$success = true;
103+
104+
// create table
105+
$tbname = GetTempTableName("", false);
106+
$colMetaArr = array(new AE\ColumnMeta($dataType, "c_det"), new AE\ColumnMeta($dataType, "c_rand", null, false));
107+
AE\createTable($conn, $tbname, $colMetaArr);
108+
109+
// Create a Store Procedure
110+
$spname = 'selectAllColumns';
111+
createProc($conn, $spname, "@c_det $dataType OUTPUT, @c_rand $dataType OUTPUT", "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname");
112+
41113
// insert a row
114+
// Take the second and third entres (some edge cases) from the various
115+
// $[$dataType]_params in AEData.inc
116+
// e.g. with $dataType = 'date', use $date_params[1] and $date_params[2]
117+
// to form an array, namely ["0001-01-01", "9999-12-31"]
42118
$inputValues = array_slice(${explode("(", $dataType)[0] . "_params"}, 1, 2);
43-
$r;
44-
$stmt = AE\insertRow($conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r);
45-
if ($r === false) {
46-
is_incompatible_types_error($dataType, "default type");
47-
}
48-
49-
foreach($directions as $direction) {
50-
echo "Testing as $direction:\n";
51-
52-
// test each SQLSRV_SQLTYPE_ constants
53-
foreach ($sqlTypes as $sqlType) {
54-
if (!AE\isColEncrypted()) {
55-
$isCompatible = false;
56-
foreach ($compatList[$dataType] as $compatType) {
57-
if (stripos($compatType, $sqlType) !== false) {
58-
$isCompatible = true;
59-
}
60-
}
61-
// 22018 is the SQLSTATE for any incompatible conversion errors
62-
$errors = sqlsrv_errors();
63-
if (!empty($errors) && $isCompatible && $errors[0]['SQLSTATE'] == 22018) {
64-
echo "$sqlType should be compatible with $dataType\n";
65-
$success = false;
66-
}
67-
} else {
68-
// skip unsupported datetime types
69-
if (!isDateTimeType($sqlType)) {
70-
$sqlTypeConstant = get_sqlType_constant($sqlType);
71-
72-
// Call store procedure
73-
$outSql = AE\getCallProcSqlPlaceholders($spname, 2);
74-
$c_detOut = '';
75-
$c_randOut = '';
76-
$stmt = sqlsrv_prepare( $conn, $outSql,
77-
array(array( &$c_detOut, SQLSRV_PARAM_OUT, null, $sqlTypeConstant),
78-
array(&$c_randOut, SQLSRV_PARAM_OUT, null, $sqlTypeConstant )));
79-
if (!$stmt) {
80-
die(print_r(sqlsrv_errors(), true));
81-
}
82-
sqlsrv_execute($stmt);
83-
$errors = sqlsrv_errors();
84-
if (empty($errors) && AE\IsDataEncrypted()) {
85-
// SQLSRV_PHPTYPE_DATETIME not supported
86-
echo "$dataType should not be compatible with any datetime type.\n";
87-
$success = false;
88-
}
89-
}
90-
}
91-
}
92-
}
93-
94-
// cleanup
95-
sqlsrv_free_stmt($stmt);
96-
sqlsrv_query($conn, "TRUNCATE TABLE $tbname");
97-
98-
if ($success) {
99-
echo "Test successfully done.\n";
100-
}
101-
102-
if (AE\isColEncrypted()) {
103-
dropProc($conn, $spname);
104-
}
105-
dropTable($conn, $tbname);
106-
}
107-
108-
sqlsrv_close($conn);
119+
$r;
120+
$stmt = AE\insertRow($conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r);
121+
if ($r === false) {
122+
fatalError("Failed to insert data of type $dataType\n");
123+
}
124+
125+
foreach ($directions as $direction) {
126+
$dir = ($direction == SQLSRV_PARAM_OUT) ? 'SQLSRV_PARAM_OUT' : 'SQLSRV_PARAM_INOUT';
127+
echo "Testing as $dir:\n";
128+
129+
// test each SQLSRV_SQLTYPE_* constants
130+
foreach ($sqlTypes as $sqlType) {
131+
$success = testOutputParam($conn, $spname, $direction, $dataType, $sqlType);
132+
if (!$success) {
133+
// No point to continue looping
134+
echo("Test failed: $dataType as $sqlType\n");
135+
die(print_r(sqlsrv_errors(), true));
136+
}
137+
}
138+
}
139+
140+
// cleanup
141+
sqlsrv_free_stmt($stmt);
142+
sqlsrv_query($conn, "TRUNCATE TABLE $tbname");
143+
144+
dropProc($conn, $spname);
145+
if ($success) {
146+
echo "Test successfully done.\n";
147+
}
148+
dropTable($conn, $tbname);
149+
}
150+
151+
sqlsrv_close($conn);
109152
?>
110153
--EXPECT--
111154

0 commit comments

Comments
 (0)