diff --git a/.gitignore b/.gitignore
index 8cc2c0c3fb..583fbd5fa3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,185 +1,187 @@
# Common
\#*
.\#*
GPATH
GRTAGS
GTAGS
TAGS
Makefile
Makefile.in
.deps
.libs
*.pc
*.pyc
*.bz2
*.tar.gz
*.rpm
*.la
*.lo
*.o
*~
*.gcda
*.gcno
# Autobuild
aclocal.m4
autoconf
autoheader
autom4te.cache/
automake
build.counter
compile
config.guess
config.log
config.status
config.sub
configure
depcomp
install-sh
include/stamp-*
libtool
libtool.m4
ltdl.m4
libltdl
ltmain.sh
missing
py-compile
/m4/argz.m4
/m4/ltargz.m4
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
/m4/lt~obsolete.m4
test-driver
ylwrap
# Configure targets
Doxyfile
cts/CTSlab.py
cts/CTSvars.py
cts/LSBDummy
cts/OCFIPraTest.py
cts/benchmark/clubench
cts/cts-coverage
cts/cts-lrmd
cts/cts-pengine
cts/cts-stonithd
cts/fence_dummy
cts/lxc_autogen.sh
extra/logrotate/pacemaker
include/config.h
include/config.h.in
include/crm_config.h
lrmd/pacemaker_remote
lrmd/pacemaker_remoted
lrmd/pacemaker_remote.service
mcp/pacemaker
mcp/pacemaker.combined.upstart
mcp/pacemaker.service
mcp/pacemaker.upstart
publican.cfg
tools/cibsecret
tools/crm_error
tools/crm_mon.service
tools/crm_mon.upstart
tools/crm_report
tools/report.common
# Build targets
*.7
*.7.xml
*.7.html
*.8
*.8.xml
*.8.html
attrd/attrd
doc/*/en-US/images/*.png
doc/*/tmp/**
doc/*/publish
cib/cib
cib/cibmon
cib/cibpipe
crmd/atest
crmd/crmd
doc/api/*
doc/Clusters_from_Scratch.txt
doc/Pacemaker_Explained.txt
doc/acls.html
doc/crm_fencing.html
doc/publican-catalog*
fencing/stonith-test
fencing/stonith_admin
fencing/stonithd
fencing/stonithd.xml
lrmd/lrmd
lrmd/lrmd_internal_ctl
lrmd/lrmd_test
mcp/pacemakerd
pengine/pengine
pengine/pengine.xml
pengine/ptest
scratch
tools/attrd_updater
tools/cibadmin
tools/crm_attribute
tools/crm_diff
tools/crm_mon
tools/crm_node
tools/crm_resource
tools/crm_shadow
tools/crm_simulate
tools/crm_verify
tools/crmadmin
tools/iso8601
tools/crm_ticket
tools/report.collector.1
xml/crm.dtd
xml/pacemaker*.rng
xml/versions.rng
doc/shared/en-US/*.xml
doc/Clusters_from_Scratch.build
doc/Clusters_from_Scratch/en-US/Ap-*.xml
doc/Clusters_from_Scratch/en-US/Ch-*.xml
doc/Pacemaker_Administration.build
doc/Pacemaker_Administration/en-US/Ch-*.xml
doc/Pacemaker_Development.build
doc/Pacemaker_Development/en-US/Ch-*.xml
doc/Pacemaker_Explained.build
doc/Pacemaker_Explained/en-US/Ch-*.xml
doc/Pacemaker_Explained/en-US/Ap-*.xml
doc/Pacemaker_Remote.build
doc/Pacemaker_Remote/en-US/Ch-*.xml
lib/gnu/libgnu.a
lib/gnu/stdalign.h
*.coverity
# Test detritus
cts/.regression.failed.diff
cts/pengine/shadow.*
+/xml/test-2/*.up
+/xml/test-2/*.up.err
# Formerly built files (helps when jumping back and forth in checkout)
/coverage.sh
/fencing/regression.py
/lrmd/regression.py
/pengine/.regression.failed.diff
/pengine/regression.core.sh
/pengine/test10/shadow.*
#Other
mock
HTML
pacemaker*.spec
coverity-*
compat_reports
.ABI-build
abi_dumps
logs
*.patch
*.diff
*.sed
*.orig
*.rej
*.swp
diff --git a/xml/cibtr-2.rng b/xml/cibtr-2.rng
new file mode 100644
index 0000000000..97218c644e
--- /dev/null
+++ b/xml/cibtr-2.rng
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
diff --git a/xml/regression.core.sh b/xml/regression.core.sh
deleted file mode 100755
index b8389bf75b..0000000000
--- a/xml/regression.core.sh
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/bin/bash
-
- # Copyright (C) 2004 Andrew Beekhof
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public
- # License as published by the Free Software Foundation; either
- # version 2 of the License, or (at your option) any later version.
- #
- # This software is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # General Public License for more details.
- #
- # You should have received a copy of the GNU General Public
- # License along with this library; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- #
-
-verbose=$1
-io_dir=../pengine/test06
-diff_opts="--ignore-all-space -u -N"
-failed=.regression.failed.diff
-# zero out the error log
-> $failed
-
-num_failed=0
-function do_test {
-
- base=$1; shift
- name=$1; shift
- input=$io_dir/${base}.xml
- output=$io_dir/${base}.upgrade.xml
- expected=$io_dir/${base}.expected.xml
-
- if [ ! -f $input ]; then
- echo "Test $name ($base)... Error (PE : input)";
- num_failed=`expr $num_failed + 1`
- return;
- fi
-
- echo "Test $base : $name";
- if [ "$create_mode" != "true" -a ! -f $expected ]; then
- echo " Error (PE : expected)";
- return;
- fi
-
- xsltproc --novalid upgrade06.xsl $input > $output
- if [ $? != 0 ]; then
- echo " * Failed (xml : xsltproc)";
- num_failed=`expr $num_failed + 1`
- fi
-
- if [ ! -s $output ]; then
- echo " Error (xml : no conversion)";
- num_failed=`expr $num_failed + 1`
- rm $output
- return;
- fi
-
- xmllint --relaxng pacemaker.rng $output > /dev/null 2>&1
-
- if [ $? != 0 ]; then
- echo " * Failed (xml : xmllint)";
- num_failed=`expr $num_failed + 1`
- xmllint --relaxng pacemaker.rng $output > /dev/null
- cat -n $output
- fi
-
- # Now convert again, this time stripping the auto-id's so that the diffs are useful
- xsltproc --novalid upgrade06.xsl $input | sed s/\\.id[0-9]*//g | sed s/nvpair.meta.auto-[0-9]*/nvpair/g > $output
- if [ "$create_mode" = "true" ]; then
- cp $output $expected
- fi
-
- diff $diff_opts $expected $output >/dev/null
- rc2=$?
- if [ $rc2 != 0 ]; then
- echo " * Failed";
- diff $diff_opts $expected $output 2>/dev/null >> $failed
- echo "" >> $failed
- num_failed=`expr $num_failed + 1`
- else
- rm $output
- fi
-}
-
-function test_results {
- if [ $num_failed != 0 ]; then
- if [ -s $failed ]; then
- if [ "$verbose" = "-v" ]; then
- echo "Results of $num_failed failed tests...."
- less $failed
- else
- echo "Results of $num_failed failed tests are in $failed...."
- echo "Use $0 -v to display them automatically."
- fi
- else
- echo "$num_failed tests failed (no diff results)"
- rm $failed
- fi
- fi
-}
-
diff --git a/xml/regression.sh b/xml/regression.sh
index cc435ef703..283345a153 100755
--- a/xml/regression.sh
+++ b/xml/regression.sh
@@ -1,288 +1,306 @@
-#!/bin/bash
-
- # Copyright (C) 2004 Andrew Beekhof
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public
- # License as published by the Free Software Foundation; either
- # version 2 of the License, or (at your option) any later version.
- #
- # This software is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # General Public License for more details.
- #
- # You should have received a copy of the GNU General Public
- # License along with this library; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- #
-
-. regression.core.sh
-create_mode="true"
-echo Generating test outputs for these tests...
-# do_test
-echo Done.
-echo ""
-
-echo Performing the following tests...
-create_mode="false"
-
-echo ""
-do_test simple1 "Offline "
-do_test simple2 "Start "
-do_test simple3 "Start 2 "
-do_test simple4 "Start Failed"
-do_test simple6 "Stop Start "
-do_test simple7 "Shutdown "
-#do_test simple8 "Stonith "
-#do_test simple9 "Lower version"
-#do_test simple10 "Higher version"
-do_test simple11 "Priority (ne)"
-do_test simple12 "Priority (eq)"
-do_test simple8 "Stickiness"
-
-echo ""
-do_test params-0 "Params: No change"
-do_test params-1 "Params: Changed"
-do_test params-2 "Params: Resource definition"
-do_test params-4 "Params: Reload"
-do_test novell-251689 "Resource definition change + target_role=stopped"
-
-echo ""
-do_test orphan-0 "Orphan ignore"
-do_test orphan-1 "Orphan stop"
-
-echo ""
-do_test target-0 "Target Role : baseline"
-do_test target-1 "Target Role : test"
-
-echo ""
-do_test date-1 "Dates" -d "2005-020"
-do_test date-2 "Date Spec - Pass" -d "2005-020T12:30"
-do_test date-3 "Date Spec - Fail" -d "2005-020T11:30"
-do_test probe-0 "Probe (anon clone)"
-do_test probe-1 "Pending Probe"
-do_test standby "Standby"
-do_test comments "Comments"
-
-echo ""
-do_test rsc_dep1 "Must not "
-do_test rsc_dep3 "Must "
-do_test rsc_dep5 "Must not 3 "
-do_test rsc_dep7 "Must 3 "
-do_test rsc_dep10 "Must (but cant)"
-do_test rsc_dep2 "Must (running) "
-do_test rsc_dep8 "Must (running : alt) "
-do_test rsc_dep4 "Must (running + move)"
-do_test asymmetric "Asymmetric - require explicit location constraints"
-
-echo ""
-do_test order1 "Order start 1 "
-do_test order2 "Order start 2 "
-do_test order3 "Order stop "
-do_test order4 "Order (multiple) "
-do_test order5 "Order (move) "
-do_test order6 "Order (move w/ restart) "
-do_test order7 "Order (mandatory) "
-do_test order-optional "Order (score=0) "
-do_test order-required "Order (score=INFINITY) "
-
-echo ""
-do_test coloc-loop "Colocation - loop"
-do_test coloc-many-one "Colocation - many-to-one"
-do_test coloc-list "Colocation - many-to-one with list"
-do_test coloc-group "Colocation - groups"
-do_test coloc-slave-anti "Anti-colocation with slave shouldn't prevent master colocation"
-
-#echo ""
-#do_test agent1 "version: lt (empty)"
-#do_test agent2 "version: eq "
-#do_test agent3 "version: gt "
-
-echo ""
-do_test attrs1 "string: eq (and) "
-do_test attrs2 "string: lt / gt (and)"
-do_test attrs3 "string: ne (or) "
-do_test attrs4 "string: exists "
-do_test attrs5 "string: not_exists "
-do_test attrs6 "is_dc: true "
-do_test attrs7 "is_dc: false "
-do_test attrs8 "score_attribute "
-
-echo ""
-do_test mon-rsc-1 "Schedule Monitor - start"
-do_test mon-rsc-2 "Schedule Monitor - move "
-do_test mon-rsc-3 "Schedule Monitor - pending start "
-do_test mon-rsc-4 "Schedule Monitor - move/pending start"
-
-echo ""
-do_test rec-rsc-0 "Resource Recover - no start "
-do_test rec-rsc-1 "Resource Recover - start "
-do_test rec-rsc-2 "Resource Recover - monitor "
-do_test rec-rsc-3 "Resource Recover - stop - ignore"
-do_test rec-rsc-4 "Resource Recover - stop - block "
-do_test rec-rsc-5 "Resource Recover - stop - fence "
-do_test rec-rsc-6 "Resource Recover - multiple - restart"
-do_test rec-rsc-7 "Resource Recover - multiple - stop "
-do_test rec-rsc-8 "Resource Recover - multiple - block "
-do_test rec-rsc-9 "Resource Recover - group/group"
-
-echo ""
-do_test quorum-1 "No quorum - ignore"
-do_test quorum-2 "No quorum - freeze"
-do_test quorum-3 "No quorum - stop "
-do_test quorum-4 "No quorum - start anyway"
-do_test quorum-5 "No quorum - start anyway (group)"
-do_test quorum-6 "No quorum - start anyway (clone)"
-
-echo ""
-do_test rec-node-1 "Node Recover - Startup - no fence"
-do_test rec-node-2 "Node Recover - Startup - fence "
-do_test rec-node-3 "Node Recover - HA down - no fence"
-do_test rec-node-4 "Node Recover - HA down - fence "
-do_test rec-node-5 "Node Recover - CRM down - no fence"
-do_test rec-node-6 "Node Recover - CRM down - fence "
-do_test rec-node-7 "Node Recover - no quorum - ignore "
-do_test rec-node-8 "Node Recover - no quorum - freeze "
-do_test rec-node-9 "Node Recover - no quorum - stop "
-do_test rec-node-10 "Node Recover - no quorum - stop w/fence"
-do_test rec-node-11 "Node Recover - CRM down w/ group - fence "
-do_test rec-node-12 "Node Recover - nothing active - fence "
-do_test rec-node-13 "Node Recover - failed resource + shutdown - fence "
-do_test rec-node-15 "Node Recover - unknown lrm section"
-do_test rec-node-14 "Serialize all stonith's"
-
-echo ""
-do_test multi1 "Multiple Active (stop/start)"
-
-echo ""
-do_test migrate-1 "Migrate (migrate)"
-do_test migrate-2 "Migrate (stable)"
-do_test migrate-3 "Migrate (failed migrate_to)"
-do_test migrate-4 "Migrate (failed migrate_from)"
-do_test novell-252693 "Migration in a stopping stack"
-do_test novell-252693-2 "Migration in a starting stack"
-do_test novell-252693-3 "Non-Migration in a starting and stopping stack"
-do_test bug-1820 "Migration in a group"
-do_test bug-1820-1 "Non-migration in a group"
-
-#echo ""
-#do_test complex1 "Complex "
-
-echo ""
-do_test group1 "Group "
-do_test group2 "Group + Native "
-do_test group3 "Group + Group "
-do_test group4 "Group + Native (nothing)"
-do_test group5 "Group + Native (move) "
-do_test group6 "Group + Group (move) "
-do_test group7 "Group colocation"
-do_test group13 "Group colocation (cant run)"
-do_test group8 "Group anti-colocation"
-do_test group9 "Group recovery"
-do_test group10 "Group partial recovery"
-do_test group11 "Group target_role"
-do_test group14 "Group stop (graph terminated)"
-do_test group15 "-ve group colocation"
-do_test bug-1573 "Partial stop of a group with two children"
-do_test bug-1718 "Mandatory group ordering - Stop group_FUN"
-
-echo ""
-do_test clone-anon-probe-1 "Probe the correct (anonymous) clone instance for each node"
-do_test clone-anon-probe-2 "Avoid needless re-probing of anonymous clones"
-do_test inc0 "Incarnation start"
-do_test inc1 "Incarnation start order"
-do_test inc2 "Incarnation silent restart, stop, move"
-do_test inc3 "Inter-incarnation ordering, silent restart, stop, move"
-do_test inc4 "Inter-incarnation ordering, silent restart, stop, move (ordered)"
-do_test inc5 "Inter-incarnation ordering, silent restart, stop, move (restart 1)"
-do_test inc6 "Inter-incarnation ordering, silent restart, stop, move (restart 2)"
-do_test inc7 "Clone colocation"
-do_test inc8 "Clone anti-colocation"
-do_test inc9 "Non-unique clone"
-do_test inc10 "Non-unique clone (stop)"
-do_test inc11 "Primitive colocation with clones"
-do_test inc12 "Clone shutdown"
-do_test cloned-group "Make sure only the correct number of cloned groups are started"
-do_test clone-no-shuffle "Don't prioritize allocation of instances that must be moved"
-
-echo ""
-do_test master-0 "Stopped -> Slave"
-do_test master-1 "Stopped -> Promote"
-do_test master-2 "Stopped -> Promote : notify"
-do_test master-3 "Stopped -> Promote : master location"
-do_test master-4 "Started -> Promote : master location"
-do_test master-5 "Promoted -> Promoted"
-do_test master-6 "Promoted -> Promoted (2)"
-do_test master-7 "Promoted -> Fenced"
-do_test master-8 "Promoted -> Fenced -> Moved"
-do_test master-9 "Stopped + Promotable + No quorum"
-do_test master-10 "Stopped -> Promotable : notify with monitor"
-do_test master-11 "Stopped -> Promote : colocation"
-do_test novell-239082 "Demote/Promote ordering"
-do_test novell-239087 "Stable master placement"
-do_test master-12 "Promotion based solely on rsc_location constraints"
-do_test master-13 "Include preferences of colocated resources when placing master"
-do_test master-demote "Ordering when actions depends on demoting a slave resource"
-do_test master-ordering "Prevent resources from starting that need a master"
-do_test bug-1765 "Master-Master Colocation (dont stop the slaves)"
-do_test master-group "Promotion of cloned groups"
-do_test bug-lf-1852 "Don't shuffle master/slave instances unnecessarily"
-do_test master-failed-demote "Don't retry failed demote actions"
-do_test master-failed-demote-2 "Don't retry failed demote actions (notify=false)"
-do_test master-depend "Ensure resources that depend on the master don't get allocated until the master does"
-
-echo ""
-do_test managed-0 "Managed (reference)"
-do_test managed-1 "Not managed - down "
-do_test managed-2 "Not managed - up "
-
-echo ""
-do_test interleave-0 "Interleave (reference)"
-do_test interleave-1 "coloc - not interleaved"
-do_test interleave-2 "coloc - interleaved "
-do_test interleave-3 "coloc - interleaved (2)"
-do_test interleave-pseudo-stop "Interleaved clone during stonith"
-do_test interleave-stop "Interleaved clone during stop"
-do_test interleave-restart "Interleaved clone during dependency restart"
-
-echo ""
-do_test notify-0 "Notify reference"
-do_test notify-1 "Notify simple"
-do_test notify-2 "Notify simple, confirm"
-do_test notify-3 "Notify move, confirm"
-do_test novell-239079 "Notification priority"
-#do_test notify-2 "Notify - 764"
-
-echo ""
-do_test 594 "OSDL #594"
-do_test 662 "OSDL #662"
-do_test 696 "OSDL #696"
-do_test 726 "OSDL #726"
-do_test 735 "OSDL #735"
-do_test 764 "OSDL #764"
-do_test 797 "OSDL #797"
-do_test 829 "OSDL #829"
-do_test 994 "OSDL #994"
-do_test 994-2 "OSDL #994 - with a dependent resource"
-do_test 1360 "OSDL #1360 - Clone stickiness"
-do_test 1484 "OSDL #1484 - on_fail=stop"
-do_test 1494 "OSDL #1494 - Clone stability"
-do_test unrunnable-1 "Unrunnable"
-do_test stonith-0 "Stonith loop - 1"
-do_test stonith-1 "Stonith loop - 2"
-do_test stonith-2 "Stonith loop - 3"
-do_test bug-1572-1 "Recovery of groups depending on master/slave"
-do_test bug-1572-2 "Recovery of groups depending on master/slave when the master is never re-promoted"
-do_test bug-1685 "Depends-on-master ordering"
-do_test bug-1822 "Don't promote partially active groups"
-do_test bug-pm-11 "New resource added to a m/s group"
-do_test bug-pm-12 "Recover only the failed portion of a cloned group"
-do_test bug-n-387749 "Don't shuffle clone instances"
-do_test bug-n-385265 "Don't ignore the failure stickiness of group children - resource_idvscommon should stay stopped"
-do_test bug-n-385265-2 "Ensure groups are migrated instead of remaining partially active on the current node"
-do_test bug-lf-1920 "Correctly handle probes that find active resources"
-
-echo ""
-
-test_results
+#!/bin/sh
+# Copyright 2018 Red Hat, Inc.
+# Author: Jan Pokorny
+# Part of pacemaker project
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+set -eu
+DIFF=${DIFF:-diff}
+DIFFOPTS=${DIFFOPTS:--u}
+DIFFPAGER=${DIFFPAGER:-less -LRX}
+tests=
+
+#
+# commons
+#
+
+emit_result() {
+ _er_howmany=${1:?} # how many errors (0/anything else incl. strings)
+ _er_subject=${2:?}
+ _er_prefix=${3-}
+
+ test -z "${_er_prefix}" || _er_prefix="${_er_prefix}: "
+
+ if test "${_er_howmany}" = 0; then
+ printf "%s%s finished OK\n" "${_er_prefix}" "${_er_subject}"
+ else
+ printf "%s%s encountered ${_er_howmany} errors\n" \
+ "${_er_prefix}" "${_er_subject}"
+ fi
+}
+
+emit_error() {
+ _ee_msg=${1:?}
+ printf "%s\n" "${_ee_msg}" >&2
+}
+
+# returns 1 + floor of base 2 logaritm for _lo0r_i in 1...255,
+# or 0 for _lo0r_i = 0
+log2_or_0_return() {
+ _lo0r_i=${1:?}
+ return $(((!(_lo0r_i >> 1) && _lo0r_i) * 1 \
+ + (!(_lo0r_i >> 2) && _lo0r_i & (1 << 1)) * 2 \
+ + (!(_lo0r_i >> 3) && _lo0r_i & (1 << 2)) * 3 \
+ + (!(_lo0r_i >> 4) && _lo0r_i & (1 << 3)) * 4 \
+ + (!(_lo0r_i >> 5) && _lo0r_i & (1 << 4)) * 5 \
+ + (!(_lo0r_i >> 6) && _lo0r_i & (1 << 5)) * 6 \
+ + (!(_lo0r_i >> 7) && _lo0r_i & (1 << 6)) * 7 \
+ + !!(_lo0r_i >> 7) * 7 ))
+}
+
+# rough addition of two base 2 logarithms
+log2_or_0_add() {
+ _lo0a_op1=${1:?}
+ _lo0a_op2=${2:?}
+
+ if test ${_lo0a_op1} -gt ${_lo0a_op2}; then
+ return ${_lo0a_op1}
+ elif test ${_lo0a_op2} -gt ${_lo0a_op1}; then
+ return ${_lo0a_op2}
+ elif test ${_lo0a_op1} -gt 0; then
+ return $((_lo0a_op1 + 1))
+ else
+ return ${_lo0a_op1}
+ fi
+}
+
+#
+# test phases
+#
+
+# stdin: input file per line
+test_cleaner() {
+ while read _tc_origin; do
+ rm -f ${_tc_origin%.*}.up ${_tc_origin%.*}.up.err
+ done
+}
+
+test_selfcheck() {
+ _tsc_template=
+ _tsc_validator=
+
+ while test $# -gt 0; do
+ case "$1" in
+ -o=*) _tsc_template="${1#-o=}";;
+ esac
+ shift
+ done
+ _tsc_validator="${_tsc_template:?}"
+ _tsc_validator="xslt_cibtr-${_tsc_validator%%.*}.rng"
+ _tsc_template="upgrade-${_tsc_template}.xsl"
+
+ xmllint --noout --relaxng "${_tsc_validator}" "${_tsc_template}"
+}
+
+# stdout: filename of the transformed file
+test_runner_upgrade() {
+ _tru_template=${1:?}
+ _tru_source=${2:?} # filename
+ _tru_mode=${3:?} # extra modes wrt. "referential" outcome, see below
+
+ _tru_ref="${_tru_source%.*}.ref"
+ { test "${_tru_mode}" -ne 0 || test -f "${_tru_ref}.err"; } \
+ && _tru_ref_err="${_tru_ref}.err" \
+ || _tru_ref_err=/dev/null
+ _tru_target="${_tru_source%.*}.up"
+ _tru_target_err="${_tru_target}.err"
+
+ xsltproc "${_tru_template}" "${_tru_source}" \
+ > "${_tru_target}" 2> "${_tru_target_err}" \
+ || { _tru_ref=$?; echo "${_tru_target_err}"; return ${_tru_ref}; }
+
+ if test "${_tru_mode}" -ne 0; then
+ if test $((_tru_mode & (1 << 0))) -ne 0; then
+ cp -a "${_tru_target}" "${_tru_ref}"
+ cp -a "${_tru_target_err}" "${_tru_ref_err}"
+ fi
+ if test $((_tru_mode & (1 << 1))) -ne 0; then
+ "${DIFF}" ${DIFFOPTS} "${_tru_source}" "${_tru_ref}" \
+ | ${DIFFPAGER} >&2
+ if test $? -ne 0; then
+ printf "\npager failure\n" >&2
+ return 1
+ fi
+ printf '\nIs comparison OK? ' >&2
+ read _tru_answer &2; return 1;;
+ esac
+ fi
+ elif test -f "${_tru_ref}" && test -f "${_tru_ref_err}"; then
+ "${DIFF}" ${DIFFOPTS} "${_tru_ref}" "${_tru_target}" >&2 \
+ && "${DIFF}" ${DIFFOPTS} "${_tru_ref_err}" "${_tru_target_err}" >&2
+ if test $? -ne 0; then
+ emit_error "Outputs differ from referential ones"
+ echo "/dev/null"
+ return 1
+ fi
+ else
+ emit_error "Referential file(s) missing: ${_tru_ref}"
+ echo "/dev/null"
+ return 1
+ fi
+
+ echo "${_tru_target}"
+}
+
+test_runner_validate() {
+ _trv_schema=${1:?}
+ _trv_target=${2:?} # filename
+
+ if ! xmllint --noout --relaxng "${_trv_schema}" "${_trv_target}" \
+ 2>/dev/null; then
+ xmllint --noout --relaxng "${_trv_schema}" "${_trv_target}"
+ fi
+}
+
+# -g ... request generating "referential" outcomes
+# -o= ... which conventional version to deem as the transform origin
+# -t= ... which conventional version to deem as the transform target
+# -D
+# -G ... see usage
+# stdin: input file per line
+test_runner() {
+ _tr_mode=0
+ _tr_ret=0
+ _tr_schema_o=
+ _tr_schema_t=
+ _tr_target=
+ _tr_template=
+
+ while test $# -gt 0; do
+ case "$1" in
+ -o=*) _tr_template="upgrade-${1#-o=}.xsl"
+ _tr_schema_o="pacemaker-${1#-o=}.rng";;
+ -t=*) _tr_schema_t="pacemaker-${1#-t=}.rng";;
+ -G) _tr_mode=$((_tr_mode | (1 << 0)));;
+ -D) _tr_mode=$((_tr_mode | (1 << 1)));;
+ esac
+ shift
+ done
+
+ if ! test -f "${_tr_schema_o:?}" || ! test -f "${_tr_schema_t:?}"; then
+ emit_error "Origin and/or target schema missing, rerun make"
+ return 1
+ fi
+
+ while read _tr_origin; do
+ printf '%-60s' "${_tr_origin}... "
+
+ # pre-validate
+ if ! test_runner_validate "${_tr_schema_o}" "${_tr_origin}"; then
+ _tr_ret=$((_tr_ret + 1)); echo "E:pre-validate"; continue
+ fi
+
+ # upgrade
+ if ! _tr_target=$(test_runner_upgrade "${_tr_template}" \
+ "${_tr_origin}" "${_tr_mode}"); then
+ _tr_ret=$((_tr_ret + 1));
+ test -n "${_tr_target}" || break
+ echo "E:upgrade"
+ test -s "${_tr_target}" \
+ && { echo ---; cat "${_tr_target}" || :; echo ---; }
+ continue
+ fi
+
+ # post-validate
+ if ! test_runner_validate "${_tr_schema_t}" "${_tr_target}"; then
+ _tr_ret=$((_tr_ret + 1)); echo "E:post-validate"; continue
+ fi
+
+ echo "OK"
+ done
+
+ log2_or_0_return ${_tr_ret}
+}
+
+#
+# particular test variations
+#
+
+test_2to3() {
+ find test-2 -name '*.xml' -print | env LC_ALL=C sort \
+ | { case " $* " in
+ *\ -C\ *) test_cleaner;;
+ *\ -S\ *) test_selfcheck -o=2.10;;
+ *) test_runner -o=2.10 -t=3.0 "$@" || return $?;;
+ esac; }
+}
+tests="${tests} test_2to3"
+
+#
+# "framework"
+#
+
+# option-likes ... options to be passed down
+# argument-likes ... drives a test selection
+test_suite() {
+ _ts_pass=
+ _ts_global_ret=0
+ _ts_ret=0
+ _ts_select=@
+
+ while test $# -gt 0; do
+ case "$1" in
+ -*) _ts_pass="${_ts_pass} $1";;
+ *) _ts_select="${_ts_select}@$1";;
+ esac
+ shift
+ done
+ _ts_select="${_ts_select}@"
+
+ for _ts_test in ${tests}; do
+ if test "${_ts_select}" != @@; then
+ case "${_ts_test}" in
+ *@${_ts_select}@*) ;; # jump through
+ *) break;;
+ esac
+ fi
+ "${_ts_test}" ${_ts_pass} || _ts_ret=$?
+ test ${_ts_ret} = 0 \
+ && emit_result ${_ts_ret} "${_ts_test}" \
+ || emit_result "at least 2^$((_ts_ret - 1))" "${_ts_test}"
+ log2_or_0_add ${_ts_global_ret} ${_ts_ret}
+ _ts_global_ret=$?
+ done
+
+ return ${_ts_global_ret}
+}
+
+# NOTE: big letters are dedicated for per-test-set behaviour,
+# small ones for generic/global behaviour
+usage() {
+ printf '%s\n %s\n %s\n %s\n %s\n' \
+ "usage: $0 [-{C,G,S}]* [{${tests## }}*]" \
+ "- use '-C' to only cleanup ephemeral byproducts" \
+ "- use '-D' to review originals vs. \"referential\" outcomes" \
+ "- use '-G' to generate \"referential\" outcomes" \
+ "- use '-S' for template self-check (requires net access)"
+}
+
+main() {
+ _main_pass=
+ _main_bailout=0
+ _main_ret=0
+
+ while test $# -gt 0; do
+ case "$1" in
+ -h) usage; exit;;
+ -C) _main_pass="${_main_pass} $1"; _main_bailout=1;;
+ -S) _main_pass="${_main_pass} $1"; _main_bailout=1;;
+ *) _main_pass="${_main_pass} $1";;
+ esac
+ shift
+ done
+
+ test_suite ${_main_pass} || _main_ret=$?
+ test ${_main_bailout} -eq 1 && return ${_main_ret} \
+ || test_suite -C ${_main_pass} >/dev/null
+ test ${_main_ret} = 0 && emit_result ${_main_ret} "Overall suite" \
+ || emit_result "at least 2^$((_main_ret - 1))" "Overall suite"
+
+ return ${_main_ret}
+}
+
+main "$@"
diff --git a/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref
new file mode 100644
index 0000000000..a4a4a23897
--- /dev/null
+++ b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref.err b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref.err
new file mode 100644
index 0000000000..95985d568f
--- /dev/null
+++ b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.ref.err
@@ -0,0 +1,2 @@
+Constraints-colocation: colocation-addr-httpd: dropping score-attribute
+Constraints-colocation: ... was actually never in effect
diff --git a/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.xml b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.xml
new file mode 100644
index 0000000000..699d3d0bd8
--- /dev/null
+++ b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xml/upgrade-1.3.xsl b/xml/upgrade-1.3.xsl
index 039c4219e3..9ea56a2513 100644
--- a/xml/upgrade-1.3.xsl
+++ b/xml/upgrade-1.3.xsl
@@ -1,95 +1,107 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
ACLs: @attribute cannot accompany @ref for upgrade-1.3.xsl purposes, ignoring
ACLs: @attribute (with @tag) handling generalized a bit for upgrade-1.3.xsl purposes
ACLs: @attribute (with @xpath) handling generalized a bit for upgrade-1.3.xsl purposes
-
+
diff --git a/xml/upgrade-2.10.xsl b/xml/upgrade-2.10.xsl
index 976db9180d..d1e7f4725e 100644
--- a/xml/upgrade-2.10.xsl
+++ b/xml/upgrade-2.10.xsl
@@ -1,10 +1,136 @@
-
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xml/xslt_cibtr-2.rng b/xml/xslt_cibtr-2.rng
new file mode 100644
index 0000000000..6dbe775151
--- /dev/null
+++ b/xml/xslt_cibtr-2.rng
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+