#!/bin/bash
# -*- mode: sh; sh-basic-offset: 2; indent-tabs-mode: t; -*-
# vim:set ft=sh sw=2 ts=2:
#
# Test suite for 08-ipv6-prefix (NetworkManager functions)
#
# shellcheck disable=SC2034,SC1090,SC2123

NMG_XTEST=${NMG_XTEST:-conf/nmg_xtest}
{ [[ -r ${NMG_XTEST} ]] && . "${NMG_XTEST}"; } ||
  { echo >&2 "Unable to load ${NMG_XTEST}"; exit 2; }

xtest::onexit::wan() {
  [[ ${WAN_CONNSTATE_PAT-} ]] || return 0
  xrm "${WAN_CONNSTATE_PAT/@WAN@/wan0}"
}

xtest::group3::wan() {

  local out state1
  local -x DHCLIENT_MOCK_OUTPUT="dhclient @ARGS@"
  local -x PGREP_MOCK_OUTPUT="100"

  # pretend dhclient is running (using pgrep-mock)
  DHCLIENT_PID=${XFILE}

  shtest::title "WAN Dispatcher Tests (wan group)"

  local connid=9613d84e-2555-4e7f-a6c2-2a7da5f4d07b
  local interface=wan0 CONNECTION_UUID=${connid}
  state1=${WAN_CONNSTATE_PAT/@WAN@/wan0}
  xrm "$state1"

  local IP4_NUM_ADDRESSES=0 IP4_ADDRESS_0=''
  printf "" >>"${DHCLIENT_PID}"

  xwrap2 "<no ip>" ipv6_wan_start
  xtest W1 t "returns true"
  xread_value out <<-EOF
	No ip4 addresses available
	${DHCLIENT} => dhclient '-x' '-sf'\
 '${SRC_ROOT}/usr/lib/NetworkManager/dispatcher.d/08-ipv6-prefix'\
 '-pf' '${DHCLIENT_PID}' 'wan0'
	${NMCLI} => nmcli 'conn' 'modify' '--temporary' '${connid}'\
 'ipv6.method' 'link-local' 'ipv6.addresses' '' 'ipv6.dns' ''\
 'ipv6.dns-search' ''
	EOF
  ftest W1f "$out" "echos stop (config requires ip)"
  [[ -e ${DHCLIENT_PID} ]]
  xtest W1p f "pid file removed"
  [[ -e ${state1} ]]
  xtest W1s f "conn-state file not created"

  IP4_NUM_ADDRESSES=1 IP4_ADDRESS_0=192.168.55.1/24
  printf "" >>"${DHCLIENT_PID}"
  printf '%s\n' "conn-uuid:${connid}" >"$state1"

  xwrap2 "<priv ip>" ipv6_wan_start
  xtest W2 t "returns true"
  xread_value out <<-EOF
	No public ip4 addresses available
	${DHCLIENT} => dhclient '-x' '-sf'\
 '${SRC_ROOT}/usr/lib/NetworkManager/dispatcher.d/08-ipv6-prefix'\
 '-pf' '${DHCLIENT_PID}' 'wan0'
	${NMCLI} => nmcli 'conn' 'modify' '--temporary' '${connid}'\
 'ipv6.method' 'link-local' 'ipv6.addresses' '' 'ipv6.dns' ''\
 'ipv6.dns-search' ''
	EOF
  ftest W2f "$out" "echos stop (config requires public)"
  [[ -e ${DHCLIENT_PID} ]]
  xtest W2p f "pid file removed"
  [[ -e ${state1} ]]
  xtest W2s f "conn-state file removed"

  IP4_NUM_ADDRESSES=1 IP4_ADDRESS_0=203.0.113.5/24

  xwrap2 "<ip>" ipv6_wan_start
  xtest W3 t "returns true"
  if shtest::last_check_ok; then
    wait $!
    xtest W3w t "background echo completes"
  fi
  xread_value out <<-EOF
	dhclient '-P' '-N' '-nw' '-sf'\
 '${SRC_ROOT}/usr/lib/NetworkManager/dispatcher.d/08-ipv6-prefix'\
 '-pf' '${DHCLIENT_PID}' '-lf' '${LEASES/@WAN@/wan0}' 'wan0'
	EOF
  ftest W3f "$out" "echos start"
  shtest::check_file W3s "$state1" "conn-uuid:${connid}" "creates uuid file"

  printf "" >>"${DHCLIENT_PID}"

  xwrap2 "" ipv6_wan_stop
  xtest W11 t "returns true"
  xread_value out <<-EOF
	${DHCLIENT} => dhclient '-x' '-sf'\
 '${SRC_ROOT}/usr/lib/NetworkManager/dispatcher.d/08-ipv6-prefix'\
 '-pf' '${DHCLIENT_PID}' 'wan0'
	${NMCLI} => nmcli 'conn' 'modify' '--temporary' '${connid}'\
 'ipv6.method' 'link-local' 'ipv6.addresses' '' 'ipv6.dns' ''\
 'ipv6.dns-search' ''
	EOF
  ftest W11f "$out" "echos stop"
  [[ -e $state1 ]]
  xtest W11s f "removes state file"

  nmddns_reset_config
  ipv6_wan_reset_config
}

xtest::onexit::lan() {
  [[ ${LAN_STATE_PAT-} ]] || return 0
  local LAN_STATE_PAT="${LAN_STATE_PAT%-prefix}-prefix"
  xrm "${LAN_STATE_PAT/@LAN@-from-@ID@-@WAN@/br1-from-aa:1-wan1}"
  xrm "${LAN_STATE_PAT/@LAN@-from-@ID@-@WAN@/br1-from-bb:1-wan1}"
  xrm "${LAN_STATE_PAT/@LAN@-from-@ID@-@WAN@/br1-from-cc:2-wan2}"
  xrm "${LAN_DDNS_STATE_PAT/@LAN@-from-@WAN@-@RREC@/br1-from-wan1-AAAA}"
}

xtest::group3::lan() {
  local out state1 state2 state3 dstate1 CUR_TIME=''
  local -x DUMMY_MOCK_OUTPUT="radvd triggered"

  shtest::title "LAN Dispatcher Tests (lan group)"

  local interface=br1
  local LAN_STATE_PAT="${LAN_STATE_PAT}-prefix"

  state1=${LAN_STATE_PAT/@LAN@-from-@ID@-@WAN@/br1-from-aa:1-wan1}
  state2=${LAN_STATE_PAT/@LAN@-from-@ID@-@WAN@/br1-from-bb:1-wan1}
  state3=${LAN_STATE_PAT/@LAN@-from-@ID@-@WAN@/br1-from-cc:2-wan2}
  dstate1=${LAN_DDNS_STATE_PAT/@LAN@-from-@WAN@-@RREC@/br1-from-wan1-AAAA}
  xrm "$state1" "$state2" "$state3" "$dstate1"

  local FORWARDING_PAT=${XFILE}
  xrm "$XFILE"
  echo 1 > "$XFILE"

  echo "inet6:2001:db8:100:2:32fb:93c5:555:1/64" > "$state1"

  xwrap2 "<1 addr>" ipv6_lan_start
  xtest L1 t "returns true"
  xread_value out <<-EOF
	Replacing 2001:db8:100:2:32fb:93c5:555:1/64 on br1
	${NMG_IP} => ip '-6' 'addr' 'replace'\
 '2001:db8:100:2:32fb:93c5:555:1/64' 'dev' 'br1'
	Setting br1-w1.example.test AAAA to 2001:db8:100:2:32fb:93c5:555:1
	${NMDDNS_NSUPDATE} => nsupdate '-t' '2'
	server 127.0.0.1
	zone example.test
	update delete br1-w1.example.test AAAA
	update add br1-w1.example.test 600 AAAA 2001:db8:100:2:32fb:93c5:555:1
	send
	${NMG_RADVD_TRIGGER} => radvd triggered
	EOF
  ftest L1f "$out" "adds addr/dns"
  shtest::check_file L1d "$dstate1" "2001:db8:100:2:32fb:93c5:555:1" \
                     "DDNS state file created"

  xcat > "$state2" <<-EOF
	inet6:2001:db8:200:2:32fb:93c5:555:1/64
	valid-life:240
	pref-life:120
	life-start:3000
	EOF
  echo "inet6:2001:db8:600::1/64" > "$state3"
  # deprecate one address
  CUR_TIME=3200

  xwrap2 "<3 addrs, 1 dep>" ipv6_lan_start
  xtest L2 t "returns true"
  xread_value out <<-EOF
	Replacing 2001:db8:100:2:32fb:93c5:555:1/64 on br1
	${NMG_IP} => ip '-6' 'addr' 'replace'\
 '2001:db8:100:2:32fb:93c5:555:1/64' 'dev' 'br1'
	Replacing 2001:db8:200:2:32fb:93c5:555:1/64 on br1
	${NMG_IP} => ip '-6' 'addr' 'replace'\
 '2001:db8:200:2:32fb:93c5:555:1/64' 'dev' 'br1' 'valid_lft' '40'\
 'preferred_lft' '0'
	Adding 2001:db8:600::1/64 to br1
	${NMG_IP} => ip '-6' 'addr' 'add' '2001:db8:600::1/64' 'dev' 'br1'
	Setting br1-w1.example.test AAAA to 2001:db8:100:2:32fb:93c5:555:1
	${NMDDNS_NSUPDATE} => nsupdate '-t' '2'
	server 127.0.0.1
	zone example.test
	update delete br1-w1.example.test AAAA
	update add br1-w1.example.test 600 AAAA 2001:db8:100:2:32fb:93c5:555:1
	send
	${NMG_RADVD_TRIGGER} => radvd triggered
	EOF
  ftest L2f "$out" "adds addresses, dns"
  shtest::check_file L2d "$dstate1" "2001:db8:100:2:32fb:93c5:555:1" \
                     "DDNS state file created"

  xrm "$state3"
  echo "inet6:2001:db8:200:2::/64" >"$state2"

  xwrap2 "<prefix>" ipv6_lan_start
  xtest L3 t "returns true"
  xread_value out <<-EOF
	Replacing 2001:db8:100:2:32fb:93c5:555:1/64 on br1
	${NMG_IP} => ip '-6' 'addr' 'replace'\
 '2001:db8:100:2:32fb:93c5:555:1/64' 'dev' 'br1'
	Replacing 2001:db8:200:2:32fb:93c5:555:1/64 on br1
	${NMG_IP} => ip '-6' 'addr' 'replace'\
 '2001:db8:200:2:32fb:93c5:555:1/64' 'dev' 'br1'
	Setting br1-w1.example.test AAAA to\
 2001:db8:100:2:32fb:93c5:555:1,2001:db8:200:2:32fb:93c5:555:1
	${NMDDNS_NSUPDATE} => nsupdate '-t' '2'
	server 127.0.0.1
	zone example.test
	update delete br1-w1.example.test AAAA
	update add br1-w1.example.test 600 AAAA 2001:db8:100:2:32fb:93c5:555:1
	update add br1-w1.example.test 600 AAAA 2001:db8:200:2:32fb:93c5:555:1
	send
	${NMG_RADVD_TRIGGER} => radvd triggered
	EOF
  ftest L3f "$out" "adds addr/dns"
  shtest::check_file L3y "$state2" "inet6:2001:db8:200:2:32fb:93c5:555:1/64" \
                     "bb:1 state file updated"
  shtest::check_file \
    L3d "$dstate1"\
    "2001:db8:100:2:32fb:93c5:555:1,2001:db8:200:2:32fb:93c5:555:1" \
    "DDNS state file created"

  xwrap2 "" ipv6_lan_stop
  xtest L11 t "returns true"
  ftest L11f "${NMG_RADVD_TRIGGER} => radvd triggered" "triggers radvd"

  [[ -e "$state1" ]]
  xtest L11i t "aa:1 state file remains"
  [[ -e "$state2" ]]
  xtest L11j t "bb:1 state file remains"
  [[ -e "$dstate1" ]]
  xtest L11d f "DDNS state file removed"

  nmddns_reset_config
  ipv6_lan_reset_config
  ipv6_wan_reset_config
  xtest::onexit::lan
}

xtest::onexit() {
  xrm "${XFILE-}"
}

xmain() {
  local XFILE="$TEST_OUT/prefix file"
  local TEST_RADVD_TRIGGER="$TEST_BIN/dummy-mock"

  # disable helper so we get nsupdate results
  local TEST_DDNS_HELPER=''

  # don't load wan config by mistake
  unset interface

  xload_script "${SRC_ROOT}/usr/lib/NetworkManager/dispatcher.d/08-ipv6-prefix"

  xtest::run_tests "ipv6-prefix-nm-test Summary" "$@"
  local rc=$?

  xtest::onexit

  return $rc
}

xstart "$@"
