Commit 5c4e5aa3 authored by Peter Eisentraut's avatar Peter Eisentraut

Make regression tests locale-proof by setting some locale categories

to C at run-time, and providing alternative output files for different
sort orders.
parent cd61650f
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.26 2002/04/08 04:37:36 tgl Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.27 2002/05/14 13:05:42 petere Exp $ -->
<chapter id="regress">
<title id="regress-title">Regression Tests</title>
......@@ -177,22 +177,32 @@
<title>Locale differences</title>
<para>
The tests expect to run in plain <quote>C</quote> locale. This
should not cause any problems when you run the tests against a
temporary installation, since the regression test driver takes care
to start the server in C locale. However, if you run the tests
against an already-installed server that is using non-C locale settings,
you may see differences caused by varying rules for string sort order,
formatting of numeric and monetary values, and so forth.
If you run the tests against an already-installed server that was
initialized with a collation order locale different than C then
there may be differences due to sort order and follow-up
failures. The regression test suite is set up to handle this
problem by providing alternative result files that together are
known to handle a large number of locales. For example, for the
<quote>char</quote> test, the expected file
<filename>char.out</filename> handles the C and POSIX locales,
and the file <filename>char_1.out</filename> handles many other
locales. The regression test driver will automatically pick the
best file to match against when checking for success and for
computing failure differences. (This means that the regression
tests cannot detect whether the results are appropriate for the
configured locale. The tests will simply pick the one result
file that works best.)
</para>
<para>
In some locales the resulting differences are small and easily checked by
inspection. However, in a locale that changes the rules for formatting
of numeric values (typically by swapping the usage of commas and
decimal points), entry of some data values will fail, resulting in
extensive differences later in the tests where the missing data values
are supposed to be used.
If for some reason the existing expected files do not cover some
locale, you can add a new file. The naming scheme is
<literal><replaceable>testname</>_<replaceable>digit</>.out</>.
The actual digit is not significant. Remember that the
regression test driver will consider all such files to be equally
valid test results. If the test results are platform-dependent,
the technique described in <xref linkend="regress-platform">
should be used instead.
</para>
</sect2>
......
......@@ -4,7 +4,7 @@
* Support for grand unified configuration scheme, including SET
* command, configuration file, and command line options.
*
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.66 2002/04/21 00:22:52 ishii Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.67 2002/05/14 13:05:43 petere Exp $
*
* Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
......@@ -587,22 +587,22 @@ static struct config_string
},
{
"lc_messages", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_messages,
"lc_messages", PGC_SUSET, PGC_S_DEFAULT, &locale_messages,
"", locale_messages_check, locale_messages_assign
},
{
"lc_monetary", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_monetary,
"lc_monetary", PGC_USERSET, PGC_S_DEFAULT, &locale_monetary,
"", locale_monetary_check, locale_monetary_assign
},
{
"lc_numeric", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_numeric,
"lc_numeric", PGC_USERSET, PGC_S_DEFAULT, &locale_numeric,
"", locale_numeric_check, locale_numeric_assign
},
{
"lc_time", PGC_POSTMASTER, PGC_S_DEFAULT, &locale_time,
"lc_time", PGC_USERSET, PGC_S_DEFAULT, &locale_time,
"", locale_time_check, locale_time_assign
},
......
--
-- CHAR
--
-- fixed-length by value
-- internally passed by value if <= 4 bytes in storage
SELECT char 'c' = char 'c' AS true;
true
------
t
(1 row)
--
-- Build a table for testing
--
CREATE TABLE CHAR_TBL(f1 char);
INSERT INTO CHAR_TBL (f1) VALUES ('a');
INSERT INTO CHAR_TBL (f1) VALUES ('A');
-- any of the following three input formats are acceptable
INSERT INTO CHAR_TBL (f1) VALUES ('1');
INSERT INTO CHAR_TBL (f1) VALUES (2);
INSERT INTO CHAR_TBL (f1) VALUES ('3');
-- zero-length char
INSERT INTO CHAR_TBL (f1) VALUES ('');
-- try char's of greater than 1 length
INSERT INTO CHAR_TBL (f1) VALUES ('cd');
ERROR: value too long for type character(1)
INSERT INTO CHAR_TBL (f1) VALUES ('c ');
SELECT '' AS seven, CHAR_TBL.*;
seven | f1
-------+----
| a
| A
| 1
| 2
| 3
|
| c
(7 rows)
SELECT '' AS six, c.*
FROM CHAR_TBL c
WHERE c.f1 <> 'a';
six | f1
-----+----
| A
| 1
| 2
| 3
|
| c
(6 rows)
SELECT '' AS one, c.*
FROM CHAR_TBL c
WHERE c.f1 = 'a';
one | f1
-----+----
| a
(1 row)
SELECT '' AS five, c.*
FROM CHAR_TBL c
WHERE c.f1 < 'a';
five | f1
------+----
| 1
| 2
| 3
|
(4 rows)
SELECT '' AS six, c.*
FROM CHAR_TBL c
WHERE c.f1 <= 'a';
six | f1
-----+----
| a
| 1
| 2
| 3
|
(5 rows)
SELECT '' AS one, c.*
FROM CHAR_TBL c
WHERE c.f1 > 'a';
one | f1
-----+----
| A
| c
(2 rows)
SELECT '' AS two, c.*
FROM CHAR_TBL c
WHERE c.f1 >= 'a';
two | f1
-----+----
| a
| A
| c
(3 rows)
DROP TABLE CHAR_TBL;
--
-- Now test longer arrays of char
--
CREATE TABLE CHAR_TBL(f1 char(4));
INSERT INTO CHAR_TBL (f1) VALUES ('a');
INSERT INTO CHAR_TBL (f1) VALUES ('ab');
INSERT INTO CHAR_TBL (f1) VALUES ('abcd');
INSERT INTO CHAR_TBL (f1) VALUES ('abcde');
ERROR: value too long for type character(4)
INSERT INTO CHAR_TBL (f1) VALUES ('abcd ');
SELECT '' AS four, CHAR_TBL.*;
four | f1
------+------
| a
| ab
| abcd
| abcd
(4 rows)
--
-- SELECT_HAVING
--
-- load test data
CREATE TABLE test_having (a int, b int, c char(8), d char);
INSERT INTO test_having VALUES (0, 1, 'XXXX', 'A');
INSERT INTO test_having VALUES (1, 2, 'AAAA', 'b');
INSERT INTO test_having VALUES (2, 2, 'AAAA', 'c');
INSERT INTO test_having VALUES (3, 3, 'BBBB', 'D');
INSERT INTO test_having VALUES (4, 3, 'BBBB', 'e');
INSERT INTO test_having VALUES (5, 3, 'bbbb', 'F');
INSERT INTO test_having VALUES (6, 4, 'cccc', 'g');
INSERT INTO test_having VALUES (7, 4, 'cccc', 'h');
INSERT INTO test_having VALUES (8, 4, 'CCCC', 'I');
INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j');
SELECT b, c FROM test_having
GROUP BY b, c HAVING count(*) = 1;
b | c
---+----------
1 | XXXX
3 | bbbb
(2 rows)
SELECT lower(c), count(c) FROM test_having
GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a);
lower | count
----------+-------
bbbb | 3
cccc | 4
xxxx | 1
(3 rows)
SELECT c, max(a) FROM test_having
GROUP BY c HAVING count(*) > 2 OR min(a) = max(a);
c | max
----------+-----
bbbb | 5
XXXX | 0
(2 rows)
DROP TABLE test_having;
--
-- SELECT_IMPLICIT
-- Test cases for queries with ordering terms missing from the target list.
-- This used to be called "junkfilter.sql".
-- The parser uses the term "resjunk" to handle these cases.
-- - thomas 1998-07-09
--
-- load test data
CREATE TABLE test_missing_target (a int, b int, c char(8), d char);
INSERT INTO test_missing_target VALUES (0, 1, 'XXXX', 'A');
INSERT INTO test_missing_target VALUES (1, 2, 'AAAA', 'b');
INSERT INTO test_missing_target VALUES (2, 2, 'AAAA', 'c');
INSERT INTO test_missing_target VALUES (3, 3, 'BBBB', 'D');
INSERT INTO test_missing_target VALUES (4, 3, 'BBBB', 'e');
INSERT INTO test_missing_target VALUES (5, 3, 'bbbb', 'F');
INSERT INTO test_missing_target VALUES (6, 4, 'cccc', 'g');
INSERT INTO test_missing_target VALUES (7, 4, 'cccc', 'h');
INSERT INTO test_missing_target VALUES (8, 4, 'CCCC', 'I');
INSERT INTO test_missing_target VALUES (9, 4, 'CCCC', 'j');
-- w/ existing GROUP BY target
SELECT c, count(*) FROM test_missing_target GROUP BY test_missing_target.c;
c | count
----------+-------
AAAA | 2
bbbb | 1
BBBB | 2
cccc | 2
CCCC | 2
XXXX | 1
(6 rows)
-- w/o existing GROUP BY target using a relation name in GROUP BY clause
SELECT count(*) FROM test_missing_target GROUP BY test_missing_target.c;
count
-------
2
1
2
2
2
1
(6 rows)
-- w/o existing GROUP BY target and w/o existing a different ORDER BY target
-- failure expected
SELECT count(*) FROM test_missing_target GROUP BY a ORDER BY b;
ERROR: Attribute test_missing_target.b must be GROUPed or used in an aggregate function
-- w/o existing GROUP BY target and w/o existing same ORDER BY target
SELECT count(*) FROM test_missing_target GROUP BY b ORDER BY b;
count
-------
1
2
3
4
(4 rows)
-- w/ existing GROUP BY target using a relation name in target
SELECT test_missing_target.b, count(*)
FROM test_missing_target GROUP BY b ORDER BY b;
b | count
---+-------
1 | 1
2 | 2
3 | 3
4 | 4
(4 rows)
-- w/o existing GROUP BY target
SELECT c FROM test_missing_target ORDER BY a;
c
----------
XXXX
AAAA
AAAA
BBBB
BBBB
bbbb
cccc
cccc
CCCC
CCCC
(10 rows)
-- w/o existing ORDER BY target
SELECT count(*) FROM test_missing_target GROUP BY b ORDER BY b desc;
count
-------
4
3
2
1
(4 rows)
-- group using reference number
SELECT count(*) FROM test_missing_target ORDER BY 1 desc;
count
-------
10
(1 row)
-- order using reference number
SELECT c, count(*) FROM test_missing_target GROUP BY 1;
c | count
----------+-------
AAAA | 2
bbbb | 1
BBBB | 2
cccc | 2
CCCC | 2
XXXX | 1
(6 rows)
-- group using reference number out of range
-- failure expected
SELECT c, count(*) FROM test_missing_target GROUP BY 3;
ERROR: GROUP BY position 3 is not in target list
-- group w/o existing GROUP BY and ORDER BY target under ambiguous condition
-- failure expected
SELECT count(*) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY b ORDER BY b;
ERROR: Column reference "b" is ambiguous
-- order w/ target under ambiguous condition
-- failure NOT expected
SELECT a, a FROM test_missing_target
ORDER BY a;
a | a
---+---
0 | 0
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
6 | 6
7 | 7
8 | 8
9 | 9
(10 rows)
-- order expression w/ target under ambiguous condition
-- failure NOT expected
SELECT a/2, a/2 FROM test_missing_target
ORDER BY a/2;
?column? | ?column?
----------+----------
0 | 0
0 | 0
1 | 1
1 | 1
2 | 2
2 | 2
3 | 3
3 | 3
4 | 4
4 | 4
(10 rows)
-- group expression w/ target under ambiguous condition
-- failure NOT expected
SELECT a/2, a/2 FROM test_missing_target
GROUP BY a/2;
?column? | ?column?
----------+----------
0 | 0
1 | 1
2 | 2
3 | 3
4 | 4
(5 rows)
-- group w/ existing GROUP BY target under ambiguous condition
SELECT x.b, count(*) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b;
b | count
---+-------
1 | 1
2 | 2
3 | 3
4 | 4
(4 rows)
-- group w/o existing GROUP BY target under ambiguous condition
SELECT count(*) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b;
count
-------
1
2
3
4
(4 rows)
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
SELECT count(*) INTO TABLE test_missing_target2
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b;
SELECT * FROM test_missing_target2;
count
-------
1
2
3
4
(4 rows)
-- Functions and expressions
-- w/ existing GROUP BY target
SELECT a%2, count(b) FROM test_missing_target GROUP BY test_missing_target.a%2;
?column? | count
----------+-------
0 | 5
1 | 5
(2 rows)
-- w/o existing GROUP BY target using a relation name in GROUP BY clause
SELECT count(c) FROM test_missing_target GROUP BY lower(test_missing_target.c);
count
-------
2
3
4
1
(4 rows)
-- w/o existing GROUP BY target and w/o existing a different ORDER BY target
-- failure expected
SELECT count(a) FROM test_missing_target GROUP BY a ORDER BY b;
ERROR: Attribute test_missing_target.b must be GROUPed or used in an aggregate function
-- w/o existing GROUP BY target and w/o existing same ORDER BY target
SELECT count(b) FROM test_missing_target GROUP BY b/2 ORDER BY b/2;
count
-------
1
5
4
(3 rows)
-- w/ existing GROUP BY target using a relation name in target
SELECT lower(test_missing_target.c), count(c)
FROM test_missing_target GROUP BY lower(c) ORDER BY lower(c);
lower | count
----------+-------
aaaa | 2
bbbb | 3
cccc | 4
xxxx | 1
(4 rows)
-- w/o existing GROUP BY target
SELECT a FROM test_missing_target ORDER BY upper(d);
a
---
0
1
2
3
4
5
6
7
8
9
(10 rows)
-- w/o existing ORDER BY target
SELECT count(b) FROM test_missing_target
GROUP BY (b + 1) / 2 ORDER BY (b + 1) / 2 desc;
count
-------
7
3
(2 rows)
-- group w/o existing GROUP BY and ORDER BY target under ambiguous condition
-- failure expected
SELECT count(x.a) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY b/2 ORDER BY b/2;
ERROR: Column reference "b" is ambiguous
-- group w/ existing GROUP BY target under ambiguous condition
SELECT x.b/2, count(x.b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b/2;
?column? | count
----------+-------
0 | 1
1 | 5
2 | 4
(3 rows)
-- group w/o existing GROUP BY target under ambiguous condition
-- failure expected due to ambiguous b in count(b)
SELECT count(b) FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b/2;
ERROR: Column reference "b" is ambiguous
-- group w/o existing GROUP BY target under ambiguous condition
-- into a table
SELECT count(x.b) INTO TABLE test_missing_target3
FROM test_missing_target x, test_missing_target y
WHERE x.a = y.a
GROUP BY x.b/2;
SELECT * FROM test_missing_target3;
count
-------
1
5
4
(3 rows)
-- Cleanup
DROP TABLE test_missing_target;
DROP TABLE test_missing_target2;
DROP TABLE test_missing_target3;
This source diff could not be displayed because it is too large. You can view the blob instead.
--
-- VARCHAR
--
CREATE TABLE VARCHAR_TBL(f1 varchar(1));
INSERT INTO VARCHAR_TBL (f1) VALUES ('a');
INSERT INTO VARCHAR_TBL (f1) VALUES ('A');
-- any of the following three input formats are acceptable
INSERT INTO VARCHAR_TBL (f1) VALUES ('1');
INSERT INTO VARCHAR_TBL (f1) VALUES (2);
INSERT INTO VARCHAR_TBL (f1) VALUES ('3');
-- zero-length char
INSERT INTO VARCHAR_TBL (f1) VALUES ('');
-- try varchar's of greater than 1 length
INSERT INTO VARCHAR_TBL (f1) VALUES ('cd');
ERROR: value too long for type character varying(1)
INSERT INTO VARCHAR_TBL (f1) VALUES ('c ');
SELECT '' AS seven, VARCHAR_TBL.*;
seven | f1
-------+----
| a
| A
| 1
| 2
| 3
|
| c
(7 rows)
SELECT '' AS six, c.*
FROM VARCHAR_TBL c
WHERE c.f1 <> 'a';
six | f1
-----+----
| A
| 1
| 2
| 3
|
| c
(6 rows)
SELECT '' AS one, c.*
FROM VARCHAR_TBL c
WHERE c.f1 = 'a';
one | f1
-----+----
| a
(1 row)
SELECT '' AS five, c.*
FROM VARCHAR_TBL c
WHERE c.f1 < 'a';
five | f1
------+----
| 1
| 2
| 3
|
(4 rows)
SELECT '' AS six, c.*
FROM VARCHAR_TBL c
WHERE c.f1 <= 'a';
six | f1
-----+----
| a
| 1
| 2
| 3
|
(5 rows)
SELECT '' AS one, c.*
FROM VARCHAR_TBL c
WHERE c.f1 > 'a';
one | f1
-----+----
| A
| c
(2 rows)
SELECT '' AS two, c.*
FROM VARCHAR_TBL c
WHERE c.f1 >= 'a';
two | f1
-----+----
| a
| A
| c
(3 rows)
DROP TABLE VARCHAR_TBL;
--
-- Now test longer arrays of char
--
CREATE TABLE VARCHAR_TBL(f1 varchar(4));
INSERT INTO VARCHAR_TBL (f1) VALUES ('a');
INSERT INTO VARCHAR_TBL (f1) VALUES ('ab');
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd');
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcde');
ERROR: value too long for type character varying(4)
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd ');
SELECT '' AS four, VARCHAR_TBL.*;
four | f1
------+------
| a
| ab
| abcd
| abcd
(4 rows)
#! /bin/sh
# $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.24 2002/04/24 01:56:20 momjian Exp $
# $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.25 2002/05/14 13:05:43 petere Exp $
me=`basename $0`
: ${TMPDIR=/tmp}
......@@ -451,6 +451,16 @@ if [ $? -ne 0 ]; then
(exit 2); exit
fi
"$bindir/psql" $psql_options -c "\
alter database \"$dbname\" set lc_messages to 'C';
alter database \"$dbname\" set lc_monetary to 'C';
alter database \"$dbname\" set lc_numeric to 'C';
alter database \"$dbname\" set lc_time to 'C';" "$dbname" 2>/dev/null
if [ $? -ne 0 ]; then
echo "$me: could not set database default locales"
(exit 2); exit
fi
# ----------
# Remove regressuser* and regressgroup* user accounts.
......@@ -559,22 +569,44 @@ do
# to a system-specific expected file.
# There shouldn't be multiple matches, but take the last if there are.
EXPECTED="$inputdir/expected/${name}.out"
EXPECTED="$inputdir/expected/${name}"
for LINE in $SUBSTLIST
do
if [ `expr "$LINE" : "$name="` -ne 0 ]
then
SUBST=`echo "$LINE" | sed 's/^.*=//'`
EXPECTED="$inputdir/expected/${SUBST}.out"
EXPECTED="$inputdir/expected/${SUBST}"
fi
done
diff $DIFFFLAGS $EXPECTED $outputdir/results/${name}.out >/dev/null 2>&1
case $? in
# If there are multiple equally valid result file, loop to get the right one.
# If none match, diff against the closet one.
bestfile=
bestdiff=
result=2
for thisfile in $EXPECTED.out ${EXPECTED}_[0-9].out; do
[ ! -r "$thisfile" ] && continue
diff $DIFFFLAGS $thisfile $outputdir/results/${name}.out >/dev/null 2>&1
result=$?
case $result in
0) break;;
1) thisdiff=`diff $DIFFFLAGS $thisfile $outputdir/results/${name}.out | wc -l`
if [ -z "$bestdiff" ] || [ "$thisdiff" -lt "$bestdiff" ]; then
bestdiff=$thisdiff; bestfile=$thisfile
fi
continue;;
2) break;;
esac
done
# Now print the result.
case $result in
0)
echo "ok";;
1)
( diff $DIFFFLAGS -C3 $EXPECTED $outputdir/results/${name}.out
( diff $DIFFFLAGS -C3 $bestfile $outputdir/results/${name}.out
echo
echo "======================================================================"
echo ) >> "$diff_file"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment