#    rpmbuild.at: test rpmbuild
#
#    Copyright (C) 2007  Ralf Corsépius <corsepiu@fedoraproject.org>
#
#    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 program 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 program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

AT_BANNER([RPM build])

# ------------------------------
# Check if rpmbuild -ba *.spec works
AT_SETUP([rpmbuild -ba *.spec])
AT_KEYWORDS([build])
AT_CHECK([
rm -rf ${TOPDIR}
AS_MKDIR_P(${TOPDIR}/SOURCES)

cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES

run rpmbuild \
  -ba "${abs_srcdir}"/data/SPECS/hello.spec
],
[0],
[ignore],
[ignore])
AT_CLEANUP

# ------------------------------
# Check if rpmbuild --rebuild *.src.rpm works
AT_SETUP([rpmbuild --rebuild])
AT_KEYWORDS([build])
AT_CHECK([
rm -rf ${TOPDIR}

run rpmbuild \
  --rebuild "${abs_srcdir}"/data/SRPMS/hello-1.0-1.src.rpm
],
[0],
[ignore],
[ignore])
AT_CLEANUP

# ------------------------------
# Check if tar unpacking works
AT_SETUP([rpmbuild -tb <tar with bad spec>])
AT_KEYWORDS([build])
AT_CHECK([
rm -rf ${TOPDIR}

run rpmbuild \
  -tb "${RPMDATA}/SOURCES/hello-1.0.tar.gz"
],
[1],
[ignore],
[error: line 5: Unknown tag: Serial:	1
])
AT_CLEANUP

# ------------------------------
# Check if tar build works
# TODO: test that the rpms are actually created...
AT_SETUP([rpmbuild -tb])
AT_KEYWORDS([build])
AT_CHECK([
rm -rf ${TOPDIR}

run rpmbuild \
  -ta "${RPMDATA}/SOURCES/hello-2.0.tar.gz"
],
[0],
[ignore],
[ignore])
AT_CLEANUP

# ------------------------------
# %attr/%defattr tests
AT_SETUP([rpmbuild %attr and %defattr])
AT_KEYWORDS([build])
AT_CHECK([[
rm -rf ${TOPDIR}

runroot rpmbuild \
  -bb --quiet /data/SPECS/attrtest.spec

runroot rpm -qp --qf \
  "\n[%{filemodes:perms} %-8{fileusername} %-8{filegroupname} %{filenames}\n]"\
  /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm
]],
[0],
[
drwx------ root     root     /a/dir
-r-------- root     root     /a/file
drwx------ daemon   adm      /b/dir
-r-------- daemon   adm      /b/file
drwxr-x--- root     adm      /c/dir
-rw-r----- daemon   root     /c/file
drwxr-x--x daemon   bin      /d/dir
-rw-r--r-- bin      daemon   /d/file
drwx------ foo      bar      /e/dir
-r-------- foo      bar      /e/file
drwxrwx--- bar      foo      /f/dir
-rw-rw---- bar      foo      /f/file
drwx------ adm      foo      /g/dir
-r-------- bar      adm      /g/file
drwxr-xr-x foo      bar      /h/dir
-rw-r--r-- foo      bar      /h/file
drwxr-x--- adm      root     /i/dir
-rwsr-xr-x root     adm      /i/file
drwxrwxrwx zoot     zoot     /j/dir
--w--w--w- zoot     zoot     /j/file
],
[])
AT_CLEANUP

# ------------------------------
# hardlink tests
AT_SETUP([rpmbuild hardlink])
AT_KEYWORDS([build])
AT_CHECK([
RPMDB_CLEAR
RPMDB_INIT
rm -rf ${TOPDIR}

runroot rpmbuild \
  -bb --quiet /data/SPECS/hlinktest.spec

runroot rpm -i /build/RPMS/noarch/hlinktest-1.0-1.noarch.rpm

runroot rpm -q --qf "[[%{filenlinks} %{filenames}\n]]%{longsize}\n" hlinktest
runroot rpm -V --nouser --nogroup hlinktest
ls -i "${RPMTEST}"/foo/hello* | awk {'print $1'} | sort -u | wc -l

],
[0],
[2 /foo/aaaa
1 /foo/copyllo
4 /foo/hello
4 /foo/hello-bar
4 /foo/hello-foo
4 /foo/hello-world
2 /foo/zzzz
87
1
],
[])
AT_CLEANUP

AT_SETUP([rpmbuild glob])
AT_KEYWORDS([build])
AT_CHECK([
RPMDB_CLEAR
RPMDB_INIT
rm -rf ${TOPDIR}

runroot rpmbuild -bb --quiet /data/SPECS/globtest.spec
runroot rpm -qp \
	--qf "[[%{filemodes:perms} %{filenames}\n]]" \
	/build/RPMS/noarch/globtest-1.0-1.noarch.rpm
],
[0],
[-rw-r--r-- /opt/globtest/baf
drwxr-xr-x /opt/globtest/bang
-rw-r--r-- /opt/globtest/bif
drwxr-xr-x /opt/globtest/bing
drwxr-xr-x /opt/globtest/bong
drwxr-xr-x /opt/globtest/foo
-rw-r--r-- /opt/globtest/foo/one
-rw-r--r-- /opt/globtest/foo/three
-rw-r--r-- /opt/globtest/foo/two
lrwxrwxrwx /opt/globtest/linkbad
lrwxrwxrwx /opt/globtest/linkgood
-rw-r--r-- /opt/globtest/weird%name
-rw-r--r-- /opt/globtest/zab
-rw-r--r-- /opt/globtest/zeb
-rw-r--r-- /opt/globtest/zib
],
[])
AT_CLEANUP

AT_SETUP([rpmbuild prefixpostfix])
AT_KEYWORDS([build])
AT_CHECK([
RPMDB_CLEAR
RPMDB_INIT
rm -rf ${TOPDIR}

runroot rpmbuild -bb --quiet \
	/data/SPECS/prefixtest.spec
runroot rpm -qp \
	--qf "[[%{filemodes:perms} %{filenames}\n]]" \
	/build/RPMS/noarch/prefixtest-1.0-1.noarch.rpm
],
[0],
[-rw-r--r-- /opt/prefixtest/ba
drwxr-xr-x /opt/prefixtest/ban
-rw-r--r-- /opt/prefixtest/bi
drwxr-xr-x /opt/prefixtest/bin
drwxr-xr-x /opt/prefixtest/bon
drwxr-xr-x /opt/prefixtest/foo
-rw-r--r-- /opt/prefixtest/foo/one
-rw-r--r-- /opt/prefixtest/foo/three
-rw-r--r-- /opt/prefixtest/foo/two
lrwxrwxrwx /opt/prefixtest/linkbad
lrwxrwxrwx /opt/prefixtest/linkgood
-rw-r--r-- /opt/prefixtest/weird%name
-rw-r--r-- /opt/prefixtest/zab
-rw-r--r-- /opt/prefixtest/zeb
-rw-r--r-- /opt/prefixtest/zib
],
[])
AT_CLEANUP

# ------------------------------
# Check if weak and reverse requires can be built
AT_SETUP([Weak and reverse requires])
AT_KEYWORDS([build])
AT_CHECK([

runroot rpmbuild -bb --quiet \
	--define "pkg weakdeps" \
	--define "recs foo > 1.2.3" \
	--define "sugs bar >= 0.1.2" \
	--define "sups baz" \
	--define "ens zap = 3" \
	  /data/SPECS/deptest.spec

runroot rpm -qp --recommends /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm
runroot rpm -qp --suggests /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm
runroot rpm -qp --supplements /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm
runroot rpm -qp --enhances /build/RPMS/noarch/deptest-weakdeps-1.0-1.noarch.rpm
],
[0],
[foo > 1.2.3
bar >= 0.1.2
baz
zap = 3
],
[ignore])
AT_CLEANUP

# ------------------------------
# Test BuildRequire functionality
AT_SETUP([Build requires])
AT_KEYWORDS([build])
AT_CHECK([

runroot rpmbuild -bb --quiet \
		--define "pkg buildreq" \
		--define "buildreqs foo > 1.2.3" \
		/data/SPECS/deptest.spec
],
[1],
[],
[error: Failed build dependencies:
	foo > 1.2.3 is needed by deptest-buildreq-1.0-1.noarch
])
AT_CLEANUP

# ------------------------------
# Test spec query functionality
AT_SETUP([rpmspec query 1])
AT_KEYWORDS([build])
AT_CHECK([

runroot rpmspec -q \
		--define "pkg dep" \
		--define "reqs foo > 1.2.3 bar <= 2.3" \
		--requires \
		/data/SPECS/deptest.spec
],
[0],
[bar <= 2.3
foo > 1.2.3
],
[])

AT_CLEANUP

# ------------------------------
# archive sanity check
AT_SETUP([rpmbuild archive sanity])
AT_KEYWORDS([build])
AT_CHECK([
rm -rf ${TOPDIR}

runroot rpmbuild \
  -bb --quiet /data/SPECS/attrtest.spec

runroot rpm2cpio \
  /build/RPMS/noarch/attrtest-1.0-1.noarch.rpm > /tmp/attrtest.cpio
],
[0],
[],
[])
AT_CLEANUP

# ------------------------------
# Check if rpmbuild creates the minisymtab section in the main hello binary
AT_SETUP([rpmbuild debuginfo minisymtab])
AT_KEYWORDS([build] [debuginfo])
AT_CHECK([
rm -rf ${TOPDIR}

# Use macros.debug to generate a debuginfo package.
export CFLAGS="-g"
run rpmbuild --quiet \
  --macros=${abs_top_builddir}/macros:${top_srcdir}/macros.debug \
  --rcfile=${abs_top_builddir}/rpmrc \
  --rebuild "${abs_srcdir}"/data/SRPMS/hello-1.0-1.src.rpm

# Extract the main package and inspect the hello binary
# It should contain .gnu_debugdata, but not the full .symtab
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm | cpio -diu
test -f ./usr/local/bin/hello || exit 1
readelf -S ./usr/local/bin/hello |\
   grep -q .gnu_debugdata; test $? == 0 || exit 1
readelf -S ./usr/local/bin/hello \
  | grep -q .symtab; test $? == 1 || exit 1

# And the opposite for the debuginfo package
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \
  | cpio -diu
test -f ./usr/lib/debug/usr/local/bin/hello*.debug || exit 1
readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
  | grep -q .gnu_debugdata; test $? == 1 || exit 1
readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
  | grep -q .symtab; test $? == 0 || exit 1
],
[0],
[],
[ignore])
AT_CLEANUP

# ------------------------------
# Check if rpmbuild doesn't create the minisymtab section if we keep symtab
# Some package might want to use strip -g to keep the symbol table and only
# but the debug symbols/info in the debuginfo package.
AT_SETUP([rpmbuild debuginfo minisymtab strip -g])
AT_KEYWORDS([build] [debuginfo])
AT_CHECK([
rm -rf ${TOPDIR}

# Use macros.debug to generate a debuginfo package.
export CFLAGS="-g"
run rpmbuild --quiet \
  --macros=${abs_top_builddir}/macros:${top_srcdir}/macros.debug \
  --rcfile=${abs_top_builddir}/rpmrc \
  --define="_find_debuginfo_opts -g" \
  --rebuild "${abs_srcdir}"/data/SRPMS/hello-1.0-1.src.rpm

# Extract the main package and inspect the hello binary
# It should contain .symtab (because of strip -g), so doesn't .gnu_debugdata.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-1.0-1.*.rpm | cpio -diu
test -f ./usr/local/bin/hello || exit 1
readelf -S ./usr/local/bin/hello \
  | grep -q .gnu_debugdata; test $? == 1 || exit 1
readelf -S ./usr/local/bin/hello \
  | grep -q .symtab; test $? == 0 || exit 1

# The debuginfo package should contain neither. The .symtab is NOBITS.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello-debuginfo-1.0-1.*.rpm \
  | cpio -diu
test -f ./usr/lib/debug/usr/local/bin/hello*.debug || exit 1
readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
  | grep -q .gnu_debugdata; test $? == 1 || exit 1
readelf -S ./usr/lib/debug/usr/local/bin/hello*.debug \
  | grep .symtab | grep -q NOBITS; test $? == 0 || exit 1
],
[0],
[],
[ignore])
AT_CLEANUP

# ------------------------------
# Check if rpmbuild runs dwz and generates a multi file that with shared
# debuginfo. This is simply the hello example with one binary build twice
# so dwz has enough slightly similar debug data.
AT_SETUP([rpmbuild debuginfo dwz])
AT_KEYWORDS([build] [debuginfo])
AT_CHECK([
rm -rf ${TOPDIR}
AS_MKDIR_P(${TOPDIR}/SOURCES)

cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES

run rpmbuild --quiet \
  --macros=${abs_top_builddir}/macros:${abs_top_builddir}/tests/testing/usr/local/lib/rpm/platform/%{_target_cpu}-%{_target_os}/macros:${top_srcdir}/macros.debug \
  --rcfile=${abs_top_builddir}/rpmrc \
  -ba "${abs_srcdir}"/data/SPECS/hello2.spec

# The debuginfo package should contain a .debug file for each binary
# and a dwz multi file that contains the shared debuginfo between them.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \
  | cpio -diu
test -f ./usr/lib/debug/usr/local/bin/hello.debug || exit 1
test -f ./usr/lib/debug/usr/local/bin/hello2.debug || exit 1
test -f ./usr/lib/debug/.dwz/hello2-1.0-1.* || exit 1

# Make sure the main package binaries contain the correct build-ids
# linking them to the debug packages.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \
  | cpio -diu
id1=$(file ./usr/local/bin/hello | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2=$(file ./usr/local/bin/hello2 | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id1debug=$(file ./usr/lib/debug/usr/local/bin/hello.debug \
  | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
id2debug=$(file ./usr/lib/debug/usr/local/bin/hello2.debug \
  | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')
idmulti=$(file ./usr/lib/debug/.dwz/hello2-1.0-1.* \
  | sed 's/.*, BuildID[.*]=\(.*\),.*/\1/')

test "$id1" = "$id1debug" || exit 1
test "$id2" = "$id2debug" || exit 1

# The build-id files should link to the .debug files.
id1file="./usr/lib/debug/.build-id/${id1:0:2}/${id1:2}"
canonid1file=$(readlink -f ${id1file})
canonfile1=$(readlink -f ./usr/local/bin/hello)
canonid1debug=$(readlink -f ${id1file}.debug)
canondebug1=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug)

test "$canonid1file" = "$canonfile1" || exit 1
test "$canonid1debug" = "$canondebug1" || exit 1

id2file="./usr/lib/debug/.build-id/${id2:0:2}/${id2:2}"
canonid2file=$(readlink -f ${id1file})
canonfile2=$(readlink -f ./usr/local/bin/hello)
canonid2debug=$(readlink -f ${id1file}.debug)
canondebug2=$(readlink -f ./usr/lib/debug/usr/local/bin/hello.debug)

test "$canonid2file" = "$canonfile2" || exit 1
test "$canonid2debug" = "$canondebug2" || exit 1

# Both .debug files should point to the dwz multi file.
# It would be nice to also test that they contain the correct dwz build-id
# but that is a bit hard to grep out of the section data.
multiref1=$(readelf --string-dump=.gnu_debugaltlink ./usr/lib/debug/usr/local/bin/hello.debug | grep '[     0]' | cut -c13-)
multiref2=$(readelf --string-dump=.gnu_debugaltlink ./usr/lib/debug/usr/local/bin/hello2.debug | grep '[     0]' | cut -c13-)

test "$multiref1" = "$multiref2" || exit 1

canonmultiref=$(readlink -f $(dirname $canondebug1)/$multiref1)
canonmultifile=$(readlink -f ./usr/lib/debug/.dwz/hello2-1.0-1.*)

test "$canonmultiref" = "$canonmultifile" || exit 1
],
[0],
[],
[ignore])
AT_CLEANUP

# ------------------------------
# Check that old style gnu_debuglink CRC checksums are correct even after
# using dwz to compress the debuginfo files.
AT_SETUP([rpmbuild debuginfo dwz gnu_debuglink crc])
AT_KEYWORDS([build] [debuginfo])
AT_CHECK([
rm -rf ${TOPDIR}
AS_MKDIR_P(${TOPDIR}/SOURCES)

# Build a package that
cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES

run rpmbuild --quiet \
  --macros=${abs_top_builddir}/macros:${abs_top_builddir}/tests/testing/usr/local/lib/rpm/platform/%{_target_cpu}-%{_target_os}/macros:${top_srcdir}/macros.debug \
  --rcfile=${abs_top_builddir}/rpmrc \
  -ba "${abs_srcdir}"/data/SPECS/hello2.spec

# Unpack the main and debuginfo rpms so we can check binaries and .debug files.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-debuginfo-1.0-1.*.rpm \
  | cpio -diu
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \
  | cpio -diu

# Check that dwz has ran and a multi file has been produced
test -f ./usr/lib/debug/.dwz/hello2-1.0-1.* || exit 1

# Run sepdbugcrcfix on the binaries, both should have correct CRC already.
${abs_top_builddir}/sepdebugcrcfix ./usr/lib/debug \
  ./usr/local/bin/hello ./usr/local/bin/hello2 | grep CRC32 | cut -f2 -d:
],
[0],
[ Updated 0 CRC32s, 2 CRC32s did match.
],
[ignore])
AT_CLEANUP

# ------------------------------
# Check that an implicit suid binary get included with the suid bit set.
# We explicitly build with all debug.macros to test those helpers.
AT_SETUP([rpmbuild implicit suid binary])
AT_KEYWORDS([build] [debuginfo] [dwz] [suid])
AT_CHECK([
rm -rf ${TOPDIR}
AS_MKDIR_P(${TOPDIR}/SOURCES)

# Build a package that has some debuginfo
cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-modernize.patch ${TOPDIR}/SOURCES

run rpmbuild --quiet \
  --rcfile=${abs_top_builddir}/rpmrc \
  --macros=${abs_top_builddir}/macros:${abs_top_builddir}/tests/testing/usr/local/lib/rpm/platform/%{_target_cpu}-%{_target_os}/macros:${top_srcdir}/macros.debug \
  -ba "${abs_srcdir}"/data/SPECS/hello2-suid.spec

# Unpack rpm so we can check the included binaries.
rpm2cpio ${abs_builddir}/testing/build/RPMS/*/hello2-1.0-1.*.rpm \
  | cpio -diu --quiet

# List all binaries with suid bit set (should be one, hello).
echo "suid:"
find usr -executable -type f -perm /4000
# List all binaries without suid bit set (should also be one, hello2).
echo "no-suid:"
find usr -executable -type f \! -perm /4000
],
[0],
[suid:
usr/local/bin/hello
no-suid:
usr/local/bin/hello2
],
[ignore])
AT_CLEANUP
