File: test_MVU.sh

package info (click to toggle)
pgtap 1.3.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,792 kB
  • sloc: sql: 25,795; sh: 790; makefile: 287; perl: 175
file content (331 lines) | stat: -rwxr-xr-x 11,312 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
#!/usr/bin/env bash

# Test performing a Major Version Upgrade via pg_upgrade.
#
# MVU can be problematic due to catalog changes. For example, if the extension
# contains a view that references a catalog column that no longer exists,
# pg_upgrade itself will break.

set -E -e -u -o pipefail 

BASEDIR=`dirname $0`
if ! . $BASEDIR/../tools/util.sh; then
    echo "FATAL: error sourcing $BASEDIR/../tools/util.sh" 1>&2
    exit 99
fi
trap err_report ERR

debug 19 "Arguments: $@"

rc=0

byte_len() (
    [ $# -eq 1 ] || die 99 "Expected 1 argument, not $# ($@)"
    LANG=C LC_ALL=C
    debug 99 "byte_len($@) = ${#1}"
    echo ${#1}
)

check_bin() {
    for f in pg_ctl psql initdb; do
        [ -x "$1/$f" ] || die 1 "$1/$f does not exist or is not executable"
    done
}

# mktemp on OS X results is a super-long path name that can cause problems, ie:
#   connection to database failed: Unix-domain socket path "/private/var/folders/rp/mv0457r17cg0xqyw5j7701892tlc0h/T/test_pgtap_upgrade.upgrade.7W4BLF/.s.PGSQL.50432" is too long (maximum 103 bytes)
#
# This function looks for that condition and replaces the output with something more legible
short_tmpdir() (
    [ $# -eq 1 ] || die 99 "Expected 1 argument, not $# ($@)"
    [ "$TMPDIR" != "" ] || die 99 '$TMPDIR not set'
    out=$(mktemp -p '' -d $1.XXXXXX)
    if echo "$out" | egrep -q '^(/private)?/var/folders'; then
        newout=$(echo "$out" | sed -e "s#.*/$TMPDIR#$TMPDIR#")
        debug 19 "replacing '$out' with '$newout'"
    fi

    debug 9 "$0($@) = $out"
    # Postgres blows up if this is too long. Technically the limit is 103 bytes,
    # but need to account for the socket name, plus the fact that OS X might
    # prepend '/private' to what we return. :(
    [ $(byte_len "$out") -lt 75 ] || die 9 "short_tmpdir($@) returning a value >= 75 bytes ('$out')"
    echo "$out"
)

banner() {
    echo
    echo '###################################'
    echo "$@"
    echo '###################################'
    echo
}

modify_config() (
    # See below for definition of ctl_separator
    if [ -z "$ctl_separator" ]; then
        confDir=$PGDATA
        conf=$confDir/postgresql.conf
        debug 6 "$0: conf = $conf"

        debug 0 "Modifying NATIVE $conf"

        echo "port = $PGPORT" >> $conf
    else
        confDir="/etc/postgresql/$1/$cluster_name"
        conf="$confDir/postgresql.conf"
        debug 6 "$0: confDir = $confDir conf=$conf"
        debug_ls 9 -la $confDir

        debug 0 "Modifying DEBIAN $confDir and $PGDATA"

        debug 2 ln -s $conf $PGDATA/
        ln -s $conf $PGDATA/
        # Some versions also have a conf.d ...
        if [ -e "$confDir/conf.d" ]; then
            debug 2 ln -s $confDir/conf.d $PGDATA/
            ln -s $confDir/conf.d $PGDATA/
        fi
        debug_ls 8 -la $PGDATA

        # Shouldn't need to muck with PGPORT...

        # GUC changed somewhere between 9.1 and 9.5, so read config to figure out correct value
        guc=$(grep unix_socket_director $conf | sed -e 's/^# *//' | cut -d ' ' -f 1)
        debug 4 "$0: guc = $guc"
        echo "$guc = '/tmp'" >> $conf
    fi

    echo "synchronous_commit = off" >> $conf
)

#############################
# Argument processing
keep=''
if [ "$1" == "-k" ]; then
    debug 1 keeping results after exit
    keep=1
    shift
fi

sudo=''
if [ "$1" == '-s' ]; then
    # Useful error if we can't find sudo
    command -v sudo > /dev/null || echo "sudo not found"
    sudo=$(command -v sudo)
    debug 2 "sudo located at $sudo"
    shift
fi

OLD_PORT=$1
NEW_PORT=$2
OLD_VERSION=$3
NEW_VERSION=$4
OLD_PATH="${5:-/usr/lib/postgresql/$OLD_VERSION/bin}"
NEW_PATH="${5:-/usr/lib/postgresql/$NEW_VERSION/bin}"

export PGDATABASE=test_pgtap_upgrade

check_bin "$OLD_PATH"
check_bin "$NEW_PATH"

export TMPDIR=${TMPDIR:-${TEMP:-${TMP:-/tmp}}}
debug 9 "\$TMPDIR=$TMPDIR"
[ $(byte_len "$TMPDIR") -lt 50 ] || die 9 "\$TMPDIR ('$TMPDIR') is too long; please set it" '(or $TEMP, or $TMP) to a value less than 50 bytes'
upgrade_dir=$(short_tmpdir test_pgtap_upgrade.upgrade)
old_dir=$(short_tmpdir test_pgtap_upgrade.old)
new_dir=$(short_tmpdir test_pgtap_upgrade.new)

# Note: if this trap fires and removes the old directories with databases still
# running we'll get a bunch of spew on STDERR. It'd be nice to have a trap that
# knew what databases might actually be running.
exit_trap() {
    # No point in stopping on error in here...
    set +e

    # Force sudo on a debian system (see below)
    [ -z "$ctl_separator" ] || sudo=$(command -v sudo)

    # Attempt to shut down any running clusters, otherwise we'll get log spew
    # when the temporary directories vanish.
    $old_pg_ctl stop > /dev/null 2>&1
    $new_pg_ctl stop > /dev/null 2>&1

    # Do not simply stick this command in the trap command; the quoting gets
    # tricky, but the quoting is also damn critical to make sure rm -rf doesn't
    # hose you if the temporary directory names have spaces in them!
    $sudo rm -rf "$upgrade_dir" "$old_dir" "$new_dir"
}
[ -n "$keep" ] || trap exit_trap EXIT
debug 5 "traps: $(trap -p)"

cluster_name=test_pg_upgrade 
if command -v pg_ctlcluster > /dev/null; then
    # Looks like we're running in a apt / Debian / Ubuntu environment, so use their tooling
    ctl_separator='--'

    # Force socket path to normal for pg_upgrade
    export PGHOST=/tmp

    # And force current user
    export PGUSER=${USER:-$(whoami)}

    old_initdb="$sudo pg_createcluster $OLD_VERSION $cluster_name -u $PGUSER -p $OLD_PORT -d $old_dir -- -A trust"
    old_pg_ctl="$sudo pg_ctlcluster $OLD_VERSION test_pg_upgrade"
    new_initdb="$sudo pg_createcluster $NEW_VERSION $cluster_name -u $PGUSER -p $NEW_PORT -d $new_dir -- -A trust"
    new_pg_ctl="$sudo pg_ctlcluster $NEW_VERSION test_pg_upgrade"

    # See also ../.github/workflows/test.yml
    new_pg_upgrade="/usr/lib/postgresql/$NEW_VERSION/bin/pg_upgrade"
else
    ctl_separator=''
    old_initdb="$(find_at_path "$OLD_PATH" initdb) -D $old_dir -N"
    old_pg_ctl=$(find_at_path "$OLD_PATH" pg_ctl)
    new_initdb="$(find_at_path "$NEW_PATH" initdb) -D $new_dir -N"
    new_pg_ctl=$(find_at_path "$NEW_PATH" pg_ctl)

    new_pg_upgrade=$(find_at_path "$NEW_PATH" pg_upgrade)
fi

# Postgres 18 enables checksums by default, so turn them off to be compatible
# with earlier versions, where they're off by default.
if [ "$OLD_VERSION" -ge 18 ]; then
    old_initdb+=" --no-data-checksums"
fi
if [ "$NEW_VERSION" -ge 18 ]; then
    new_initdb+=" --no-data-checksums"
fi

##################################################################################################
banner "Creating old version temporary installation at $old_dir on port $OLD_PORT (in the background)"
echo "Creating new version temporary installation at $new_dir on port $NEW_PORT (in the background)"
$old_initdb &
$new_initdb &

echo Waiting...
wait

##################################################################################################
banner "Starting OLD $OLD_VERSION postgres via $old_pg_ctl"
export PGDATA=$old_dir
export PGPORT=$OLD_PORT
modify_config $OLD_VERSION

$old_pg_ctl start $ctl_separator -w # older versions don't support --wait

echo "Creating database"
createdb # Note this uses PGPORT, so no need to wrap.

echo "Installing pgtap"
# If user requested sudo then we need to use it for the install step. TODO:
# it'd be nice to move this into the Makefile, if the PGXS make stuff allows
# it...
$sudo make clean install

banner "Loading extension"
psql -c 'CREATE EXTENSION pgtap' # Also uses PGPORT

echo "Stopping OLD postgres via $old_pg_ctl"
$old_pg_ctl stop $ctl_separator -w # older versions don't support --wait

##################################################################################################
banner "Running pg_upgrade"
export PGDATA=$new_dir
export PGPORT=$NEW_PORT
modify_config $NEW_VERSION

(
    cd $upgrade_dir
    if [ $DEBUG -ge 9 ]; then
        echo $old_dir; ls -la $old_dir; egrep 'director|unix|conf' $old_dir/postgresql.conf
        echo $new_dir; ls -la $new_dir; egrep 'director|unix|conf' $new_dir/postgresql.conf
    fi
    echo $new_pg_upgrade -d "$old_dir" -D "$new_dir" -b "$OLD_PATH" -B "$NEW_PATH"
    $new_pg_upgrade -d "$old_dir" -D "$new_dir" -b "$OLD_PATH" -B "$NEW_PATH" || rc=$?
    if [ $rc -ne 0 ]; then
        # Dump log, but only if we're not keeping the directory
        if [ -z "$keep" ]; then
            for f in `ls *.log`; do
                echo; echo; echo; echo; echo; echo
                echo "`pwd`/$f:"
                cat "$f"
            done
            ls -la
        else
            error "pg_upgrade logs are at $upgrade_dir"
        fi
        die $rc "pg_upgrade returned $rc"
    fi
)

##################################################################################################
banner "Testing UPGRADED cluster"

# Run our tests against the upgraded cluster, but first make sure the old
# cluster is still down, to ensure there's no chance of testing it instead.
# Note that some versions of pg_ctl return different exit codes when the server
# isn't running.
echo ensuring OLD cluster is stopped
rc=0
status=$($old_pg_ctl status) || rc=$?
[ "$status" == 'pg_ctl: no server running' ] || die 3 "$old_pg_ctl status returned '$status' and exited with $?"
debug 4 "$old_pg_ctl status exited with $rc"

# TODO: send log output to a file so it doesn't mix in with STDOUT
echo starting NEW cluster
$new_pg_ctl start $ctl_separator -w || die $? "$new_pg_ctl start $ctl_separator -w returned $?"
$new_pg_ctl status # Should error if not running on most versions

psql -E -c '\dx'
psql -E -c 'SELECT pgtap_version(), pg_version_num(), version();'

# We want to make sure to use the NEW pg_config
export PG_CONFIG=$(find_at_path "$NEW_PATH" pg_config)
[ -x "$PG_CONFIG" ] || ( debug_ls 1 "$NEW_PATH"; die 4 "unable to find executable pg_config at $NEW_PATH" )

# When crossing certain upgrade boundaries we need to exclude some tests
# because the test functions are not available in the previous version.
int_ver() {
    local ver
    ver=$(echo $1 | tr -d .)
    # "multiply" versions less than 7.0 by 10 so that version 10.x becomes 100,
    # 11 becomes 110, etc.
    [ $ver -ge 70 ] || ver="${ver}0"
    echo $ver
}
EXCLUDE_TEST_FILES=''
add_exclude() {
    local old new
    old=$(int_ver $1)
    new=$(int_ver $2)
    shift 2
    if [ $(int_ver $OLD_VERSION) -le $old -a $(int_ver $NEW_VERSION) -ge $new ]; then
        EXCLUDE_TEST_FILES="$EXCLUDE_TEST_FILES $@"
    fi
}

add_exclude 9.1 9.2 test/sql/resultset.sql
add_exclude 9.1 9.2 test/sql/valueset.sql
add_exclude 9.1 9.2 test/sql/throwtap.sql
add_exclude 9.4 9.5 test/sql/policy.sql test/sql/throwtap.sql 
add_exclude 9.6 10 test/sql/partitions.sql

# Use this if there's a single test failing .github/workflows/test.yml that you can't figure out...
#(cd $(dirname $0)/..; pg_prove -v --pset tuples_only=1 test/sql/throwtap.sql)

export EXCLUDE_TEST_FILES
$sudo make clean
make test

if [ -n "$EXCLUDE_TEST_FILES" ]; then
    banner "Rerunning test after a reinstall due to version differences"
    echo "Excluded tests: $EXCLUDE_TEST_FILES"
    export EXCLUDED_TEST_FILES=''

    # Need to build with the new version, then install
    $sudo make install

    psql -E -c 'DROP EXTENSION pgtap; CREATE EXTENSION pgtap;'

    make test
fi