#
# \brief  Test for using chroot on Linux
# \author Norman Feske
# \date   2012-06-06
#
#
if {![have_spec linux]} { puts "Run script requires Linux"; exit 0 }

#
# Build
#

build { core init drivers/timer test/timer
        server/loader test/chroot_loader }

if {[catch { exec which setcap }]} {
	puts stderr "Error: setcap not available, please install the libcap2-bin package"
	return 0
}

#
# Clean up remains of a potentially failed previous run
#

proc chroot_path     { id } { return "/tmp/chroot-test-$id" }
proc chroot_cwd_path { id } { return "[chroot_path $id][pwd]/[run_dir]" }

proc cleanup_chroot { } {

	foreach id { 1 2 } {
		umount_and_rmdir [chroot_cwd_path $id]
		umount_and_rmdir [chroot_path $id]/lib
		umount_and_rmdir [chroot_path $id]/lib64
	}
}

cleanup_chroot

create_boot_directory

#
# Generate config
#

set config {
	<config>
		<parent-provides>
			<service name="ROM"/>
			<service name="LOG"/>
			<service name="CAP"/>
			<service name="RAM"/>
			<service name="CPU"/>
			<service name="RM"/>
			<service name="PD"/>
			<service name="SIGNAL"/>
		</parent-provides>
		<default-route>
			<any-service> <parent/> <any-child/> </any-service>
		</default-route>
		<start name="timer">
			<resource name="RAM" quantum="1M"/>
			<provides><service name="Timer"/></provides>
		</start>
		<start name="loader">
			<resource name="RAM" quantum="1M"/>
			<provides><service name="Loader"/></provides>
		</start>
		<start name="test-chroot_loader">
			<resource name="RAM" quantum="32M"/>
			<config>
				<static_test  chroot_path="chroot_path_1" />
				<dynamic_test chroot_path="chroot_path_2" />
			</config>
		</start>
	</config>
}

# replace 'chroot_path' markers in config with actual paths
foreach id { 1 2 } {
	regsub "chroot_path_$id" $config [chroot_path $id] config }

install_config $config

#
# Copy boot modules into run directory
#
# We cannot use the predefined 'build_boot_image' function here because
# this would create mere symlinks. However, we want to hardlink the
# run directory into the chroot environment. If the directory entries
# were symlinks, those would point to nowhere within the chroot.
#
foreach binary { core init timer loader test-chroot_loader test-timer} {
	exec cp -H  bin/$binary [run_dir] }

#
# Grant chroot permission to 'core'
#
# CAP_SYS_ADMIN is needed for bind mounting genode runtime directories
# CAP_SYS_CHROOT is needed to perform the chroot syscall
#
exec sudo setcap cap_sys_admin,cap_sys_chroot=ep [run_dir]/core

#
# Setup chroot environment
#

# start with fresh directory
foreach id { 1 2 } {
	exec mkdir -p [chroot_path $id]
	exec mkdir -p [chroot_path $id]/lib
	exec mkdir -p [chroot_path $id]/lib64

	# bind mount '/lib' as need libc within the chroot environment
	exec sudo mount --bind /lib [chroot_path $id]/lib
	catch { exec sudo mount --bind /lib64 [chroot_path $id]/lib64 }
}

#
# Execute test case
#
run_genode_until {.*--- chroot-loader test finished ---\s*\n} 60

#
# Validate log output
#

if {[regexp -all -- {--- timer test ---} $output] != 6} {
	puts stderr "Number of spawned subsystems differs from 6"
	exit 2
}

if {![regexp -- {init-1 -> test-timer] Done 500 ms period 4 times} $output]} {
	puts stderr "Long-running timer test has made too little progress"
	exit 3
}

#
# Remove artifacts created while running the test
#
cleanup_chroot

puts "Test succeeded"

# vi: set ft=tcl :